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