Fix up some of the error paths in the low level code to not go into an
endless loop.  Replace the endless loops with failout code.

This patch is just a first step.  It eliminates the endless loops, but
some of the code paths don't yet have a failure path, so instead the
driver uses BUG_ON() to die with lots of noise.  The driver needs to be
refactored to add in the failure paths so the driver can fail gracefully

Signed-off-by: Grant Likely <[EMAIL PROTECTED]>
---
 drivers/usb/c67x00/c67x00-drv.c    |    8 ++++-
 drivers/usb/c67x00/c67x00-ll-hpi.c |   57 ++++++++++++++++++++++-------------
 drivers/usb/c67x00/c67x00-ll-hpi.h |    6 ++--
 3 files changed, 46 insertions(+), 25 deletions(-)

diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
index 6b38248..2737344 100644
--- a/drivers/usb/c67x00/c67x00-drv.c
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -209,7 +209,11 @@ static int __devinit usb_c67x00_drv_probe(struct 
platform_device *pdev)
                goto request_irq_failed;
        }
 
-       c67x00_ll_reset(drv);
+       ret = c67x00_ll_reset(drv);
+       if (ret) {
+               dev_err(&pdev->dev, "Device reset failed\n");
+               goto reset_failed;
+       }
 
        for (i = 0; i < C67X00_SIES; i++)
                probe_sie(&drv->sie[i]);
@@ -218,6 +222,8 @@ static int __devinit usb_c67x00_drv_probe(struct 
platform_device *pdev)
 
        return 0;
 
+reset_failed:
+       free_irq(res2->start, drv);
 request_irq_failed:
        iounmap(drv->hpi.base);
 map_failed:
diff --git a/drivers/usb/c67x00/c67x00-ll-hpi.c 
b/drivers/usb/c67x00/c67x00-ll-hpi.c
index f47ce79..868736a 100644
--- a/drivers/usb/c67x00/c67x00-ll-hpi.c
+++ b/drivers/usb/c67x00/c67x00-ll-hpi.c
@@ -243,7 +243,7 @@ static inline u16 ll_recv_msg(struct c67x00_drv *drv)
        INIT_COMPLETION(drv->lcp.msg_received);
        WARN_ON(!res);
 
-       return res;
+       return (res == 0) ? -EIO : 0;
 }
 
 static inline void ll_release(struct c67x00_drv *drv)
@@ -283,18 +283,22 @@ static inline void c67x00_ll_husb_sie_init(struct 
c67x00_sie *sie)
 {
        struct c67x00_drv *drv = sie->drv;
        struct lcp_int_data data;
+       int rc;
 
-       c67x00_comm_exec_int(drv, HUSB_SIE_INIT_INT(sie->sie_num), &data);
+       rc = c67x00_comm_exec_int(drv, HUSB_SIE_INIT_INT(sie->sie_num), &data);
+       BUG_ON(rc); /* No return path for error code; crash spectacularly */
 }
 
 void c67x00_ll_husb_reset(struct c67x00_sie *sie, int port)
 {
        struct c67x00_drv *drv = sie->drv;
        struct lcp_int_data data;
+       int rc;
 
        data.regs[0] = 50;      /* Reset USB port for 50ms */
        data.regs[1] = port | (sie->sie_num << 1);
-       c67x00_comm_exec_int(drv, HUSB_RESET_INT, &data);
+       rc = c67x00_comm_exec_int(drv, HUSB_RESET_INT, &data);
+       BUG_ON(rc); /* No return path for error code; crash spectacularly */
 }
 
 void c67x00_ll_husb_set_current_td(struct c67x00_sie *sie, u16 addr)
@@ -358,10 +362,12 @@ void c67x00_ll_susb_init(struct c67x00_sie *sie)
 {
        struct c67x00_drv *drv = sie->drv;
        struct lcp_int_data data;
+       int rc;
 
        data.regs[1] = 1;       /* full speed */
        data.regs[2] = sie->sie_num + 1;
-       c67x00_comm_exec_int(drv, SUSB_INIT_INT, &data);
+       rc = c67x00_comm_exec_int(drv, SUSB_INIT_INT, &data);
+       BUG_ON(rc); /* No return path for error code; crash spectacularly */
 
        hpi_clear_bits(drv, HPI_IRQ_ROUTING_REG,
                       SOFEOP_TO_HPI_EN(sie->sie_num));
@@ -384,45 +390,54 @@ void c67x00_ll_irq(struct c67x00_drv *drv)
 u16 c67x00_comm_read_ctrl_reg(struct c67x00_drv * drv, u16 addr)
 {
        unsigned long msg, res;
+       int rc;
 
        ll_start(drv);
-       do {
-               hpi_write_word(drv, COMM_CTRL_REG_ADDR, addr);
-               hpi_send_mbox(drv, COMM_READ_CTRL_REG);
-       } while (!ll_recv_msg(drv));
+       hpi_write_word(drv, COMM_CTRL_REG_ADDR, addr);
+       hpi_send_mbox(drv, COMM_READ_CTRL_REG);
+       rc = ll_recv_msg(drv);
+
+       BUG_ON(rc); /* No return path for error code; crash spectacularly */
+
        msg = drv->lcp.last_msg;
        if (msg != COMM_ACK) {
                dev_warn(&drv->pdev->dev, "COMM_READ_CTRL_REG didn't ACK!\n");
                res = 0;
-       } else
+       } else {
                res = hpi_read_word(drv, COMM_CTRL_REG_DATA);
+       }
        ll_release(drv);
        return res;
 }
 
-void c67x00_comm_exec_int(struct c67x00_drv *drv, u16 nr,
+int c67x00_comm_exec_int(struct c67x00_drv *drv, u16 nr,
                          struct lcp_int_data *data)
 {
+       int i, rc;
+
        ll_start(drv);
-       do {
-               int i;
-               hpi_write_word(drv, COMM_INT_NUM, nr);
-               for (i = 0; i < COMM_REGS; i++)
-                       hpi_write_word(drv, COMM_R(i), data->regs[i]);
-               hpi_send_mbox(drv, COMM_EXEC_INT);
-       } while (!ll_recv_msg(drv));
+       hpi_write_word(drv, COMM_INT_NUM, nr);
+       for (i = 0; i < COMM_REGS; i++)
+               hpi_write_word(drv, COMM_R(i), data->regs[i]);
+       hpi_send_mbox(drv, COMM_EXEC_INT);
+       rc = ll_recv_msg(drv);
        ll_release(drv);
+
+       return rc;
 }
 
 /* -------------------------------------------------------------------------- 
*/
 
-void c67x00_ll_reset(struct c67x00_drv *drv)
+int c67x00_ll_reset(struct c67x00_drv *drv)
 {
+       int rc;
+
        ll_start(drv);
-       do {
-               hpi_send_mbox(drv, COMM_RESET);
-       } while (!ll_recv_msg(drv));
+       hpi_send_mbox(drv, COMM_RESET);
+       rc = ll_recv_msg(drv);
        ll_release(drv);
+
+       return rc;
 }
 
 /* -------------------------------------------------------------------------- 
*/
diff --git a/drivers/usb/c67x00/c67x00-ll-hpi.h 
b/drivers/usb/c67x00/c67x00-ll-hpi.h
index 118cd7d..3f84348 100644
--- a/drivers/usb/c67x00/c67x00-ll-hpi.h
+++ b/drivers/usb/c67x00/c67x00-ll-hpi.h
@@ -85,14 +85,14 @@ void c67x00_read_mem_le16(struct c67x00_drv *drv, u16 addr,
 
 u16 c67x00_comm_read_ctrl_reg(struct c67x00_drv *drv, u16 addr);
 
-void c67x00_comm_exec_int(struct c67x00_drv *drv, u16 nr,
-                         struct lcp_int_data *data);
+int c67x00_comm_exec_int(struct c67x00_drv *drv, u16 nr,
+                        struct lcp_int_data *data);
 
 /* Called by c67x00_irq to handle lcp interrupts */
 void c67x00_ll_irq(struct c67x00_drv *drv);
 
 void c67x00_ll_init(struct c67x00_drv *drv);
 void c67x00_ll_release(struct c67x00_drv *drv);
-void c67x00_ll_reset(struct c67x00_drv *drv);
+int c67x00_ll_reset(struct c67x00_drv *drv);
 
 #endif                         /* _USB_C67X00_LL_HPI_H */
-- 
1.4.4.2


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to