Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 71a380d6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'hysdn' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6

* 'hysdn' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6:
  [ISDN] hysdn: convert to PCI hotplug API
parents 408af0da 60cc5147
Loading
Loading
Loading
Loading
+130 −144
Original line number Diff line number Diff line
@@ -20,10 +20,15 @@
#include "hysdn_defs.h"

static struct pci_device_id hysdn_pci_tbl[] = {
	{PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO},
	{PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2},
	{PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO},
	{PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX, PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO},
	{ PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
	  PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_METRO, 0, 0, BD_METRO },
	{ PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
	  PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, 0, 0, BD_CHAMP2 },
	{ PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
	  PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, 0, 0, BD_ERGO },
	{ PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
	  PCI_ANY_ID, PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, 0, 0, BD_ERGO },

	{ }				/* Terminating entry */
};
MODULE_DEVICE_TABLE(pci, hysdn_pci_tbl);
@@ -34,56 +39,57 @@ MODULE_LICENSE("GPL");
static char *hysdn_init_revision = "$Revision: 1.6.6.6 $";
static int cardmax;		/* number of found cards */
hysdn_card *card_root = NULL;	/* pointer to first card */
static hysdn_card *card_last = NULL;	/* pointer to first card */

/**********************************************/
/* table assigning PCI-sub ids to board types */
/* the last entry contains all 0              */
/**********************************************/
static struct {
	unsigned short subid;		/* PCI sub id */
	unsigned char cardtyp;		/* card type assigned */
} pci_subid_map[] = {

/****************************************************************************/
/* The module startup and shutdown code. Only compiled when used as module. */
/* Using the driver as module is always advisable, because the booting      */
/* image becomes smaller and the driver code is only loaded when needed.    */
/* Additionally newer versions may be activated without rebooting.          */
/****************************************************************************/

/******************************************************/
/* extract revision number from string for log output */
/******************************************************/
char *
hysdn_getrev(const char *revision)
{
		PCI_SUBDEVICE_ID_HYPERCOPE_METRO, BD_METRO
	},
	{
		PCI_SUBDEVICE_ID_HYPERCOPE_CHAMP2, BD_CHAMP2
	},
	{
		PCI_SUBDEVICE_ID_HYPERCOPE_ERGO, BD_ERGO
	},
	{
		PCI_SUBDEVICE_ID_HYPERCOPE_OLD_ERGO, BD_ERGO
	},
	{
		0, 0
	}			/* terminating entry */
};
	char *rev;
	char *p;

	if ((p = strchr(revision, ':'))) {
		rev = p + 2;
		p = strchr(rev, '$');
		*--p = 0;
	} else
		rev = "???";
	return rev;
}

/*********************************************************************/
/* search_cards searches for available cards in the pci config data. */
/* If a card is found, the card structure is allocated and the cards */
/* ressources are reserved. cardmax is incremented.                  */
/*********************************************************************/
static void
search_cards(void)

/****************************************************************************/
/* init_module is called once when the module is loaded to do all necessary */
/* things like autodetect...                                                */
/* If the return value of this function is 0 the init has been successful   */
/* and the module is added to the list in /proc/modules, otherwise an error */
/* is assumed and the module will not be kept in memory.                    */
/****************************************************************************/

static int __devinit hysdn_pci_init_one(struct pci_dev *akt_pcidev,
					const struct pci_device_id *ent)
{
	struct pci_dev *akt_pcidev = NULL;
	hysdn_card *card, *card_last;
	int i;
	hysdn_card *card;
	int rc;

	card_root = NULL;
	card_last = NULL;
	while ((akt_pcidev = pci_find_device(PCI_VENDOR_ID_HYPERCOPE, PCI_DEVICE_ID_HYPERCOPE_PLX,
					     akt_pcidev)) != NULL) {
		if (pci_enable_device(akt_pcidev))
			continue;
	rc = pci_enable_device(akt_pcidev);
	if (rc)
		return rc;

	if (!(card = kzalloc(sizeof(hysdn_card), GFP_KERNEL))) {
		printk(KERN_ERR "HYSDN: unable to alloc device mem \n");
			return;
		rc = -ENOMEM;
		goto err_out;
	}
	card->myid = cardmax;	/* set own id */
	card->bus = akt_pcidev->bus->number;
@@ -97,22 +103,14 @@ search_cards(void)
	card->debug_flags = DEF_DEB_FLAGS;	/* set default debug */
	card->faxchans = 0;	/* default no fax channels */
	card->bchans = 2;	/* and 2 b-channels */
		for (i = 0; pci_subid_map[i].subid; i++)
			if (pci_subid_map[i].subid == card->subsysid) {
				card->brdtype = pci_subid_map[i].cardtyp;
				break;
			}
		if (card->brdtype != BD_NONE) {
	card->brdtype = ent->driver_data;

	if (ergo_inithardware(card)) {
		printk(KERN_WARNING "HYSDN: card at io 0x%04x already in use\n", card->iobase);
				kfree(card);
				continue;
			}
		} else {
			printk(KERN_WARNING "HYSDN: unknown card id 0x%04x\n", card->subsysid);
			kfree(card);	/* release mem */
			continue;
		rc = -EBUSY;
		goto err_out_card;
	}

	cardmax++;
	card->next = NULL;	/*end of chain */
	if (card_last)
@@ -120,102 +118,95 @@ search_cards(void)
	else
		card_root = card;
	card_last = card;	/* new chain end */
	}			/* device found */
}				/* search_cards */

/************************************************************************************/
/* free_resources frees the acquired PCI resources and returns the allocated memory */
/************************************************************************************/
static void
free_resources(void)
{
	hysdn_card *card;

	while (card_root) {
		card = card_root;
		if (card->releasehardware)
			card->releasehardware(card);	/* free all hardware resources */
		card_root = card_root->next;	/* remove card from chain */
		kfree(card);	/* return mem */
	pci_set_drvdata(akt_pcidev, card);
	return 0;

	}			/* while card_root */
}				/* free_resources */
err_out_card:
	kfree(card);
err_out:
	pci_disable_device(akt_pcidev);
	return rc;
}

/**************************************************************************/
/* stop_cards disables (hardware resets) all cards and disables interrupt */
/**************************************************************************/
static void
stop_cards(void)
static void __devexit hysdn_pci_remove_one(struct pci_dev *akt_pcidev)
{
	hysdn_card *card;
	hysdn_card *card = pci_get_drvdata(akt_pcidev);

	pci_set_drvdata(akt_pcidev, NULL);

	card = card_root;	/* first in chain */
	while (card) {
	if (card->stopcard)
		card->stopcard(card);
		card = card->next;	/* remove card from chain */
	}			/* while card */
}				/* stop_cards */

#ifdef CONFIG_HYSDN_CAPI
	hycapi_capi_release(card);
#endif

/****************************************************************************/
/* The module startup and shutdown code. Only compiled when used as module. */
/* Using the driver as module is always advisable, because the booting      */
/* image becomes smaller and the driver code is only loaded when needed.    */
/* Additionally newer versions may be activated without rebooting.          */
/****************************************************************************/
	if (card->releasehardware)
		card->releasehardware(card);   /* free all hardware resources */

/******************************************************/
/* extract revision number from string for log output */
/******************************************************/
char *
hysdn_getrev(const char *revision)
{
	char *rev;
	char *p;
	if (card == card_root) {
		card_root = card_root->next;
		if (!card_root)
			card_last = NULL;
	} else {
		hysdn_card *tmp = card_root;
		while (tmp) {
			if (tmp->next == card)
				tmp->next = card->next;
			card_last = tmp;
			tmp = tmp->next;
		}
	}

	if ((p = strchr(revision, ':'))) {
		rev = p + 2;
		p = strchr(rev, '$');
		*--p = 0;
	} else
		rev = "???";
	return rev;
	kfree(card);
	pci_disable_device(akt_pcidev);
}

static struct pci_driver hysdn_pci_driver = {
	.name		= "hysdn",
	.id_table	= hysdn_pci_tbl,
	.probe		= hysdn_pci_init_one,
	.remove		= __devexit_p(hysdn_pci_remove_one),
};

static int hysdn_have_procfs;

/****************************************************************************/
/* init_module is called once when the module is loaded to do all necessary */
/* things like autodetect...                                                */
/* If the return value of this function is 0 the init has been successful   */
/* and the module is added to the list in /proc/modules, otherwise an error */
/* is assumed and the module will not be kept in memory.                    */
/****************************************************************************/
static int __init
hysdn_init(void)
{
	char tmp[50];
	int rc;

	strcpy(tmp, hysdn_init_revision);
	printk(KERN_NOTICE "HYSDN: module Rev: %s loaded\n", hysdn_getrev(tmp));
	strcpy(tmp, hysdn_net_revision);
	printk(KERN_NOTICE "HYSDN: network interface Rev: %s \n", hysdn_getrev(tmp));
	search_cards();

	rc = pci_register_driver(&hysdn_pci_driver);
	if (rc)
		return rc;

	printk(KERN_INFO "HYSDN: %d card(s) found.\n", cardmax);

	if (hysdn_procconf_init()) {
		free_resources();	/* proc file_sys not created */
		return (-1);
	}
	if (!hysdn_procconf_init())
		hysdn_have_procfs = 1;

#ifdef CONFIG_HYSDN_CAPI
	if(cardmax > 0) {
		if(hycapi_init()) {
			printk(KERN_ERR "HYCAPI: init failed\n");
			return(-1);

			if (hysdn_have_procfs)
				hysdn_procconf_release();

			pci_unregister_driver(&hysdn_pci_driver);
			return -ESPIPE;
		}
	}
#endif /* CONFIG_HYSDN_CAPI */
	return (0);		/* no error */

	return 0;		/* no error */
}				/* init_module */


@@ -230,20 +221,15 @@ hysdn_init(void)
static void __exit
hysdn_exit(void)
{
	if (hysdn_have_procfs)
		hysdn_procconf_release();

	pci_unregister_driver(&hysdn_pci_driver);

#ifdef CONFIG_HYSDN_CAPI
	hysdn_card *card;
#endif /* CONFIG_HYSDN_CAPI */
	stop_cards();
#ifdef CONFIG_HYSDN_CAPI
	card = card_root;	/* first in chain */
	while (card) {
		hycapi_capi_release(card);
		card = card->next;	/* remove card from chain */
	}			/* while card */
	hycapi_cleanup();
#endif /* CONFIG_HYSDN_CAPI */
	hysdn_procconf_release();
	free_resources();

	printk(KERN_NOTICE "HYSDN: module unloaded\n");
}				/* cleanup_module */