38
38
#include <linux/pci.h>
39
39
#include <linux/arcdevice.h>
40
40
#include <linux/com20020.h>
41
+ #include <linux/list.h>
41
42
42
43
#include <asm/io.h>
43
44
@@ -61,85 +62,125 @@ module_param(clockp, int, 0);
61
62
module_param (clockm , int , 0 );
62
63
MODULE_LICENSE ("GPL" );
63
64
65
+ static void com20020pci_remove (struct pci_dev * pdev );
66
+
64
67
static int com20020pci_probe (struct pci_dev * pdev , const struct pci_device_id * id )
65
68
{
66
- struct com20020_pci_channel_map * cm ;
67
69
struct com20020_pci_card_info * ci ;
68
70
struct net_device * dev ;
69
71
struct arcnet_local * lp ;
70
- int ioaddr , err ;
72
+ struct com20020_priv * priv ;
73
+ int i , ioaddr , ret ;
74
+ struct resource * r ;
71
75
72
76
if (pci_enable_device (pdev ))
73
77
return - EIO ;
74
- dev = alloc_arcdev (device );
75
- if (!dev )
76
- return - ENOMEM ;
77
-
78
- dev -> netdev_ops = & com20020_netdev_ops ;
79
78
79
+ priv = devm_kzalloc (& pdev -> dev , sizeof (struct com20020_priv ),
80
+ GFP_KERNEL );
80
81
ci = (struct com20020_pci_card_info * )id -> driver_data ;
82
+ priv -> ci = ci ;
81
83
82
- lp = netdev_priv ( dev );
84
+ INIT_LIST_HEAD ( & priv -> list_dev );
83
85
84
- pci_set_drvdata (pdev , dev );
85
86
86
- cm = & ci -> chan_map_tbl [ 0 ];
87
- BUGMSG ( D_NORMAL , "%s Controls\n" , ci -> name ) ;
88
- ioaddr = pci_resource_start ( pdev , cm -> bar ) ;
87
+ for ( i = 0 ; i < ci -> devcount ; i ++ ) {
88
+ struct com20020_pci_channel_map * cm = & ci -> chan_map_tbl [ i ] ;
89
+ struct com20020_dev * card ;
89
90
90
- if (!request_region (ioaddr , ARCNET_TOTAL_SIZE , "com20020-pci" )) {
91
- BUGMSG (D_INIT , "IO region %xh-%xh already allocated.\n" ,
92
- ioaddr , ioaddr + ARCNET_TOTAL_SIZE - 1 );
93
- err = - EBUSY ;
94
- goto out_dev ;
95
- }
91
+ dev = alloc_arcdev (device );
92
+ if (!dev ) {
93
+ ret = - ENOMEM ;
94
+ goto out_port ;
95
+ }
96
96
97
- // Dummy access after Reset
98
- // ARCNET controller needs this access to detect bustype
99
- outb (0x00 ,ioaddr + 1 );
100
- inb (ioaddr + 1 );
101
-
102
- dev -> base_addr = ioaddr ;
103
- dev -> irq = pdev -> irq ;
104
- dev -> dev_addr [0 ] = node ;
105
- lp -> card_name = "PCI COM20020" ;
106
- lp -> card_flags = ci -> flags ;
107
- lp -> backplane = backplane ;
108
- lp -> clockp = clockp & 7 ;
109
- lp -> clockm = clockm & 3 ;
110
- lp -> timeout = timeout ;
111
- lp -> hw .owner = THIS_MODULE ;
112
-
113
- if (ASTATUS () == 0xFF ) {
114
- BUGMSG (D_NORMAL , "IO address %Xh was reported by PCI BIOS, "
115
- "but seems empty!\n" , ioaddr );
116
- err = - EIO ;
117
- goto out_port ;
118
- }
119
- if (com20020_check (dev )) {
120
- err = - EIO ;
121
- goto out_port ;
97
+ dev -> netdev_ops = & com20020_netdev_ops ;
98
+
99
+ lp = netdev_priv (dev );
100
+
101
+ BUGMSG (D_NORMAL , "%s Controls\n" , ci -> name );
102
+ ioaddr = pci_resource_start (pdev , cm -> bar ) + cm -> offset ;
103
+
104
+ r = devm_request_region (& pdev -> dev , ioaddr , cm -> size ,
105
+ "com20020-pci" );
106
+ if (!r ) {
107
+ pr_err ("IO region %xh-%xh already allocated.\n" ,
108
+ ioaddr , ioaddr + cm -> size - 1 );
109
+ ret = - EBUSY ;
110
+ goto out_port ;
111
+ }
112
+
113
+ /* Dummy access after Reset
114
+ * ARCNET controller needs
115
+ * this access to detect bustype
116
+ */
117
+ outb (0x00 , ioaddr + 1 );
118
+ inb (ioaddr + 1 );
119
+
120
+ dev -> base_addr = ioaddr ;
121
+ dev -> dev_addr [0 ] = node ;
122
+ dev -> irq = pdev -> irq ;
123
+ lp -> card_name = "PCI COM20020" ;
124
+ lp -> card_flags = ci -> flags ;
125
+ lp -> backplane = backplane ;
126
+ lp -> clockp = clockp & 7 ;
127
+ lp -> clockm = clockm & 3 ;
128
+ lp -> timeout = timeout ;
129
+ lp -> hw .owner = THIS_MODULE ;
130
+
131
+ if (ASTATUS () == 0xFF ) {
132
+ pr_err ("IO address %Xh is empty!\n" , ioaddr );
133
+ ret = - EIO ;
134
+ goto out_port ;
135
+ }
136
+ if (com20020_check (dev )) {
137
+ ret = - EIO ;
138
+ goto out_port ;
139
+ }
140
+
141
+ card = devm_kzalloc (& pdev -> dev , sizeof (struct com20020_dev ),
142
+ GFP_KERNEL );
143
+ if (!card ) {
144
+ pr_err ("%s out of memory!\n" , __func__ );
145
+ return - ENOMEM ;
146
+ }
147
+
148
+ card -> index = i ;
149
+ card -> pci_priv = priv ;
150
+ card -> dev = dev ;
151
+
152
+ dev_set_drvdata (& dev -> dev , card );
153
+
154
+ ret = com20020_found (dev , IRQF_SHARED );
155
+ if (ret )
156
+ goto out_port ;
157
+
158
+ list_add (& card -> list , & priv -> list_dev );
122
159
}
123
160
124
- if ((err = com20020_found (dev , IRQF_SHARED )) != 0 )
125
- goto out_port ;
161
+ pci_set_drvdata (pdev , priv );
126
162
127
163
return 0 ;
128
164
129
165
out_port :
130
- release_region (ioaddr , ARCNET_TOTAL_SIZE );
131
- out_dev :
132
- free_netdev (dev );
133
- return err ;
166
+ com20020pci_remove (pdev );
167
+ return ret ;
134
168
}
135
169
136
170
static void com20020pci_remove (struct pci_dev * pdev )
137
171
{
138
- struct net_device * dev = pci_get_drvdata (pdev );
139
- unregister_netdev (dev );
140
- free_irq (dev -> irq , dev );
141
- release_region (dev -> base_addr , ARCNET_TOTAL_SIZE );
142
- free_netdev (dev );
172
+ struct com20020_dev * card , * tmpcard ;
173
+ struct com20020_priv * priv ;
174
+
175
+ priv = pci_get_drvdata (pdev );
176
+
177
+ list_for_each_entry_safe (card , tmpcard , & priv -> list_dev , list ) {
178
+ struct net_device * dev = card -> dev ;
179
+
180
+ unregister_netdev (dev );
181
+ free_irq (dev -> irq , dev );
182
+ free_netdev (dev );
183
+ }
143
184
}
144
185
145
186
static struct com20020_pci_card_info card_info_10mbit = {
0 commit comments