diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/ast_adc.c | 2 | ||||
-rw-r--r-- | drivers/i2c/busses/i2c-ast.c | 296 | ||||
-rw-r--r-- | drivers/net/ftgmac100_26.c | 37 | ||||
-rw-r--r-- | drivers/serial/8250.c | 58 | ||||
-rw-r--r-- | drivers/usb/gadget/aspeed_udc.c | 15 | ||||
-rw-r--r-- | drivers/watchdog/ast_wdt.c | 2 |
6 files changed, 312 insertions, 98 deletions
diff --git a/drivers/hwmon/ast_adc.c b/drivers/hwmon/ast_adc.c index 8f5aa541d12d..e21d52eeae4a 100644 --- a/drivers/hwmon/ast_adc.c +++ b/drivers/hwmon/ast_adc.c @@ -525,7 +525,7 @@ ast_show_adc(struct device *dev, struct device_attribute *attr, char *sysfsbuf) break; case 1: //value voltage = ast_get_voltage(sensor_attr->index); - return sprintf(sysfsbuf, "%d.%d (V)\n",voltage/100, voltage%100); + return sprintf(sysfsbuf, "%d.%02d (V)\n",voltage/100, voltage%100); break; case 2: //alarm return sprintf(sysfsbuf, "%d \n", ast_get_adc_alarm(ast_adc,sensor_attr->index)); diff --git a/drivers/i2c/busses/i2c-ast.c b/drivers/i2c/busses/i2c-ast.c index 9bb3154e6bd8..48f019278907 100644 --- a/drivers/i2c/busses/i2c-ast.c +++ b/drivers/i2c/busses/i2c-ast.c @@ -49,14 +49,22 @@ /***************************************************************************/ #ifdef CONFIG_AST_I2C_SLAVE_RDWR -#define I2C_S_BUF_SIZE 64 -#define I2C_S_RX_BUF_NUM 4 +#define I2C_S_BUF_SIZE 256 +#define I2C_S_RX_BUF_NUM 20 #define BUFF_FULL 0xff00 #define BUFF_ONGOING 1 #endif #define AST_LOCKUP_DETECTED (0x1 << 15) +// Enable SCL/SDA pull LOW detection for Yosemite platform +#ifdef CONFIG_YOSEMITE +#define AST_I2C_LOW_TIMEOUT 0x07 +#else +#define AST_I2C_LOW_TIMEOUT 0x00 +#endif //CONFIG_YOSEMITE + + struct ast_i2c_dev { struct ast_i2c_driver_data *ast_i2c_data; struct device *dev; @@ -192,12 +200,12 @@ static void ast_i2c_dev_init(struct ast_i2c_dev *i2c_dev) , I2C_FUN_CTRL_REG); /* Set AC Timing */ - ast_i2c_write(i2c_dev, 0x3, I2C_AC_TIMING_REG2); + ast_i2c_write(i2c_dev, AST_I2C_LOW_TIMEOUT, I2C_AC_TIMING_REG2); ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); }else { /* target apeed is xxKhz*/ ast_i2c_write(i2c_dev, select_i2c_clock(i2c_dev), I2C_AC_TIMING_REG1); - ast_i2c_write(i2c_dev, AST_NO_TIMEOUT_CTRL, I2C_AC_TIMING_REG2); + ast_i2c_write(i2c_dev, AST_I2C_LOW_TIMEOUT, I2C_AC_TIMING_REG2); } #else /* target apeed is xxKhz*/ @@ -252,6 +260,7 @@ static void ast_i2c_slave_buff_init(struct ast_i2c_dev *i2c_dev) static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) { int i; + int count = 0; unsigned long flags; spin_lock_irqsave(&i2c_dev->slave_rx_lock, flags); @@ -265,15 +274,31 @@ static void ast_i2c_slave_rdwr_xfer(struct ast_i2c_dev *i2c_dev) } } if(i == I2C_S_RX_BUF_NUM) { - printk("RX buffer full ........use tmp msgs buff \n"); - //TODO... + // dev_err(i2c_dev->dev, "RX buffer full ........use tmp msgs buff \n"); + for(i=0; i<I2C_S_RX_BUF_NUM; i++) { + if((i2c_dev->slave_rx_msg[i].flags == 0) && (i2c_dev->slave_rx_msg[i].addr == BUFF_ONGOING)) { + count++; + i2c_dev->slave_rx_msg[i].addr = 0; + } + } + + if (count) { + dev_err(i2c_dev->dev, "Cleared slave ongoing buffers of count: %d\n", count); + } + + for(i=0; i<I2C_S_RX_BUF_NUM; i++) { + if((i2c_dev->slave_rx_msg[i].flags == 0) && (i2c_dev->slave_rx_msg[i].addr != BUFF_ONGOING)) { + i2c_dev->slave_rx_msg[i].addr = BUFF_ONGOING; + break; + } + } } //printk("I2C_SLAVE_EVENT_START_WRITE ... %d \n", i); i2c_dev->slave_msgs = &i2c_dev->slave_rx_msg[i]; break; case I2C_SLAVE_EVENT_START_READ: - //printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); + // printk("I2C_SLAVE_EVENT_START_READ ERROR .. not imple \n"); i2c_dev->slave_msgs = &i2c_dev->slave_tx_msg; break; case I2C_SLAVE_EVENT_WRITE: @@ -379,17 +404,17 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) if ((sts & AST_I2CD_SDA_LINE_STS) && (sts & AST_I2CD_SCL_LINE_STS)) { //Means bus is idle. - dev_dbg(i2c_dev->dev, "I2C bus (%d) is idle. I2C slave doesn't exist?!\n", i2c_dev->bus_id); + dev_err(i2c_dev->dev, "I2C bus (%d) is idle. I2C slave doesn't exist?!\n", i2c_dev->bus_id); return -1; } - dev_dbg(i2c_dev->dev, "ERROR!! I2C(%d) bus hanged, try to recovery it!\n", i2c_dev->bus_id); + dev_err(i2c_dev->dev, "ERROR!! I2C(%d) bus hanged, try to recovery it!\n", i2c_dev->bus_id); if ((sts & AST_I2CD_SDA_LINE_STS) && !(sts & AST_I2CD_SCL_LINE_STS)) { //if SDA == 1 and SCL == 0, it means the master is locking the bus. //Send a stop command to unlock the bus. - dev_dbg(i2c_dev->dev, "I2C's master is locking the bus, try to stop it.\n"); + dev_err(i2c_dev->dev, "I2C's master is locking the bus, try to stop it.\n"); // init_completion(&i2c_dev->cmd_complete); i2c_dev->cmd_err = 0; @@ -401,15 +426,15 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) if(i2c_dev->cmd_err && i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) { - dev_dbg(i2c_dev->dev, "recovery error \n"); + dev_err(i2c_dev->dev, "recovery error \n"); return -1; } if (r == 0) { - dev_dbg(i2c_dev->dev, "recovery timed out\n"); + dev_err(i2c_dev->dev, "recovery timed out\n"); return -1; } else { - dev_dbg(i2c_dev->dev, "Recovery successfully\n"); + dev_err(i2c_dev->dev, "Recovery successfully\n"); return 0; } @@ -417,19 +442,20 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) } else if (!(sts & AST_I2CD_SDA_LINE_STS)) { //else if SDA == 0, the device is dead. We need to reset the bus //And do the recovery command. - dev_dbg(i2c_dev->dev, "I2C's slave is dead, try to recover it\n"); + dev_err(i2c_dev->dev, "I2C's slave is dead, try to recover it\n"); //Let's retry 10 times for (i = 0; i < 10; i++) { ast_i2c_dev_init(i2c_dev); //Do the recovery command BIT11 init_completion(&i2c_dev->cmd_complete); + i2c_dev->cmd_err = 0; ast_i2c_write(i2c_dev, AST_I2CD_BUS_RECOVER_CMD_EN, I2C_CMD_REG); r = wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete, i2c_dev->adap.timeout*HZ); if (i2c_dev->cmd_err != 0 && i2c_dev->cmd_err != AST_I2CD_INTR_STS_NORMAL_STOP) { - dev_dbg(i2c_dev->dev, "ERROR!! Failed to do recovery command(0x%08x)\n", i2c_dev->cmd_err); + dev_err(i2c_dev->dev, "ERROR!! Failed to do recovery command(0x%08x)\n", i2c_dev->cmd_err); return -1; } //Check 0x14's SDA and SCL status @@ -438,14 +464,14 @@ ast_i2c_bus_error_recover(struct ast_i2c_dev *i2c_dev) break; } if (i == 10) { - dev_dbg(i2c_dev->dev, "ERROR!! recover failed\n"); + dev_err(i2c_dev->dev, "ERROR!! recover failed\n"); return -1; } } else { - dev_dbg(i2c_dev->dev, "Don't know how to handle this case?!\n"); + dev_err(i2c_dev->dev, "Don't know how to handle this case?!\n"); return -1; } - dev_dbg(i2c_dev->dev, "Recovery successfully\n"); + dev_err(i2c_dev->dev, "Recovery successfully\n"); return 0; } @@ -472,7 +498,8 @@ static int ast_i2c_wait_bus_not_busy(struct ast_i2c_dev *i2c_dev) } if (timeout <= 0) { - return -EAGAIN; + //TODO: sometimes the slave operation flag is not reset properly so go ahead with checking bus busy signal + dev_err(i2c_dev->dev, "slave operation set, check busy status line\n"); } // Wait for Bus to go IDLE @@ -491,6 +518,8 @@ static int ast_i2c_wait_bus_not_busy(struct ast_i2c_dev *i2c_dev) return 0; } + // TODO: hack to reset slave operation flag manually + i2c_dev->slave_operation = 0; return 0; } @@ -499,9 +528,6 @@ static void ast_i2c_do_dma_xfer(struct ast_i2c_dev *i2c_dev) u32 cmd = 0; int i; - i2c_dev->master_xfer_mode = DMA_XFER; - i2c_dev->slave_xfer_mode = DMA_XFER; - if(i2c_dev->slave_operation == 1) { if(i2c_dev->slave_msgs->flags & I2C_M_RD) { //DMA tx mode @@ -683,9 +709,6 @@ static void ast_i2c_do_pool_xfer(struct ast_i2c_dev *i2c_dev) int i; u32 *tx_buf; - i2c_dev->master_xfer_mode = BUFF_XFER; - i2c_dev->slave_xfer_mode = BUFF_XFER; - #if defined(CONFIG_ARCH_AST2400) ast_i2c_write(i2c_dev, (ast_i2c_read(i2c_dev, I2C_FUN_CTRL_REG) & @@ -872,12 +895,6 @@ static void ast_i2c_do_byte_xfer(struct ast_i2c_dev *i2c_dev) u8 *xfer_buf; u32 cmd = 0; - i2c_dev->master_xfer_mode = BYTE_XFER; - i2c_dev->master_xfer_len = 1; - - i2c_dev->slave_xfer_mode = BYTE_XFER; - i2c_dev->slave_xfer_len = 1; - if(i2c_dev->slave_operation == 1) { dev_dbg(i2c_dev->dev,"S cnt %d, xf len %d \n",i2c_dev->slave_xfer_cnt, i2c_dev->slave_msgs->len); if(i2c_dev->slave_msgs->flags & I2C_M_RD) { @@ -973,14 +990,16 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) u32 xfer_len; int i; u8 *rx_buf; + unsigned long flags; dev_dbg(i2c_dev->dev, "ast_i2c_slave_xfer_done [%d]\n",i2c_dev->slave_xfer_mode); + if (i2c_dev->slave_msgs->flags & I2C_M_RD) { //tx done , only check tx count ... - if(i2c_dev->master_xfer_mode == BYTE_XFER) { + if(i2c_dev->slave_xfer_mode == BYTE_XFER) { xfer_len = 1; - } else if (i2c_dev->master_xfer_mode == BUFF_XFER) { + } else if (i2c_dev->slave_xfer_mode == BUFF_XFER) { xfer_len = AST_I2CD_TX_DATA_BUF_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG)); xfer_len++; dev_dbg(i2c_dev->dev,"S tx buff done len %d \n",xfer_len); @@ -1004,10 +1023,12 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt] = 0; i2c_dev->slave_msgs->len = i2c_dev->slave_xfer_cnt; } else { + if (i2c_dev->slave_xfer_cnt == 0) + dev_err(i2c_dev->dev,"Possible first byte failure issue\n"); i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt] = ast_i2c_read(i2c_dev,I2C_BYTE_BUF_REG) >> 8; } dev_dbg(i2c_dev->dev,"rx buff %d, [%x] \n",i2c_dev->slave_xfer_cnt ,i2c_dev->slave_msgs->buf[i2c_dev->slave_xfer_cnt]); - } else if (i2c_dev->master_xfer_mode == BUFF_XFER) { + } else if (i2c_dev->slave_xfer_mode == BUFF_XFER) { xfer_len = AST_I2CD_RX_BUF_ADDR_GET(ast_i2c_read(i2c_dev, I2C_BUF_CTRL_REG)); if(xfer_len == 0) xfer_len = AST_I2C_PAGE_SIZE; @@ -1056,7 +1077,7 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) i2c_dev->slave_xfer_cnt = 0; } else { if(i2c_dev->slave_xfer_cnt == i2c_dev->slave_msgs->len) { - dev_dbg(i2c_dev->dev,"slave next msgs \n"); + dev_err(i2c_dev->dev,"slave next msgs with len %d\n", i2c_dev->slave_xfer_cnt); #ifdef CONFIG_AST_I2C_SLAVE_RDWR ast_i2c_slave_rdwr_xfer(i2c_dev); #else @@ -1068,6 +1089,8 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) i2c_dev->do_slave_xfer(i2c_dev); } + // Read the current state for clearing up the slave mode + i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf; if(AST_I2CD_IDLE == i2c_dev->state) { dev_dbg(i2c_dev->dev,"** Slave go IDLE **\n"); @@ -1077,7 +1100,10 @@ static void ast_i2c_slave_xfer_done(struct ast_i2c_dev *i2c_dev) i2c_dev->ast_i2c_data->free_pool_buff_page(i2c_dev->req_page); } - } + } else if (i2c_dev->slave_event == I2C_SLAVE_EVENT_STOP) { + // TODO: hack to reset slave operation flag in case the stop is received + i2c_dev->slave_operation = 0; + } } @@ -1212,6 +1238,8 @@ unlock_out: static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) { u8 match; + unsigned long flags; + i2c_dev->slave_operation = 1; i2c_dev->slave_xfer_cnt = 0; @@ -1219,7 +1247,6 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) i2c_dev->slave_msgs->buf[0] = match; dev_dbg(i2c_dev->dev, "S Start Addr match [%x] \n",match); - if(match & 1) { i2c_dev->slave_event = I2C_SLAVE_EVENT_START_READ; } else { @@ -1228,23 +1255,33 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) #ifdef CONFIG_AST_I2C_SLAVE_RDWR ast_i2c_slave_rdwr_xfer(i2c_dev); - i2c_dev->slave_msgs->buf[0] = match; - i2c_dev->slave_xfer_cnt = 1; + i2c_dev->slave_msgs->buf[0] = match; + i2c_dev->slave_xfer_cnt = 1; + // Reset the length field as we have received new slave address match + i2c_dev->slave_msgs->len = 0x0; #else i2c_dev->ast_i2c_data->slave_xfer(i2c_dev->slave_event, &(i2c_dev->slave_msgs)); i2c_dev->slave_xfer_cnt = 0; #endif - //request - if(i2c_dev->ast_i2c_data->slave_dma == BYTE_MODE) + //request: set slave_xfer_mode properly based on slave_dma mode + if(i2c_dev->ast_i2c_data->slave_dma == BYTE_MODE) { i2c_dev->do_slave_xfer = ast_i2c_do_byte_xfer; - else if (i2c_dev->ast_i2c_data->slave_dma == DMA_MODE) + i2c_dev->slave_xfer_mode = BYTE_XFER; + i2c_dev->slave_xfer_len = 1; + } else if (i2c_dev->ast_i2c_data->slave_dma == DMA_MODE) { i2c_dev->do_slave_xfer = ast_i2c_do_dma_xfer; - else { - if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) + i2c_dev->slave_xfer_mode = DMA_XFER; + } else { + if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) { i2c_dev->do_slave_xfer = ast_i2c_do_pool_xfer; - else + i2c_dev->slave_xfer_mode = BUFF_XFER; + } else { i2c_dev->do_slave_xfer = ast_i2c_do_byte_xfer; + dev_err(i2c_dev->dev,"i2cdriver: pool request failed for slave\n"); + i2c_dev->slave_xfer_mode = BYTE_XFER; + i2c_dev->slave_xfer_len = 1; + } } i2c_dev->do_slave_xfer(i2c_dev); @@ -1254,6 +1291,7 @@ static void ast_i2c_slave_addr_match(struct ast_i2c_dev *i2c_dev) static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) { u32 sts; + u32 temp; struct ast_i2c_dev *i2c_dev = dev_id; u32 isr_sts = readl(i2c_dev->ast_i2c_data->reg_gr); @@ -1280,17 +1318,15 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) } if(AST_I2CD_INTR_STS_ABNORMAL & sts) { - i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ABNORMAL; - // Turn off interrupts for further abnormal - // conditions until we fix this one. - ast_i2c_write(i2c_dev, - ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) & - ~AST_I2CD_ABNORMAL_INTR_EN, - I2C_INTR_CTRL_REG); - complete(&i2c_dev->cmd_complete); - sts &= ~AST_I2CD_INTR_STS_ABNORMAL; + // TODO: observed abnormal interrupt happening when the bus is stressed with traffic + dev_err(i2c_dev->dev, "abnormal interrupt happens with status: %x, slave mode: %d\n", sts, i2c_dev->slave_operation); // Need to clear the interrupt ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ABNORMAL, I2C_INTR_STS_REG); + + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ABNORMAL; + complete(&i2c_dev->cmd_complete); + + return IRQ_HANDLED; } switch(sts) { @@ -1316,15 +1352,47 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) ast_i2c_master_xfer_done(i2c_dev); } else { - printk("ast_i2c: TX_ACK | NORMAL_STOP; xfer_last %d\n", i2c_dev->xfer_last); + dev_err(i2c_dev->dev,"ast_i2c: TX_ACK | NORMAL_STOP; xfer_last %d\n", i2c_dev->xfer_last); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + uint32_t new_val = ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | + AST_I2CD_NORMAL_STOP_INTR_EN | + AST_I2CD_TX_ACK_INTR_EN; + ast_i2c_write(i2c_dev, new_val, I2C_INTR_CTRL_REG); + //take care + i2c_dev->cmd_err |= AST_LOCKUP_DETECTED; + complete(&i2c_dev->cmd_complete); + } + break; + case AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP | AST_I2CD_INTR_STS_SLAVE_MATCH : + if((i2c_dev->xfer_last == 1) && (i2c_dev->slave_operation == 0)) { + dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP | AST_I2CD_INTR_STS_SLAVE_MATCH= %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + //take care + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | + AST_I2CD_TX_ACK_INTR_EN, I2C_INTR_CTRL_REG); + ast_i2c_master_xfer_done(i2c_dev); + + // Handle the new slave match interrupt + ast_i2c_slave_addr_match(i2c_dev); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); + } else { + dev_err(i2c_dev->dev, "Slave TX_ACK | NORMAL_STOP | AST_I2CD_INTR_STS_SLAVE_MATCH; xfer_last %d\n", i2c_dev->xfer_last); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); uint32_t new_val = ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | - AST_I2CD_NORMAL_STOP_INTR_EN | + AST_I2CD_NORMAL_STOP_INTR_EN | AST_I2CD_TX_ACK_INTR_EN; ast_i2c_write(i2c_dev, new_val, I2C_INTR_CTRL_REG); //take care i2c_dev->cmd_err |= AST_LOCKUP_DETECTED; complete(&i2c_dev->cmd_complete); + + // stop previous slave transaction + i2c_dev->slave_event = I2C_SLAVE_EVENT_STOP; + ast_i2c_slave_xfer_done(i2c_dev); + + // Handle the new slave match interrupt + ast_i2c_slave_addr_match(i2c_dev); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); } break; @@ -1332,9 +1400,8 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) if(i2c_dev->slave_operation == 1) { i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK; ast_i2c_slave_xfer_done(i2c_dev); - dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); + dev_err(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); - } else { dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); @@ -1352,7 +1419,10 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP: if(i2c_dev->slave_operation == 1) { printk("SLAVE TODO .... \n"); - + i2c_dev->slave_operation = 0; + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP; + complete(&i2c_dev->cmd_complete); } else { dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_TX_NAK| AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); @@ -1365,12 +1435,17 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) //Issue : Workaround for I2C slave mode case AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH: if(i2c_dev->slave_operation == 1) { - i2c_dev->slave_event = I2C_SLAVE_EVENT_NACK; - ast_i2c_slave_xfer_done(i2c_dev); + dev_err(i2c_dev->dev, "i2cdriver: TX_NAK and Slave match sts = %x\n",sts); ast_i2c_slave_addr_match(i2c_dev); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK | AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); } else { printk("ERROR !!!!\n"); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_NAK, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_TX_NAK; + complete(&i2c_dev->cmd_complete); + + ast_i2c_slave_addr_match(i2c_dev); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SLAVE_MATCH , I2C_INTR_STS_REG); } break; case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH: @@ -1378,7 +1453,17 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) dev_dbg(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); break; + case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH | AST_I2CD_INTR_STS_ARBIT_LOSS: + dev_err(i2c_dev->dev, "M clear isr: sts = %x\n",sts); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | + AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + complete(&i2c_dev->cmd_complete); + ast_i2c_slave_addr_match(i2c_dev); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); + break; case AST_I2CD_INTR_STS_RX_DOWN: if(i2c_dev->slave_operation == 1) { i2c_dev->slave_event = I2C_SLAVE_EVENT_WRITE; @@ -1389,7 +1474,6 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN, I2C_INTR_STS_REG); ast_i2c_master_xfer_done(i2c_dev); - } break; @@ -1407,7 +1491,7 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) complete(&i2c_dev->cmd_complete); } break; - case (AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP): + case AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP: /* Whether or not we're done, the hardware thinks we're done, so bail. */ if(i2c_dev->slave_operation == 0) { dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); @@ -1416,18 +1500,47 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); ast_i2c_master_xfer_done(i2c_dev); - } + } else { + dev_err(i2c_dev->dev, "S clear isr: AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP = %x\n",sts); + i2c_dev->slave_event = I2C_SLAVE_EVENT_STOP; + ast_i2c_slave_xfer_done(i2c_dev); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_RX_DOWN | AST_I2CD_INTR_STS_NORMAL_STOP, I2C_INTR_STS_REG); + ast_i2c_write(i2c_dev, ast_i2c_read(i2c_dev,I2C_INTR_CTRL_REG) | + AST_I2CD_RX_DOWN_INTR_EN, I2C_INTR_CTRL_REG); + ast_i2c_master_xfer_done(i2c_dev); + } break; case AST_I2CD_INTR_STS_ARBIT_LOSS: - dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_ARBIT_LOSS = %x\n",sts); + dev_err(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_ARBIT_LOSS = %x\n",sts); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG); i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; complete(&i2c_dev->cmd_complete); break; case AST_I2CD_INTR_STS_SCL_TO: + dev_err(i2c_dev->dev, "SCL LOW detected with sts = %x, slave mode: %x\n",sts, i2c_dev->slave_operation); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SCL_TO, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_SCL_TO; + complete(&i2c_dev->cmd_complete); + + // Reset i2c controller + temp = ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG); + + ast_i2c_write(i2c_dev, temp & ~(AST_I2CD_SLAVE_EN | AST_I2CD_MASTER_EN), I2C_FUN_CTRL_REG); + + ast_i2c_write(i2c_dev, temp, I2C_FUN_CTRL_REG); + break; + case AST_I2CD_INTR_STS_SLAVE_MATCH | AST_I2CD_INTR_STS_SCL_TO: + dev_err(i2c_dev->dev, "SCL LOW detected with sts = %x, slave mode: %x\n",sts, i2c_dev->slave_operation); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SCL_TO | AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); i2c_dev->cmd_err |= AST_I2CD_INTR_STS_SCL_TO; complete(&i2c_dev->cmd_complete); + // Reset i2c controller + temp = ast_i2c_read(i2c_dev,I2C_FUN_CTRL_REG); + + ast_i2c_write(i2c_dev, temp & ~(AST_I2CD_SLAVE_EN | AST_I2CD_MASTER_EN), I2C_FUN_CTRL_REG); + + ast_i2c_write(i2c_dev, temp, I2C_FUN_CTRL_REG); break; case AST_I2CD_INTR_STS_GCALL_ADDR: i2c_dev->cmd_err |= AST_I2CD_INTR_STS_GCALL_ADDR; @@ -1437,24 +1550,26 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) case AST_I2CD_INTR_STS_SMBUS_DEF_ADDR: break; case AST_I2CD_INTR_STS_SMBUS_DEV_ALT: - break; case AST_I2CD_INTR_STS_SMBUS_ARP_ADDR: break; case AST_I2CD_INTR_STS_SDA_DL_TO: + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SDA_DL_TO, I2C_INTR_STS_REG); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_SDA_DL_TO; + complete(&i2c_dev->cmd_complete); break; case AST_I2CD_INTR_STS_BUS_RECOVER: - dev_dbg(i2c_dev->dev, "M clear isr: AST_I2CD_INTR_STS_BUS_RECOVER= %x\n",sts); + dev_err(i2c_dev->dev, "Bus recover with sts= %x, slave mode: %x\n",sts, i2c_dev->slave_operation); ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_BUS_RECOVER, I2C_INTR_STS_REG); complete(&i2c_dev->cmd_complete); break; default: - //TODO: Clearing this interrupt for now, but needs to cleanup this ISR function - ast_i2c_write(i2c_dev, sts, I2C_INTR_STS_REG); + printk("GR %x : Status : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id); // Handle Arbitration Loss if (sts & AST_I2CD_INTR_STS_ARBIT_LOSS) { + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_ARBIT_LOSS, I2C_INTR_STS_REG); i2c_dev->cmd_err |= AST_I2CD_INTR_STS_ARBIT_LOSS; complete(&i2c_dev->cmd_complete); sts &= (~AST_I2CD_INTR_STS_ARBIT_LOSS); @@ -1462,22 +1577,35 @@ static irqreturn_t i2c_ast_handler(int this_irq, void *dev_id) // Handle the write transaction ACK if (sts & AST_I2CD_INTR_STS_TX_ACK) { + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); ast_i2c_master_xfer_done(i2c_dev); - complete(&i2c_dev->cmd_complete); sts &= (~AST_I2CD_INTR_STS_TX_ACK); } + // Handle Normal Stop conditon + if (sts & AST_I2CD_INTR_STS_NORMAL_STOP) { + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_TX_ACK, I2C_INTR_STS_REG); + sts &= (~AST_I2CD_INTR_STS_NORMAL_STOP); + i2c_dev->cmd_err |= AST_I2CD_INTR_STS_NORMAL_STOP; + complete(&i2c_dev->cmd_complete); + } + // Handle the Slave address match if (sts & AST_I2CD_INTR_STS_SLAVE_MATCH) { ast_i2c_slave_addr_match(i2c_dev); sts &= (~AST_I2CD_INTR_STS_SLAVE_MATCH); + ast_i2c_write(i2c_dev, AST_I2CD_INTR_STS_SLAVE_MATCH, I2C_INTR_STS_REG); } + // TODO: Debug print for any unhandled condition if(sts) { printk("GR %x : Status : %x, bus_id %d\n",i2c_dev->ast_i2c_data->reg_gr, sts, i2c_dev->bus_id); } + //TODO: Clearing this interrupt for now, but needs to cleanup this ISR function + ast_i2c_write(i2c_dev, sts, I2C_INTR_STS_REG); + return IRQ_HANDLED; } @@ -1492,16 +1620,25 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg spin_lock_irqsave(&i2c_dev->master_lock, flags); - //request - if(i2c_dev->ast_i2c_data->master_dma == BYTE_MODE) + //request: update master_xfer_mode based on master_dma selection + if(i2c_dev->ast_i2c_data->master_dma == BYTE_MODE) { i2c_dev->do_master_xfer = ast_i2c_do_byte_xfer; - else if (i2c_dev->ast_i2c_data->master_dma == DMA_MODE) + i2c_dev->master_xfer_mode = BYTE_XFER; + i2c_dev->master_xfer_len = 1; + } else if (i2c_dev->ast_i2c_data->master_dma == DMA_MODE) { i2c_dev->do_master_xfer = ast_i2c_do_dma_xfer; - else { - if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) + i2c_dev->master_xfer_mode = DMA_XFER; + } else { + if(i2c_dev->ast_i2c_data->request_pool_buff_page(&(i2c_dev->req_page)) == 0) { i2c_dev->do_master_xfer = ast_i2c_do_pool_xfer; - else + i2c_dev->master_xfer_mode = BUFF_XFER; + } else { i2c_dev->do_master_xfer = ast_i2c_do_byte_xfer; + dev_err(i2c_dev->dev, "i2cdriver: pool request failed for master\n"); + i2c_dev->master_xfer_mode = BYTE_XFER; + i2c_dev->master_xfer_len = 1; + + } } // printk("start xfer ret = %d \n",ret); @@ -1534,7 +1671,7 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg i2c_dev->master_msgs = NULL; if (ret == 0) { - dev_dbg(i2c_dev->dev, "controller timed out\n"); + dev_err(i2c_dev->dev, "controller timed out\n"); i2c_dev->state = (ast_i2c_read(i2c_dev,I2C_CMD_REG) >> 19) & 0xf; // printk("sts [%x], isr sts [%x] \n",i2c_dev->state, ast_i2c_read(i2c_dev,I2C_INTR_STS_REG)); ret = -ETIMEDOUT; @@ -1564,9 +1701,10 @@ static int ast_i2c_do_msgs_xfer(struct ast_i2c_dev *i2c_dev, struct i2c_msg *msg } stop: - init_completion(&i2c_dev->cmd_complete); if(i2c_dev->cmd_err & AST_I2CD_INTR_STS_NORMAL_STOP) goto out; + init_completion(&i2c_dev->cmd_complete); + i2c_dev->cmd_err = 0; ast_i2c_write(i2c_dev, AST_I2CD_M_STOP_CMD, I2C_CMD_REG); wait_for_completion_interruptible_timeout(&i2c_dev->cmd_complete, i2c_dev->adap.timeout*HZ); @@ -1605,7 +1743,7 @@ static int ast_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) ret = ast_i2c_do_msgs_xfer(i2c_dev, msgs, num); if (ret != -EAGAIN) goto out; - dev_dbg(&adap->dev, "Retrying transmission [%d]\n",i); + dev_dbg(&i2c_dev->adap.dev, "Retrying transmission [%d]\n",i); udelay(100); } diff --git a/drivers/net/ftgmac100_26.c b/drivers/net/ftgmac100_26.c index 3a5d7969278a..f558d385e8dc 100644 --- a/drivers/net/ftgmac100_26.c +++ b/drivers/net/ftgmac100_26.c @@ -901,6 +901,41 @@ void Enable_Broadcast_Filter (struct net_device * dev) lp->Retry = 0; } +void Disable_Multicast_Filter (struct net_device * dev) +{ + struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; + unsigned long Combined_Channel_ID; + struct sk_buff * skb; + + do { + skb = dev_alloc_skb (TX_BUF_SIZE + 16); + memset(skb->data, 0, TX_BUF_SIZE + 16); +//TX + lp->InstanceID++; + lp->NCSI_Request.IID = lp->InstanceID; + lp->NCSI_Request.Command = DISABLE_GLOBAL_MULTICAST_FILTERING; + Combined_Channel_ID = (lp->NCSI_Cap.Package_ID << 5) + lp->NCSI_Cap.Channel_ID; + lp->NCSI_Request.Channel_ID = Combined_Channel_ID; + lp->NCSI_Request.Payload_Length = 0; + memcpy ((unsigned char *)skb->data, &lp->NCSI_Request, 30); + copy_data (dev, skb, lp->NCSI_Request.Payload_Length); + skb->len = 30 + lp->NCSI_Request.Payload_Length + 4; + ftgmac100_wait_to_send_packet (skb, dev); +//RX + NCSI_Rx(dev); + if (((lp->NCSI_Respond.IID != lp->InstanceID) || (lp->NCSI_Respond.Command != (DISABLE_GLOBAL_MULTICAST_FILTERING | 0x80)) || (lp->NCSI_Respond.Response_Code != COMMAND_COMPLETED)) && (lp->Retry != RETRY_COUNT)) { + printk ("Retry: Command = %x, Response_Code = %x\n", lp->NCSI_Request.Command, lp->NCSI_Respond.Response_Code); + printk ("IID: %x:%x, Command: %x:%x\n", lp->InstanceID, lp->NCSI_Respond.IID, lp->NCSI_Request.Command, lp->NCSI_Respond.Command); + lp->Retry++; + lp->InstanceID--; + } + else { + lp->Retry = 0; + } + } while ((lp->Retry != 0) && (lp->Retry <= RETRY_COUNT)); + lp->Retry = 0; +} + void Disable_VLAN (struct net_device * dev) { struct ftgmac100_priv *lp = (struct ftgmac100_priv *)dev->priv; @@ -1416,6 +1451,8 @@ static void ftgmac100_enable( struct net_device *dev ) Enable_Set_MAC_Address(dev); //Enable Broadcast Filter Enable_Broadcast_Filter(dev); +//Disable Multicast Filter + Disable_Multicast_Filter(dev); //Disable VLAN Disable_VLAN(dev); //Enable AEN diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index f16da5982358..d01c1c7152e2 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c @@ -127,6 +127,11 @@ static unsigned long probe_rsa[PORT_RSA_MAX]; static unsigned int probe_rsa_count; #endif /* CONFIG_SERIAL_8250_RSA */ +struct rs485_wait_state { + int gpio; + int waiting; +}; + struct uart_8250_port { struct uart_port port; struct timer_list timer; /* "no irq" timer */ @@ -156,6 +161,8 @@ struct uart_8250_port { */ void (*pm)(struct uart_port *port, unsigned int state, unsigned int old); + + struct rs485_wait_state rs485_wait_state; }; struct irq_info { @@ -169,6 +176,9 @@ struct irq_info { static struct hlist_head irq_lists[NR_IRQ_HASH]; static DEFINE_MUTEX(hash_mutex); /* Used to walk the hash */ +#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) +static void wait_for_xmitr(struct uart_8250_port *up, int bits); + /* * Here we define the default xmit fifo size used for each type of UART. */ @@ -530,6 +540,31 @@ static void serial_dl_write(struct uart_8250_port *up, int value) #define serial_dl_write(up, value) _serial_dl_write(up, value) #endif +// unfortunately it seems the gpio switch for RS485 can be late even with the +// wait queue based wakeup of the task waiting on its completion, so we *have* +// to do the gpio switch in the interrupt handler. +static void rs485_wait_end(struct uart_8250_port *up) { + struct rs485_wait_state *rs485_wait_state = + &up->rs485_wait_state; + if (rs485_wait_state->waiting) { + int status; + status = serial_in(up, UART_LSR); + // no interrupt will be fire for shift register (TEMT) so we have to spin + // on it. + if (status & UART_LSR_THRE) { + wait_for_xmitr(up, BOTH_EMPTY); + // turn off RS485 DE pin + if (rs485_wait_state->gpio) + gpio_set_value(rs485_wait_state->gpio, 0); + // grab any phantom char seen on RX when transceiver switches + (void) serial_inp(up, UART_RX); + // enable read + up->port.ignore_status_mask &= ~UART_LSR_DR; + rs485_wait_state->waiting = 0; + } + } +} + /* * For the 16C950 */ @@ -1235,6 +1270,7 @@ static inline void __stop_tx(struct uart_8250_port *p) p->ier &= ~UART_IER_THRI; serial_out(p, UART_IER, p->ier); } + uart_write_wakeup(&p->port); } static void serial8250_stop_tx(struct uart_port *port) @@ -1436,7 +1472,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up) if (status & UART_MSR_DCTS) uart_handle_cts_change(&up->port, status & UART_MSR_CTS); - wake_up_interruptible(&up->port.info->delta_msr_wait); + wake_up_interruptible(&up->port.info->delta_msr_wait); } return status; @@ -1462,6 +1498,7 @@ static void serial8250_handle_port(struct uart_8250_port *up) if (status & UART_LSR_THRE) transmit_chars(up); + rs485_wait_end(up); spin_unlock_irqrestore(&up->port.lock, flags); } @@ -1777,8 +1814,6 @@ static void serial8250_break_ctl(struct uart_port *port, int break_state) spin_unlock_irqrestore(&up->port.lock, flags); } -#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE) - /* * Wait for transmitter & holding register to empty */ @@ -2539,8 +2574,13 @@ static int serial8250_ioctl(struct uart_port *port, unsigned int cmd, unsigned l int ret = -ENOIOCTLCMD; // kernel-space RS485 drain-and-switch hack if (cmd == TIOCSERWAITTEMT) { - // wait for kernel buffers and UART FIFO to both empty struct circ_buf *xmit = &up->port.info->xmit; + spin_lock_irqsave(&up->port.lock, flags); + up->rs485_wait_state.gpio = arg; + up->rs485_wait_state.waiting = 1; + spin_unlock_irqrestore(&up->port.lock, flags); + + // wait for kernel buffers and UART FIFO to both empty wait_event_interruptible( thre_wait, uart_circ_empty(xmit) && @@ -2548,14 +2588,6 @@ static int serial8250_ioctl(struct uart_port *port, unsigned int cmd, unsigned l // spin until TEMT (transmit shift register empty) spin_lock_irqsave(&up->port.lock, flags); wait_for_xmitr(up, BOTH_EMPTY); - if (arg != 0) { - // turn off RS485 DE pin - gpio_set_value(arg, 0); - } - // grab any phantom char seen on RX when transceiver switches - (void) serial_inp(up, UART_RX); - // enable read - up->port.ignore_status_mask &= ~UART_LSR_DR; spin_unlock_irqrestore(&up->port.lock, flags); return 0; } @@ -2607,6 +2639,8 @@ static void __init serial8250_isa_init_ports(void) init_timer(&up->timer); up->timer.function = serial8250_timeout; + up->rs485_wait_state.waiting = 0; + up->rs485_wait_state.gpio = 0; /* * ALPHA_KLUDGE_MCR needs to be killed. diff --git a/drivers/usb/gadget/aspeed_udc.c b/drivers/usb/gadget/aspeed_udc.c index a65e52a0af62..51cb34ca65c5 100644 --- a/drivers/usb/gadget/aspeed_udc.c +++ b/drivers/usb/gadget/aspeed_udc.c @@ -580,10 +580,10 @@ static void ep_dequeue_locked(struct ast_ep* ep, struct ast_usb_request *req) { static void ep_dequeue_all(struct ast_ep* ep, int status) { struct ast_usb_request *req; - struct ast_usb_request *n; unsigned long flags; spin_lock_irqsave(&ep->lock, flags); - list_for_each_entry_safe(req, n, &ep->queue, queue) { + while (!list_empty(&ep->queue)) { + req = list_entry(ep->queue.next, struct ast_usb_request, queue); ep_dequeue_locked(ep, req); req->req.status = status; if(req->req.complete) { @@ -654,8 +654,14 @@ static void ep_txrx_check_done(struct ast_ep* ep) { spin_lock_irqsave(&ep->lock, flags); status = ep_hreadl(ep, DESC_STATUS); // if txrx complete; - if(!(status & 0xff) && - !list_empty(&ep->queue)) { + if (!(status & 0xff)) { + /* DMA is done */ + ep->dma_busy = 0; + /* if the list is empty, nothing to do */ + if (list_empty(&ep->queue)) { + spin_unlock_irqrestore(&ep->lock, flags); + return; + } req = list_entry(ep->queue.next, struct ast_usb_request, queue); if(!req->in_transit) { spin_unlock_irqrestore(&ep->lock, flags); @@ -663,7 +669,6 @@ static void ep_txrx_check_done(struct ast_ep* ep) { } //head rq completed req->in_transit = 0; - ep->dma_busy = 0; if(!ep->to_host) { req->lastpacket = (status >> 16) & 0x3ff; __cpuc_flush_kern_all(); diff --git a/drivers/watchdog/ast_wdt.c b/drivers/watchdog/ast_wdt.c index e599a557076f..cfe70a15587a 100644 --- a/drivers/watchdog/ast_wdt.c +++ b/drivers/watchdog/ast_wdt.c @@ -450,7 +450,7 @@ static int ast_wdt_open(struct inode *inode, struct file *file) static int ast_wdt_release(struct inode *inode, struct file *file) { - if (expect_close != 42 || !nowayout) + if (expect_close != 42 && !nowayout) { /* handles the case where the device is closed without the "magic * close" character (anything that is not 'V' qualifies -- see the |