tifm: move common adapter management tasks from tifm_7xx1 to tifm_core

Some details of the adapter management (create, add, remove) are really
belong to the tifm_core, as they are not hardware specific.

Signed-off-by: Alex Dubov <oakad@yahoo.com>
Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
This commit is contained in:
Alex Dubov 2007-04-12 16:59:17 +10:00 committed by Pierre Ossman
parent 342c0ec485
commit 6113ed73e6
3 changed files with 50 additions and 44 deletions

View File

@ -22,6 +22,11 @@
#define TIFM_IRQ_FIFOMASK(x) ((x) << 16) #define TIFM_IRQ_FIFOMASK(x) ((x) << 16)
#define TIFM_IRQ_SETALL 0xffffffff #define TIFM_IRQ_SETALL 0xffffffff
static void tifm_7xx1_dummy_eject(struct tifm_adapter *fm,
struct tifm_dev *sock)
{
}
static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock) static void tifm_7xx1_eject(struct tifm_adapter *fm, struct tifm_dev *sock)
{ {
unsigned long flags; unsigned long flags;
@ -140,7 +145,7 @@ static void tifm_7xx1_switch_media(struct work_struct *work)
socket_change_set = fm->socket_change_set; socket_change_set = fm->socket_change_set;
fm->socket_change_set = 0; fm->socket_change_set = 0;
dev_dbg(fm->dev, "checking media set %x\n", dev_dbg(fm->cdev.dev, "checking media set %x\n",
socket_change_set); socket_change_set);
if (!socket_change_set) { if (!socket_change_set) {
@ -328,20 +333,13 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
pci_intx(dev, 1); pci_intx(dev, 1);
fm = tifm_alloc_adapter(); fm = tifm_alloc_adapter(dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM
? 4 : 2, &dev->dev);
if (!fm) { if (!fm) {
rc = -ENOMEM; rc = -ENOMEM;
goto err_out_int; goto err_out_int;
} }
fm->dev = &dev->dev;
fm->num_sockets = (dev->device == PCI_DEVICE_ID_TI_XX21_XX11_FM)
? 4 : 2;
fm->sockets = kzalloc(sizeof(struct tifm_dev*) * fm->num_sockets,
GFP_KERNEL);
if (!fm->sockets)
goto err_out_free;
INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media); INIT_WORK(&fm->media_switcher, tifm_7xx1_switch_media);
fm->eject = tifm_7xx1_eject; fm->eject = tifm_7xx1_eject;
pci_set_drvdata(dev, fm); pci_set_drvdata(dev, fm);
@ -351,7 +349,7 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
if (!fm->addr) if (!fm->addr)
goto err_out_free; goto err_out_free;
rc = request_irq(dev->irq, tifm_7xx1_isr, IRQF_SHARED, DRIVER_NAME, fm); rc = request_irq(dev->irq, tifm_7xx1_isr, SA_SHIRQ, DRIVER_NAME, fm);
if (rc) if (rc)
goto err_out_unmap; goto err_out_unmap;
@ -359,10 +357,8 @@ static int tifm_7xx1_probe(struct pci_dev *dev,
if (rc) if (rc)
goto err_out_irq; goto err_out_irq;
writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1), writel(TIFM_IRQ_ENABLE | TIFM_IRQ_SOCKMASK((1 << fm->num_sockets) - 1),
fm->addr + FM_SET_INTERRUPT_ENABLE); fm->addr + FM_SET_INTERRUPT_ENABLE);
return 0; return 0;
err_out_irq: err_out_irq:
@ -384,16 +380,12 @@ err_out:
static void tifm_7xx1_remove(struct pci_dev *dev) static void tifm_7xx1_remove(struct pci_dev *dev)
{ {
struct tifm_adapter *fm = pci_get_drvdata(dev); struct tifm_adapter *fm = pci_get_drvdata(dev);
unsigned long flags;
fm->eject = tifm_7xx1_dummy_eject;
writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE); writel(TIFM_IRQ_SETALL, fm->addr + FM_CLEAR_INTERRUPT_ENABLE);
mmiowb(); mmiowb();
free_irq(dev->irq, fm); free_irq(dev->irq, fm);
spin_lock_irqsave(&fm->lock, flags);
fm->socket_change_set = (1 << fm->num_sockets) - 1;
spin_unlock_irqrestore(&fm->lock, flags);
tifm_remove_adapter(fm); tifm_remove_adapter(fm);
pci_set_drvdata(dev, NULL); pci_set_drvdata(dev, NULL);

View File

@ -156,7 +156,6 @@ static void tifm_free(struct class_device *cdev)
{ {
struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev); struct tifm_adapter *fm = container_of(cdev, struct tifm_adapter, cdev);
kfree(fm->sockets);
kfree(fm); kfree(fm);
} }
@ -165,26 +164,24 @@ static struct class tifm_adapter_class = {
.release = tifm_free .release = tifm_free
}; };
struct tifm_adapter *tifm_alloc_adapter(void) struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
struct device *dev)
{ {
struct tifm_adapter *fm; struct tifm_adapter *fm;
fm = kzalloc(sizeof(struct tifm_adapter), GFP_KERNEL); fm = kzalloc(sizeof(struct tifm_adapter)
+ sizeof(struct tifm_dev*) * num_sockets, GFP_KERNEL);
if (fm) { if (fm) {
fm->cdev.class = &tifm_adapter_class; fm->cdev.class = &tifm_adapter_class;
spin_lock_init(&fm->lock); fm->cdev.dev = dev;
class_device_initialize(&fm->cdev); class_device_initialize(&fm->cdev);
spin_lock_init(&fm->lock);
fm->num_sockets = num_sockets;
} }
return fm; return fm;
} }
EXPORT_SYMBOL(tifm_alloc_adapter); EXPORT_SYMBOL(tifm_alloc_adapter);
void tifm_free_adapter(struct tifm_adapter *fm)
{
class_device_put(&fm->cdev);
}
EXPORT_SYMBOL(tifm_free_adapter);
int tifm_add_adapter(struct tifm_adapter *fm) int tifm_add_adapter(struct tifm_adapter *fm)
{ {
int rc; int rc;
@ -195,31 +192,44 @@ int tifm_add_adapter(struct tifm_adapter *fm)
spin_lock(&tifm_adapter_lock); spin_lock(&tifm_adapter_lock);
rc = idr_get_new(&tifm_adapter_idr, fm, &fm->id); rc = idr_get_new(&tifm_adapter_idr, fm, &fm->id);
spin_unlock(&tifm_adapter_lock); spin_unlock(&tifm_adapter_lock);
if (!rc) { if (rc)
snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id); return rc;
rc = class_device_add(&fm->cdev);
if (rc) { snprintf(fm->cdev.class_id, BUS_ID_SIZE, "tifm%u", fm->id);
spin_lock(&tifm_adapter_lock); rc = class_device_add(&fm->cdev);
idr_remove(&tifm_adapter_idr, fm->id); if (rc) {
spin_unlock(&tifm_adapter_lock); spin_lock(&tifm_adapter_lock);
} idr_remove(&tifm_adapter_idr, fm->id);
spin_unlock(&tifm_adapter_lock);
} }
return rc; return rc;
} }
EXPORT_SYMBOL(tifm_add_adapter); EXPORT_SYMBOL(tifm_add_adapter);
void tifm_remove_adapter(struct tifm_adapter *fm) void tifm_remove_adapter(struct tifm_adapter *fm)
{ {
unsigned int cnt;
flush_workqueue(workqueue); flush_workqueue(workqueue);
class_device_del(&fm->cdev); for (cnt = 0; cnt < fm->num_sockets; ++cnt) {
if (fm->sockets[cnt])
device_unregister(&fm->sockets[cnt]->dev);
}
spin_lock(&tifm_adapter_lock); spin_lock(&tifm_adapter_lock);
idr_remove(&tifm_adapter_idr, fm->id); idr_remove(&tifm_adapter_idr, fm->id);
spin_unlock(&tifm_adapter_lock); spin_unlock(&tifm_adapter_lock);
class_device_del(&fm->cdev);
} }
EXPORT_SYMBOL(tifm_remove_adapter); EXPORT_SYMBOL(tifm_remove_adapter);
void tifm_free_adapter(struct tifm_adapter *fm)
{
class_device_put(&fm->cdev);
}
EXPORT_SYMBOL(tifm_free_adapter);
void tifm_free_device(struct device *dev) void tifm_free_device(struct device *dev)
{ {
struct tifm_dev *fm_dev = container_of(dev, struct tifm_dev, dev); 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)
if (dev) { if (dev) {
spin_lock_init(&dev->lock); spin_lock_init(&dev->lock);
dev->dev.parent = fm->dev; dev->dev.parent = fm->cdev.dev;
dev->dev.bus = &tifm_bus_type; dev->dev.bus = &tifm_bus_type;
dev->dev.release = tifm_free_device; dev->dev.release = tifm_free_device;
dev->card_event = tifm_dummy_event; dev->card_event = tifm_dummy_event;

View File

@ -114,19 +114,23 @@ struct tifm_adapter {
unsigned int id; unsigned int id;
unsigned int num_sockets; unsigned int num_sockets;
struct completion *finish_me; struct completion *finish_me;
struct tifm_dev **sockets;
struct work_struct media_switcher; struct work_struct media_switcher;
struct class_device cdev; struct class_device cdev;
struct device *dev;
void (*eject)(struct tifm_adapter *fm, struct tifm_dev *sock); void (*eject)(struct tifm_adapter *fm,
struct tifm_dev *sock);
struct tifm_dev *sockets[0];
}; };
struct tifm_adapter *tifm_alloc_adapter(void); struct tifm_adapter *tifm_alloc_adapter(unsigned int num_sockets,
void tifm_free_device(struct device *dev); struct device *dev);
void tifm_free_adapter(struct tifm_adapter *fm);
int tifm_add_adapter(struct tifm_adapter *fm); int tifm_add_adapter(struct tifm_adapter *fm);
void tifm_remove_adapter(struct tifm_adapter *fm); void tifm_remove_adapter(struct tifm_adapter *fm);
void tifm_free_adapter(struct tifm_adapter *fm);
void tifm_free_device(struct device *dev);
struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm); struct tifm_dev *tifm_alloc_device(struct tifm_adapter *fm);
int tifm_register_driver(struct tifm_driver *drv); int tifm_register_driver(struct tifm_driver *drv);
void tifm_unregister_driver(struct tifm_driver *drv); void tifm_unregister_driver(struct tifm_driver *drv);