aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/misc/tifm_7xx1.c28
-rw-r--r--drivers/misc/tifm_core.c52
-rw-r--r--include/linux/tifm.h16
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
25static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm,
26 struct tifm_dev *sock)
27{
28}
29
25static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) 30static 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
368err_out_irq: 364err_out_irq:
@@ -384,16 +380,12 @@ err_out:
384static void tifm_7xx1_remove(struct pci_dev *dev) 380static 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
168struct tifm_adapter *tifm_alloc_adapter(void) 167struct 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}
180EXPORT_SYMBOL(tifm_alloc_adapter); 183EXPORT_SYMBOL(tifm_alloc_adapter);
181 184
182void tifm_free_adapter(struct tifm_adapter *fm)
183{
184 class_device_put(&fm->cdev);
185}
186EXPORT_SYMBOL(tifm_free_adapter);
187
188int tifm_add_adapter(struct tifm_adapter *fm) 185int 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}
210EXPORT_SYMBOL(tifm_add_adapter); 208EXPORT_SYMBOL(tifm_add_adapter);
211 209
212void tifm_remove_adapter(struct tifm_adapter *fm) 210void 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}
221EXPORT_SYMBOL(tifm_remove_adapter); 225EXPORT_SYMBOL(tifm_remove_adapter);
222 226
227void tifm_free_adapter(struct tifm_adapter *fm)
228{
229 class_device_put(&fm->cdev);
230}
231EXPORT_SYMBOL(tifm_free_adapter);
232
223void tifm_free_device(struct device *dev) 233void 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
125struct tifm_adapter *tifm_alloc_adapter(void); 127struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
126void tifm_free_device(struct device *dev); 128 struct device *dev);
127void tifm_free_adapter(struct tifm_adapter *fm);
128int tifm_add_adapter(struct tifm_adapter *fm); 129int tifm_add_adapter(struct tifm_adapter *fm);
129void tifm_remove_adapter(struct tifm_adapter *fm); 130void tifm_remove_adapter(struct tifm_adapter *fm);
131void tifm_free_adapter(struct tifm_adapter *fm);
132
133void tifm_free_device(struct device *dev);
130struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm); 134struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm);
131int tifm_register_driver(struct tifm_driver *drv); 135int tifm_register_driver(struct tifm_driver *drv);
132void tifm_unregister_driver(struct tifm_driver *drv); 136void tifm_unregister_driver(struct tifm_driver *drv);