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