The error handling around that part of advansys_board_found() was tricky,
so I split out that part into its own function.  It's still 120 lines, but
it's somewhat easier to see what's going on.  Also use GFP_KERNEL when
allocating memory during initialisation, not GFP_ATOMIC.

Signed-off-by: Matthew Wilcox <[EMAIL PROTECTED]>
---
 drivers/scsi/advansys.c |  285 +++++++++++++++++++++-------------------------
 1 files changed, 130 insertions(+), 155 deletions(-)

diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c
index 3620322..a663d14 100644
--- a/drivers/scsi/advansys.c
+++ b/drivers/scsi/advansys.c
@@ -17693,6 +17693,129 @@ static void AdvInquiryHandling(ADV_DVC_VAR *asc_dvc, 
ADV_SCSI_REQ_Q *scsiq)
        }
 }
 
+static int __devinit
+advansys_wide_init_chip(asc_board_t *boardp, ADV_DVC_VAR *adv_dvc_varp)
+{
+       ADV_CARR_T *carrp;
+       int req_cnt = 0;
+       adv_req_t *reqp = NULL;
+       int sg_cnt = 0;
+       adv_sgblk_t *sgp;
+       int warn_code, err_code;
+
+       /*
+        * Allocate buffer carrier structures. The total size
+        * is about 4 KB, so allocate all at once.
+        */
+       carrp = kmalloc(ADV_CARRIER_BUFSIZE, GFP_KERNEL);
+       ASC_DBG1(1, "advansys_wide_init_chip: carrp 0x%lx\n", (ulong) carrp);
+
+       if (!carrp)
+               goto kmalloc_failed;
+
+       /*
+        * Allocate up to 'max_host_qng' request structures for the Wide
+        * board. The total size is about 16 KB, so allocate all at once.
+        * If the allocation fails decrement and try again.
+        */
+       for (req_cnt = adv_dvc_varp->max_host_qng; req_cnt > 0; req_cnt--) {
+               reqp = kmalloc(sizeof(adv_req_t) * req_cnt, GFP_KERNEL);
+
+               ASC_DBG3(1, "advansys_wide_init_chip: reqp 0x%p, req_cnt %d, "
+                        "bytes %lu\n", reqp, req_cnt,
+                        (ulong)sizeof(adv_req_t) * req_cnt);
+
+               if (reqp)
+                       break;
+       }
+
+       if (!reqp)
+               goto kmalloc_failed;
+
+       /*
+        * Allocate up to ADV_TOT_SG_BLOCK request structures for
+        * the Wide board. Each structure is about 136 bytes.
+        */
+       boardp->adv_sgblkp = NULL;
+       for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
+               sgp = kmalloc(sizeof(adv_sgblk_t), GFP_KERNEL);
+
+               if (!sgp)
+                       break;
+
+               sgp->next_sgblkp = boardp->adv_sgblkp;
+               boardp->adv_sgblkp = sgp;
+
+       }
+
+       ASC_DBG3(1, "advansys_wide_init_chip: sg_cnt %d * %u = %u bytes\n",
+                sg_cnt, sizeof(adv_sgblk_t),
+                (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
+
+       if (!boardp->adv_sgblkp)
+               goto kmalloc_failed;
+
+       /* Save carrier buffer pointer. */
+       boardp->orig_carrp = carrp;
+
+       /*
+        * Save original pointer for kfree() in case the
+        * driver is built as a module and can be unloaded.
+        */
+       boardp->orig_reqp = reqp;
+
+       adv_dvc_varp->carrier_buf = carrp;
+
+       /*
+        * Point 'adv_reqp' to the request structures and
+        * link them together.
+        */
+       req_cnt--;
+       reqp[req_cnt].next_reqp = NULL;
+       for (; req_cnt > 0; req_cnt--) {
+               reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
+       }
+       boardp->adv_reqp = &reqp[0];
+
+       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
+               ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc3550Driver()\n");
+               warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
+       } else if (adv_dvc_varp->chip_type == ADV_CHIP_ASC38C0800) {
+               ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C0800Driver()"
+                          "\n");
+               warn_code = AdvInitAsc38C0800Driver(adv_dvc_varp);
+       } else {
+               ASC_DBG(2, "advansys_wide_init_chip: AdvInitAsc38C1600Driver()"
+                          "\n");
+               warn_code = AdvInitAsc38C1600Driver(adv_dvc_varp);
+       }
+       err_code = adv_dvc_varp->err_code;
+
+       if (warn_code || err_code) {
+               ASC_PRINT3("advansys_wide_init_chip: board %d error: warn 0x%x,"
+                          " error 0x%x\n", boardp->id, warn_code, err_code);
+       }
+
+       if (err_code == 0)
+               return 0;
+
+       while ((sgp = boardp->adv_sgblkp) != NULL) {
+               boardp->adv_sgblkp = sgp->next_sgblkp;
+               kfree(sgp);
+       }
+
+ failed:
+       kfree(reqp);
+       kfree(carrp);
+       return err_code;
+
+ kmalloc_failed:
+       ASC_PRINT1("advansys_wide_init_chip: board %d error: kmalloc() "
+                  "failed\n", boardp->id);
+       err_code = ADV_ERROR;
+       goto failed;
+}
+
 static struct Scsi_Host *__devinit
 advansys_board_found(int iop, struct device *dev, int bus_type)
 {
@@ -17701,7 +17824,6 @@ advansys_board_found(int iop, struct device *dev, int 
bus_type)
        asc_board_t *boardp;
        ASC_DVC_VAR *asc_dvc_varp = NULL;
        ADV_DVC_VAR *adv_dvc_varp = NULL;
-       adv_sgblk_t *sgp = NULL;
        int share_irq = FALSE;
        int iolen = 0;
        ADV_PADDR pci_memory_address;
@@ -17834,10 +17956,10 @@ advansys_board_found(int iop, struct device *dev, int 
bus_type)
         * Allocate buffer for printing information from
         * /proc/scsi/advansys/[0...].
         */
-       if ((boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_ATOMIC)) == NULL) {
-               ASC_PRINT3
-                   ("advansys_board_found: board %d: kmalloc(%d, %d) returned 
NULL\n",
-                    boardp->id, ASC_PRTBUF_SIZE, GFP_ATOMIC);
+       boardp->prtbuf = kmalloc(ASC_PRTBUF_SIZE, GFP_KERNEL);
+       if (!boardp->prtbuf) {
+               ASC_PRINT2("advansys_board_found: board %d: kmalloc(%d) "
+                          "returned NULL\n", boardp->id, ASC_PRTBUF_SIZE);
                goto err_unmap;
        }
 #endif /* CONFIG_PROC_FS */
@@ -18385,159 +18507,12 @@ advansys_board_found(int iop, struct device *dev, 
int bus_type)
                             asc_dvc_varp->init_state, warn_code, err_code);
                }
        } else {
-               ADV_CARR_T *carrp;
-               int req_cnt = 0;
-               adv_req_t *reqp = NULL;
-               int sg_cnt = 0;
-
-               /*
-                * Allocate buffer carrier structures. The total size
-                * is about 4 KB, so allocate all at once.
-                */
-               carrp = (ADV_CARR_T *) kmalloc(ADV_CARRIER_BUFSIZE, GFP_ATOMIC);
-               ASC_DBG1(1, "advansys_board_found: carrp 0x%lx\n", 
(ulong)carrp);
-
-               if (carrp == NULL) {
-                       goto kmalloc_error;
-               }
-
-               /*
-                * Allocate up to 'max_host_qng' request structures for
-                * the Wide board. The total size is about 16 KB, so
-                * allocate all at once. If the allocation fails decrement
-                * and try again.
-                */
-               for (req_cnt = adv_dvc_varp->max_host_qng;
-                    req_cnt > 0; req_cnt--) {
-
-                       reqp = (adv_req_t *)
-                           kmalloc(sizeof(adv_req_t) * req_cnt, GFP_ATOMIC);
-
-                       ASC_DBG3(1,
-                                "advansys_board_found: reqp 0x%lx, req_cnt %d, 
bytes %lu\n",
-                                (ulong)reqp, req_cnt,
-                                (ulong)sizeof(adv_req_t) * req_cnt);
-
-                       if (reqp != NULL) {
-                               break;
-                       }
-               }
-               if (reqp == NULL) {
-                       goto kmalloc_error;
-               }
-
-               /*
-                * Allocate up to ADV_TOT_SG_BLOCK request structures for
-                * the Wide board. Each structure is about 136 bytes.
-                */
-               boardp->adv_sgblkp = NULL;
-               for (sg_cnt = 0; sg_cnt < ADV_TOT_SG_BLOCK; sg_cnt++) {
-
-                       sgp = (adv_sgblk_t *)
-                           kmalloc(sizeof(adv_sgblk_t), GFP_ATOMIC);
-
-                       if (sgp == NULL) {
-                               break;
-                       }
-
-                       sgp->next_sgblkp = boardp->adv_sgblkp;
-                       boardp->adv_sgblkp = sgp;
-
-               }
-               ASC_DBG3(1,
-                        "advansys_board_found: sg_cnt %d * %u = %u bytes\n",
-                        sg_cnt, sizeof(adv_sgblk_t),
-                        (unsigned)(sizeof(adv_sgblk_t) * sg_cnt));
-
-               /*
-                * If no request structures or scatter-gather structures could
-                * be allocated, then return an error. Otherwise continue with
-                * initialization.
-                */
- kmalloc_error:
-               if (carrp == NULL) {
-                       ASC_PRINT1
-                           ("advansys_board_found: board %d error: failed to 
kmalloc() carrier buffer.\n",
-                            boardp->id);
-                       err_code = ADV_ERROR;
-               } else if (reqp == NULL) {
-                       kfree(carrp);
-                       ASC_PRINT1
-                           ("advansys_board_found: board %d error: failed to 
kmalloc() adv_req_t buffer.\n",
-                            boardp->id);
-                       err_code = ADV_ERROR;
-               } else if (boardp->adv_sgblkp == NULL) {
-                       kfree(carrp);
-                       kfree(reqp);
-                       ASC_PRINT1
-                           ("advansys_board_found: board %d error: failed to 
kmalloc() adv_sgblk_t buffers.\n",
-                            boardp->id);
-                       err_code = ADV_ERROR;
-               } else {
-
-                       /* Save carrier buffer pointer. */
-                       boardp->orig_carrp = carrp;
-
-                       /*
-                        * Save original pointer for kfree() in case the
-                        * driver is built as a module and can be unloaded.
-                        */
-                       boardp->orig_reqp = reqp;
-
-                       adv_dvc_varp->carrier_buf = carrp;
-
-                       /*
-                        * Point 'adv_reqp' to the request structures and
-                        * link them together.
-                        */
-                       req_cnt--;
-                       reqp[req_cnt].next_reqp = NULL;
-                       for (; req_cnt > 0; req_cnt--) {
-                               reqp[req_cnt - 1].next_reqp = &reqp[req_cnt];
-                       }
-                       boardp->adv_reqp = &reqp[0];
-
-                       if (adv_dvc_varp->chip_type == ADV_CHIP_ASC3550) {
-                               ASC_DBG(2,
-                                       "advansys_board_found: 
AdvInitAsc3550Driver()\n");
-                               warn_code = AdvInitAsc3550Driver(adv_dvc_varp);
-                       } else if (adv_dvc_varp->chip_type ==
-                                  ADV_CHIP_ASC38C0800) {
-                               ASC_DBG(2,
-                                       "advansys_board_found: 
AdvInitAsc38C0800Driver()\n");
-                               warn_code =
-                                   AdvInitAsc38C0800Driver(adv_dvc_varp);
-                       } else {
-                               ASC_DBG(2,
-                                       "advansys_board_found: 
AdvInitAsc38C1600Driver()\n");
-                               warn_code =
-                                   AdvInitAsc38C1600Driver(adv_dvc_varp);
-                       }
-                       err_code = adv_dvc_varp->err_code;
-
-                       if (warn_code || err_code) {
-                               ASC_PRINT3
-                                   ("advansys_board_found: board %d error: 
warn 0x%x, error 0x%x\n",
-                                    boardp->id, warn_code, err_code);
-                       }
-               }
+               err_code = advansys_wide_init_chip(boardp, adv_dvc_varp);
        }
 
-       if (err_code != 0) {
-               if (ASC_WIDE_BOARD(boardp)) {
-                       kfree(boardp->orig_carrp);
-                       boardp->orig_carrp = NULL;
-                       if (boardp->orig_reqp) {
-                               kfree(boardp->orig_reqp);
-                               boardp->orig_reqp = boardp->adv_reqp = NULL;
-                       }
-                       while ((sgp = boardp->adv_sgblkp) != NULL) {
-                               boardp->adv_sgblkp = sgp->next_sgblkp;
-                               kfree(sgp);
-                       }
-               }
+       if (err_code != 0)
                goto err_free_irq;
-       }
+
        ASC_DBG_PRT_SCSI_HOST(2, shost);
 
        return shost;
-- 
1.4.4.4

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to