[PATCH] ISDN: move card state init to separate function

From: Jeff Garzik
Date: Tue May 22 2007 - 08:45:17 EST



The follow is the first baby step towards moving the HiSax drivers to
the new PCI API. The HiSax PCI initialization code is ass-backwards and
an incredible pain, so this will take many steps. If anybody is
motivated to assist, help is more than welcome!

The first step just moves some code into a separate function, with the
general direction being the isolation of card-generic code away from all
the heavily #ifdef'd card-specific code.

This patch should not change any behavior at all. It only includes very
trivial code modifications, like s/kmalloc/kzalloc/, use of gfp_mask,
and the allocation of cs->rcvbuf was moved up to be with the rest of the
memory allocations.

Further changes will be checked into this git branch:

The 'isdn-pci' branch of
git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/misc-2.6.git

contains the following updates:

drivers/isdn/hisax/config.c | 83 ++++++++++++++++++++++++++++--------------
1 files changed, 55 insertions(+), 28 deletions(-)

Jeff Garzik (1):
[ISDN] hisax: split cs alloc and init away from checkcard()

diff --git a/drivers/isdn/hisax/config.c b/drivers/isdn/hisax/config.c
index da4196f..6c9a336 100644
--- a/drivers/isdn/hisax/config.c
+++ b/drivers/isdn/hisax/config.c
@@ -847,13 +847,14 @@ static int init_card(struct IsdnCardState *cs)
return 3;
}

-static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
+static int hisax_new_cs(int cardnr, struct IsdnCard *card,
+ struct IsdnCardState **cs_out, int *busy_flag,
+ struct module *lockowner, gfp_t gfp_mask)
{
- int ret = 0;
- struct IsdnCard *card = cards + cardnr;
struct IsdnCardState *cs;
+ int rc = -ENOMEM;

- cs = kzalloc(sizeof(struct IsdnCardState), GFP_ATOMIC);
+ cs = kzalloc(sizeof(struct IsdnCardState), gfp_mask);
if (!cs) {
printk(KERN_WARNING
"HiSax: No memory for IsdnCardState(card %d)\n",
@@ -870,30 +871,32 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
cs->HW_Flags = 0;
cs->busy_flag = busy_flag;
cs->irq_flags = I4L_IRQ_FLAG;
-#if TEI_PER_CARD
- if (card->protocol == ISDN_PTYPE_NI1)
- test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#else
- test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
-#endif
+
cs->protocol = card->protocol;

if (card->typ <= 0 || card->typ > ISDN_CTYPE_COUNT) {
printk(KERN_WARNING
"HiSax: Card Type %d out of range\n", card->typ);
+ rc = -EINVAL;
goto outf_cs;
}
- if (!(cs->dlog = kmalloc(MAX_DLOG_SPACE, GFP_ATOMIC))) {
+
+ if (!(cs->dlog = kzalloc(MAX_DLOG_SPACE, gfp_mask))) {
printk(KERN_WARNING
"HiSax: No memory for dlog(card %d)\n", cardnr + 1);
goto outf_cs;
}
- if (!(cs->status_buf = kmalloc(HISAX_STATUS_BUFSIZE, GFP_ATOMIC))) {
+ if (!(cs->status_buf = kzalloc(HISAX_STATUS_BUFSIZE, gfp_mask))) {
printk(KERN_WARNING
"HiSax: No memory for status_buf(card %d)\n",
cardnr + 1);
goto outf_dlog;
}
+ if (!(cs->rcvbuf = kzalloc(MAX_DFRAME_LEN_L1, gfp_mask))) {
+ printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
+ goto outf_status;
+ }
+
cs->stlist = NULL;
cs->status_read = cs->status_buf;
cs->status_write = cs->status_buf;
@@ -911,22 +914,53 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
ISDN_FEATURE_L2_HDLC |
ISDN_FEATURE_L2_HDLC_56K |
ISDN_FEATURE_L2_TRANS |
- ISDN_FEATURE_L3_TRANS |
+ ISDN_FEATURE_L3_TRANS;
+ cs->iif.command = HiSax_command;
+ cs->iif.writecmd = NULL;
+ cs->iif.writebuf_skb = HiSax_writebuf_skb;
+ cs->iif.readstat = HiSax_readstatus;
+
+ *cs_out = cs;
+ return 0;
+
+outf_status:
+ kfree(cs->status_buf);
+outf_dlog:
+ kfree(cs->dlog);
+outf_cs:
+ kfree(cs);
+ card->cs = NULL;
+out:
+ *cs_out = NULL;
+ return rc;
+}
+
+static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockowner)
+{
+ int ret = 0, rc;
+ struct IsdnCard *card = cards + cardnr;
+ struct IsdnCardState *cs = NULL;
+
+ rc = hisax_new_cs(cardnr, card, &cs, busy_flag, lockowner, GFP_ATOMIC);
+ if (rc)
+ goto out; /* ret == 0 == error */
+
+#if TEI_PER_CARD
+ if (card->protocol == ISDN_PTYPE_NI1)
+ test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
+#else
+ test_and_set_bit(FLG_TWO_DCHAN, &cs->HW_Flags);
+#endif
#ifdef CONFIG_HISAX_1TR6
- ISDN_FEATURE_P_1TR6 |
+ cs->iif.features |= ISDN_FEATURE_P_1TR6;
#endif
#ifdef CONFIG_HISAX_EURO
- ISDN_FEATURE_P_EURO |
+ cs->iif.features |= ISDN_FEATURE_P_EURO;
#endif
#ifdef CONFIG_HISAX_NI1
- ISDN_FEATURE_P_NI1 |
+ cs->iif.features |= ISDN_FEATURE_P_NI1;
#endif
- 0;

- cs->iif.command = HiSax_command;
- cs->iif.writecmd = NULL;
- cs->iif.writebuf_skb = HiSax_writebuf_skb;
- cs->iif.readstat = HiSax_readstatus;
register_isdn(&cs->iif);
cs->myid = cs->iif.channels;
printk(KERN_INFO
@@ -1101,11 +1135,6 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
ll_unload(cs);
goto outf_cs;
}
- if (!(cs->rcvbuf = kmalloc(MAX_DFRAME_LEN_L1, GFP_ATOMIC))) {
- printk(KERN_WARNING "HiSax: No memory for isac rcvbuf\n");
- ll_unload(cs);
- goto outf_cs;
- }
cs->rcvidx = 0;
cs->tx_skb = NULL;
cs->tx_cnt = 0;
@@ -1146,8 +1175,6 @@ static int checkcard(int cardnr, char *id, int *busy_flag, struct module *lockow
ret = 1;
goto out;

- outf_dlog:
- kfree(cs->dlog);
outf_cs:
kfree(cs);
card->cs = NULL;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/