struct work_struct work;\r
/* set to 1 to make the workhandler exit as soon as possible */\r
int force_end_work;\r
+ int open_flag;\r
/* need to know we are suspending to avoid deadlock on workqueue */\r
int suspending;\r
\r
#define BU92747_IRDA_DBG(x...)\r
#endif\r
\r
+\r
+/* race on startup&shutdown, mutex lock with CIR driver */\r
+static DEFINE_MUTEX(irda_cir_lock);\r
+int bu92747_try_lock(void)\r
+{\r
+ if (mutex_trylock(&irda_cir_lock))\r
+ return 1; //ready\r
+ else\r
+ return 0; //busy\r
+}\r
+\r
+void bu92747_unlock(void)\r
+{\r
+ return mutex_unlock(&irda_cir_lock);\r
+}\r
+\r
static int add_frame_length(struct rev_frame_length *f, unsigned long length)\r
{\r
if (frame_write_full(f))\r
return -1;\r
\r
f->frame_length[f->iWrite] = length;\r
- printk("add one frame, length=%d\n", f->frame_length[f->iWrite]);\r
+ printk("add one frame, length=%ld\n", f->frame_length[f->iWrite]);\r
f->iCount++;\r
printk("now frame iCount=%d\n", f->iCount);\r
f->iWrite = (f->iWrite+1) % MAX_FRAME_NUM;\r
return -1;\r
\r
*length = f->frame_length[f->iRead];\r
- printk("read one frame, length=%d\n", *length);\r
+ printk("read one frame, length=%ld\n", *length);\r
f->iCount--;\r
printk("now frame iCount=%d\n", f->iCount);\r
f->iRead = (f->iRead+1) % MAX_FRAME_NUM;\r
\r
static int bu92747_irda_do_tx(struct bu92747_port *s)\r
{\r
- int i;\r
+ //int i;\r
struct circ_buf *xmit = &s->port.state->xmit;\r
int len = uart_circ_chars_pending(xmit);\r
- BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ printk("line %d, enter %s, sending %d data\n", __LINE__, __FUNCTION__, len);\r
\r
if (IS_FIR(s)) {\r
//printk("fir sending.....\n");\r
irda_hw_tx_enable_irq(BU92725GUW_SIR);\r
}\r
\r
- BU92747_IRDA_DBG("data:\n");\r
- for (i=0; i<len; i++) {\r
- BU92747_IRDA_DBG("%d ", xmit->buf[xmit->tail+i]);\r
- }\r
- BU92747_IRDA_DBG("\n");\r
+ //BU92747_IRDA_DBG("data:\n");\r
+ //for (i=0; i<len; i++) {\r
+ //BU92747_IRDA_DBG("%d ", xmit->buf[xmit->tail+i]);\r
+ //}\r
+ //BU92747_IRDA_DBG("\n");\r
\r
if (len>0) { \r
s->tx_empty = 0;\r
struct circ_buf *xmit = &s->port.state->xmit;\r
\r
dev_dbg(s->dev, "%s\n", __func__);\r
- BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ printk("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
\r
if (!s->force_end_work && !freezing(current)) {\r
//BU92725GUW_dump_register();\r
BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
irq_src = irda_hw_get_irqsrc();\r
printk("[%s][%d], 0x%x\n",__FUNCTION__,__LINE__, irq_src);\r
- /* error */\r
- if (irq_src & (REG_INT_TO| REG_INT_CRC | REG_INT_OE | REG_INT_FE\r
- | REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) {\r
- BU92747_IRDA_DBG("[%s][%d]: do err\n", __FUNCTION__, __LINE__);\r
- //BU92725GUW_dump_register();\r
- BU92725GUW_clr_fifo();\r
- BU92725GUW_reset();\r
- if ((BU92725GUW_SEND==irda_hw_get_mode())\r
- || (BU92725GUW_MULTI_SEND==irda_hw_get_mode())) {\r
- s->tx_empty = 1;\r
- }\r
- }\r
\r
if (irq_src & (REG_INT_DRX | FRM_EVT_RX_EOFRX | FRM_EVT_RX_RDE)) {\r
len = bu92747_irda_do_rx(s);\r
s->tx_empty = 1;\r
irda_hw_set_moderx();\r
}\r
+\r
+ /* error */\r
+ if (irq_src & (REG_INT_TO| REG_INT_CRC | REG_INT_OE | REG_INT_FE\r
+ | REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) {\r
+ BU92747_IRDA_DBG("[%s][%d]: do err\n", __FUNCTION__, __LINE__);\r
+ //BU92725GUW_dump_register();\r
+ BU92725GUW_clr_fifo();\r
+ BU92725GUW_reset();\r
+ if ((BU92725GUW_SEND==irda_hw_get_mode())\r
+ || (BU92725GUW_MULTI_SEND==irda_hw_get_mode())) {\r
+ s->tx_empty = 1;\r
+ }\r
+ }\r
\r
return IRQ_HANDLED;\r
}\r
if (IS_FIR(s))\r
return ;\r
\r
- if (s->tx_empty)\r
- bu92747_irda_do_tx(s);\r
- else \r
- bu92747_irda_dowork(s);\r
+ bu92747_irda_dowork(s);\r
}\r
\r
static void bu92747_irda_stop_rx(struct uart_port *port)\r
struct bu92747_port *s = container_of(port,\r
struct bu92747_port,\r
port);\r
+ struct rev_frame_length *f = &(s->rev_frames);\r
\r
BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
dev_dbg(s->dev, "%s\n", __func__);\r
- struct rev_frame_length *f = &(s->rev_frames);\r
\r
if (s->suspending)\r
return;\r
\r
+ s->open_flag = 0;\r
s->force_end_work = 1;\r
\r
if (s->workqueue) {\r
\r
irda_hw_shutdown();\r
if (s->pdata->irda_pwr_ctl)\r
- s->pdata->irda_pwr_ctl(0);\r
+ s->pdata->irda_pwr_ctl(0); \r
\r
+ bu92747_unlock();\r
}\r
\r
static int bu92747_irda_startup(struct uart_port *port)\r
BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
dev_dbg(s->dev, "%s\n", __func__);\r
\r
- s->baud = 9600;\r
s->rx_enabled = 1;\r
\r
+ if (s->suspending)\r
+ return 0;\r
+\r
+ if (!bu92747_try_lock()) {\r
+ printk("func %s, cannot get bu92747 lock, bu92747 in using\n", __func__);\r
+ return -EBUSY;\r
+ }\r
+ \r
+ s->baud = 9600;\r
+ \r
spin_lock(&s->data_lock);\r
frame_length_buf_clear(f);\r
s->cur_frame_length = 0;\r
spin_unlock(&s->data_lock);\r
\r
- if (s->suspending)\r
- return 0;\r
-\r
s->tx_empty = 1;\r
s->force_end_work = 0;\r
\r
s->workqueue = create_freezeable_workqueue(b);\r
if (!s->workqueue) {\r
dev_warn(s->dev, "cannot create workqueue\n");\r
+ bu92747_unlock();\r
return -EBUSY;\r
}\r
INIT_WORK(&s->work, bu92747_irda_work);\r
s->irq = 0;\r
destroy_workqueue(s->workqueue);\r
s->workqueue = NULL;\r
+ bu92747_unlock();\r
return -EBUSY;\r
}\r
\r
\r
enable_irq(s->irq);\r
\r
+ s->open_flag = 1;\r
+\r
return 0;\r
}\r
\r
dev_warn(&pdev->dev,\r
"uart_add_one_port failed for line %d with error %d\n",\r
i, retval);\r
-\r
- /* set shutdown mode to save power. Will be woken-up on open */\r
+ bu92747s[i]->open_flag = 0;\r
+ bu92747s[i]->suspending = 0;\r
+ /* set shutdown mode to save power. Will be woken-up on open */ \r
if (bu92747s[i]->pdata->irda_pwr_ctl)\r
bu92747s[i]->pdata->irda_pwr_ctl(0);\r
\r
\r
dev_dbg(s->dev, "%s\n", __func__);\r
\r
- BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
- disable_irq(s->irq);\r
-\r
- s->suspending = 1;\r
- uart_suspend_port(&bu92747_irda_uart_driver, &s->port);\r
+ if (s->open_flag) {\r
+ printk("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ disable_irq(s->irq);\r
\r
- //irda_hw_shutdown();\r
- if (s->pdata->irda_pwr_ctl)\r
- s->pdata->irda_pwr_ctl(0);\r
+ s->suspending = 1;\r
+ uart_suspend_port(&bu92747_irda_uart_driver, &s->port);\r
\r
+ irda_hw_shutdown();\r
+ if (s->pdata->irda_pwr_ctl)\r
+ s->pdata->irda_pwr_ctl(0);\r
+ }\r
+ \r
return 0;\r
}\r
\r
struct bu92747_port *s = dev_get_drvdata(&pdev->dev);\r
\r
dev_dbg(s->dev, "%s\n", __func__);\r
-\r
- BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
- if (s->pdata->irda_pwr_ctl)\r
- s->pdata->irda_pwr_ctl(1);\r
\r
- //irda_hw_startup();\r
- irda_hw_set_speed(s->baud);\r
+ if (s->open_flag) {\r
+ printk("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ if (s->pdata->irda_pwr_ctl)\r
+ s->pdata->irda_pwr_ctl(1);\r
+ \r
+ irda_hw_startup();\r
+ irda_hw_set_speed(s->baud);\r
+ irda_hw_set_moderx();\r
\r
- uart_resume_port(&bu92747_irda_uart_driver, &s->port);\r
- s->suspending = 0;\r
+ uart_resume_port(&bu92747_irda_uart_driver, &s->port);\r
+ s->suspending = 0;\r
\r
- enable_irq(s->irq);\r
- \r
- if (s->workqueue)\r
- bu92747_irda_dowork(s);\r
+ enable_irq(s->irq);\r
\r
+ if (!s->tx_empty)\r
+ s->tx_empty = 1;\r
+ \r
+ if (s->workqueue && !IS_FIR(s))\r
+ bu92747_irda_dowork(s);\r
+ }\r
+ \r
return 0;\r
}\r
#else\r