diff options
-rw-r--r-- | drivers/misc/tifm_7xx1.c | 28 | ||||
-rw-r--r-- | drivers/misc/tifm_core.c | 52 | ||||
-rw-r--r-- | include/linux/tifm.h | 16 |
3 files changed, 51 insertions, 45 deletions
diff --git a/drivers/misc/tifm_7xx1.c b/drivers/misc/tifm_7xx1.c index 34746798ba8e..e051f9da9c5c 100644 --- a/drivers/misc/tifm_7xx1.c +++ b/drivers/misc/tifm_7xx1.c | |||
@@ -22,6 +22,11 @@ | |||
22 | #define TIFM_IRQ_FIFOMASK(x) ((x) << 16) | 22 | #define TIFM_IRQ_FIFOMASK(x) ((x) << 16) |
23 | #define TIFM_IRQ_SETALL 0xffffffff | 23 | #define TIFM_IRQ_SETALL 0xffffffff |
24 | 24 | ||
25 | static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm, | ||
26 | struct tifm_dev *sock) | ||
27 | { | ||
28 | } | ||
29 | |||
25 | static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) | 30 | static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) |
26 | { | 31 | { |
27 | unsigned long flags; | 32 | unsigned long flags; |
@@ -140,7 +145,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work) | |||
140 | socket_change_set = fm->socket_change_set; | 145 | socket_change_set = fm->socket_change_set; |
141 | fm->socket_change_set = 0; | 146 | fm->socket_change_set = 0; |
142 | 147 | ||
143 | dev_dbg(fm->dev, "checking media set %x\n", | 148 | dev_dbg(fm->cdev.dev, "checking media set %x\n", |
144 | socket_change_set); | 149 | socket_change_set); |
145 | 150 | ||
146 | if (!socket_change_set) { | 151 | if (!socket_change_set) { |
@@ -328,20 +333,13 @@ static int tifm_7xx1_probe(struct pci_dev *dev, | |||
328 | 333 | ||
329 | pci_intx(dev, 1); | 334 | pci_intx(dev, 1); |
330 | 335 | ||
331 | fm = tifm_alloc_adapter(); | 336 | fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM |
337 | ? 4 : 2, &dev->dev); | ||
332 | if (!fm) { | 338 | if (!fm) { |
333 | rc = -ENOMEM; | 339 | rc = -ENOMEM; |
334 | goto err_out_int; | 340 | goto err_out_int; |
335 | } | 341 | } |
336 | 342 | ||
337 | fm->dev = &dev->dev; | ||
338 | fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM) | ||
339 | ? 4 : 2; | ||
340 | fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets, | ||
341 | GFP_KERNEL); | ||
342 | if (!fm->sockets) | ||
343 | goto err_out_free; | ||
344 | |||
345 | INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media); | 343 | INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media); |
346 | fm->eject = tifm_7xx1_eject; | 344 | fm->eject = tifm_7xx1_eject; |
347 | pci_set_drvdata(dev, fm); | 345 | pci_set_drvdata(dev, fm); |
@@ -351,7 +349,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev, | |||
351 | if (!fm->addr) | 349 | if (!fm->addr) |
352 | goto err_out_free; | 350 | goto err_out_free; |
353 | 351 | ||
354 | rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm); | 352 | rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm); |
355 | if (rc) | 353 | if (rc) |
356 | goto err_out_unmap; | 354 | goto err_out_unmap; |
357 | 355 | ||
@@ -359,10 +357,8 @@ static int tifm_7xx1_probe(struct pci_dev *dev, | |||
359 | if (rc) | 357 | if (rc) |
360 | goto err_out_irq; | 358 | goto err_out_irq; |
361 | 359 | ||
362 | writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | ||
363 | writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), | 360 | writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), |
364 | fm->addr + FM_SET_INTERRUPT_ENABLE); | 361 | fm->addr + FM_SET_INTERRUPT_ENABLE); |
365 | |||
366 | return 0; | 362 | return 0; |
367 | 363 | ||
368 | err_out_irq: | 364 | err_out_irq: |
@@ -384,16 +380,12 @@ err_out: | |||
384 | static void tifm_7xx1_remove(struct pci_dev *dev) | 380 | static void tifm_7xx1_remove(struct pci_dev *dev) |
385 | { | 381 | { |
386 | struct tifm_adapter *fm = pci_get_drvdata(dev); | 382 | struct tifm_adapter *fm = pci_get_drvdata(dev); |
387 | unsigned long flags; | ||
388 | 383 | ||
384 | fm->eject = tifm_7xx1_dummy_eject; | ||
389 | writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); | 385 | writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); |
390 | mmiowb(); | 386 | mmiowb(); |
391 | free_irq(dev->irq, fm); | 387 | free_irq(dev->irq, fm); |
392 | 388 | ||
393 | spin_lock_irqsave(&fm->lock, flags); | ||
394 | fm->socket_change_set = (1 << fm->num_sockets) - 1; | ||
395 | spin_unlock_irqrestore(&fm->lock, flags); | ||
396 | |||
397 | tifm_remove_adapter(fm); | 389 | tifm_remove_adapter(fm); |
398 | 390 | ||
399 | pci_set_drvdata(dev, NULL); | 391 | pci_set_drvdata(dev, NULL); |
diff --git a/drivers/misc/tifm_core.c b/drivers/misc/tifm_core.c index ef8a97b819dd..f0cce2a642df 100644 --- a/drivers/misc/tifm_core.c +++ b/drivers/misc/tifm_core.c | |||
@@ -156,7 +156,6 @@ static void tifm_free(struct class_device *cdev) | |||
156 | { | 156 | { |
157 | struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev); | 157 | struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev); |
158 | 158 | ||
159 | kfree(fm->sockets); | ||
160 | kfree(fm); | 159 | kfree(fm); |
161 | } | 160 | } |
162 | 161 | ||
@@ -165,26 +164,24 @@ static struct class tifm_adapter_class = { | |||
165 | .release = tifm_free | 164 | .release = tifm_free |
166 | }; | 165 | }; |
167 | 166 | ||
168 | struct tifm_adapter *tifm_alloc_adapter(void) | 167 | struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets, |
168 | struct device *dev) | ||
169 | { | 169 | { |
170 | struct tifm_adapter *fm; | 170 | struct tifm_adapter *fm; |
171 | 171 | ||
172 | fm = kzalloc(sizeof(struct tifm_adapter), GFP_KERNEL); | 172 | fm = kzalloc(sizeof(struct tifm_adapter) |
173 | + sizeof(struct tifm_dev*) * num_sockets, GFP_KERNEL); | ||
173 | if (fm) { | 174 | if (fm) { |
174 | fm->cdev.class = &tifm_adapter_class; | 175 | fm->cdev.class = &tifm_adapter_class; |
175 | spin_lock_init(&fm->lock); | 176 | fm->cdev.dev = dev; |
176 | class_device_initialize(&fm->cdev); | 177 | class_device_initialize(&fm->cdev); |
178 | spin_lock_init(&fm->lock); | ||
179 | fm->num_sockets = num_sockets; | ||
177 | } | 180 | } |
178 | return fm; | 181 | return fm; |
179 | } | 182 | } |
180 | EXPORT_SYMBOL(tifm_alloc_adapter); | 183 | EXPORT_SYMBOL(tifm_alloc_adapter); |
181 | 184 | ||
182 | void tifm_free_adapter(struct tifm_adapter *fm) | ||
183 | { | ||
184 | class_device_put(&fm->cdev); | ||
185 | } | ||
186 | EXPORT_SYMBOL(tifm_free_adapter); | ||
187 | |||
188 | int tifm_add_adapter(struct tifm_adapter *fm) | 185 | int tifm_add_adapter(struct tifm_adapter *fm) |
189 | { | 186 | { |
190 | int rc; | 187 | int rc; |
@@ -195,31 +192,44 @@ int tifm_add_adapter(struct tifm_adapter *fm) | |||
195 | spin_lock(&tifm_adapter_lock); | 192 | spin_lock(&tifm_adapter_lock); |
196 | rc = idr_get_new(&tifm_adapter_idr, fm, &fm->id); | 193 | rc = idr_get_new(&tifm_adapter_idr, fm, &fm->id); |
197 | spin_unlock(&tifm_adapter_lock); | 194 | spin_unlock(&tifm_adapter_lock); |
198 | if (!rc) { | 195 | if (rc) |
199 | snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id); | 196 | return rc; |
200 | rc = class_device_add(&fm->cdev); | 197 | |
201 | 198 | snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id); | |
202 | if (rc) { | 199 | rc = class_device_add(&fm->cdev); |
203 | spin_lock(&tifm_adapter_lock); | 200 | if (rc) { |
204 | idr_remove(&tifm_adapter_idr, fm->id); | 201 | spin_lock(&tifm_adapter_lock); |
205 | spin_unlock(&tifm_adapter_lock); | 202 | idr_remove(&tifm_adapter_idr, fm->id); |
206 | } | 203 | spin_unlock(&tifm_adapter_lock); |
207 | } | 204 | } |
205 | |||
208 | return rc; | 206 | return rc; |
209 | } | 207 | } |
210 | EXPORT_SYMBOL(tifm_add_adapter); | 208 | EXPORT_SYMBOL(tifm_add_adapter); |
211 | 209 | ||
212 | void tifm_remove_adapter(struct tifm_adapter *fm) | 210 | void tifm_remove_adapter(struct tifm_adapter *fm) |
213 | { | 211 | { |
212 | unsigned int cnt; | ||
213 | |||
214 | flush_workqueue(workqueue); | 214 | flush_workqueue(workqueue); |
215 | class_device_del(&fm->cdev); | 215 | for (cnt = 0; cnt < fm->num_sockets; ++cnt) { |
216 | if (fm->sockets[cnt]) | ||
217 | device_unregister(&fm->sockets[cnt]->dev); | ||
218 | } | ||
216 | 219 | ||
217 | spin_lock(&tifm_adapter_lock); | 220 | spin_lock(&tifm_adapter_lock); |
218 | idr_remove(&tifm_adapter_idr, fm->id); | 221 | idr_remove(&tifm_adapter_idr, fm->id); |
219 | spin_unlock(&tifm_adapter_lock); | 222 | spin_unlock(&tifm_adapter_lock); |
223 | class_device_del(&fm->cdev); | ||
220 | } | 224 | } |
221 | EXPORT_SYMBOL(tifm_remove_adapter); | 225 | EXPORT_SYMBOL(tifm_remove_adapter); |
222 | 226 | ||
227 | void tifm_free_adapter(struct tifm_adapter *fm) | ||
228 | { | ||
229 | class_device_put(&fm->cdev); | ||
230 | } | ||
231 | EXPORT_SYMBOL(tifm_free_adapter); | ||
232 | |||
223 | void tifm_free_device(struct device *dev) | 233 | void tifm_free_device(struct device *dev) |
224 | { | 234 | { |
225 | struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); | 235 | struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); |
@@ -234,7 +244,7 @@ struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm) | |||
234 | if (dev) { | 244 | if (dev) { |
235 | spin_lock_init(&dev->lock); | 245 | spin_lock_init(&dev->lock); |
236 | 246 | ||
237 | dev->dev.parent = fm->dev; | 247 | dev->dev.parent = fm->cdev.dev; |
238 | dev->dev.bus = &tifm_bus_type; | 248 | dev->dev.bus = &tifm_bus_type; |
239 | dev->dev.release = tifm_free_device; | 249 | dev->dev.release = tifm_free_device; |
240 | dev->card_event = tifm_dummy_event; | 250 | dev->card_event = tifm_dummy_event; |
diff --git a/include/linux/tifm.h b/include/linux/tifm.h index d9de79275c21..a7bd654e2ee5 100644 --- a/include/linux/tifm.h +++ b/include/linux/tifm.h | |||
@@ -114,19 +114,23 @@ struct tifm_adapter { | |||
114 | unsigned int id; | 114 | unsigned int id; |
115 | unsigned int num_sockets; | 115 | unsigned int num_sockets; |
116 | struct completion *finish_me; | 116 | struct completion *finish_me; |
117 | struct tifm_dev **sockets; | 117 | |
118 | struct work_struct media_switcher; | 118 | struct work_struct media_switcher; |
119 | struct class_device cdev; | 119 | struct class_device cdev; |
120 | struct device *dev; | ||
121 | 120 | ||
122 | void (*eject)(struct tifm_adapter *fm, struct tifm_dev *sock); | 121 | void (*eject)(struct tifm_adapter *fm, |
122 | struct tifm_dev *sock); | ||
123 | |||
124 | struct tifm_dev *sockets[0]; | ||
123 | }; | 125 | }; |
124 | 126 | ||
125 | struct tifm_adapter *tifm_alloc_adapter(void); | 127 | struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets, |
126 | void tifm_free_device(struct device *dev); | 128 | struct device *dev); |
127 | void tifm_free_adapter(struct tifm_adapter *fm); | ||
128 | int tifm_add_adapter(struct tifm_adapter *fm); | 129 | int tifm_add_adapter(struct tifm_adapter *fm); |
129 | void tifm_remove_adapter(struct tifm_adapter *fm); | 130 | void tifm_remove_adapter(struct tifm_adapter *fm); |
131 | void tifm_free_adapter(struct tifm_adapter *fm); | ||
132 | |||
133 | void tifm_free_device(struct device *dev); | ||
130 | struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm); | 134 | struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm); |
131 | int tifm_register_driver(struct tifm_driver *drv); | 135 | int tifm_register_driver(struct tifm_driver *drv); |
132 | void tifm_unregister_driver(struct tifm_driver *drv); | 136 | void tifm_unregister_driver(struct tifm_driver *drv); |