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 [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to