Make sure fifo does not need serviced before handling
other interrupt sources

Signed-off-by: Troy Kisky <[EMAIL PROTECTED]>
---
 drivers/mmc/host/davinci_mmc.c |  454 +++++++++++++++++++---------------------
 1 files changed, 218 insertions(+), 236 deletions(-)

diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c
index 6b1182c..9a70c97 100755
--- a/drivers/mmc/host/davinci_mmc.c
+++ b/drivers/mmc/host/davinci_mmc.c
@@ -960,283 +960,265 @@ static void mmc_davinci_cmd_done(struct 
mmc_davinci_host *host,
        }
 }
 
-static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
+static inline int handle_core_command(
+               struct mmc_davinci_host *host, unsigned int status)
 {
-       struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id;
-       u16 status;
-       int end_command;
-       int end_transfer;
+       int end_command = 0;
+       int end_transfer = 0;
+       unsigned int qstatus;
        unsigned long flags;
 
-       if (host->is_core_command) {
-               if (host->cmd == NULL && host->data == NULL) {
-                       status = mmcsd_regs->mmc_st0;
-                       dev_dbg(&mmc_dev, "Spurious interrupt 0x%04x\r\n",
-                               status);
-                       /* Disable the interrupt from mmcsd */
-                       mmcsd_regs->mmc_im = 0;
-                       return IRQ_HANDLED;
+       if ((is_card_initialized) && (new_card_state == 0)) {
+               if (host->cmd) {
+                       host->cmd->error = -ETIMEDOUT;
+                       mmc_davinci_cmd_done(host, host->cmd);
                }
+               dev_dbg(&mmc_dev, "From code segment "
+                       "excuted when card removed\n");
+               return -1;
        }
-       end_command = 0;
-       end_transfer = 0;
 
-       status = mmcsd_regs->mmc_st0;
-       if (status == 0)
-               return IRQ_HANDLED;
+       qstatus = status;
+       while (1) {
+               if ((status & MMCSD_EVENT_WRITE) &&
+                               (host->data_dir == DAVINCI_MMC_DATADIR_WRITE)
+                               && (host->bytes_left > 0)) {
+                       /* Buffer almost empty */
+                       davinci_fifo_data_trans(host, mmcsd_cfg.rw_threshold);
+               }
 
-       if (host->is_core_command) {
-               if (is_card_initialized) {
-                       if (new_card_state == 0) {
-                               if (host->cmd) {
-                                       host->cmd->error = -ETIMEDOUT;
-                                       mmc_davinci_cmd_done(host, host->cmd);
-                               }
-                               dev_dbg(&mmc_dev,
-                                       "From code segment excuted when card 
removed\n");
-                               return IRQ_HANDLED;
-                       }
+               if ((status & MMCSD_EVENT_READ) &&
+                               (host->data_dir == DAVINCI_MMC_DATADIR_READ)
+                               && (host->bytes_left > 0)) {
+                       /* Buffer almost empty */
+                       davinci_fifo_data_trans(host, mmcsd_cfg.rw_threshold);
                }
+               status = mmcsd_regs->mmc_st0;
+               if (!status)
+                       break;
+               qstatus |= status;
+               if (host->data == NULL) {
+                       dev_dbg(&mmc_dev, "Status is %x at end of ISR "
+                               "when host->data is NULL", status);
+                       break;
+               }
+       }
 
-               while (status != 0) {
-                       if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) {
-                               if (status & MMCSD_EVENT_WRITE) {
-                                       /* Buffer almost empty */
-                                       if (host->bytes_left > 0)
-                                               davinci_fifo_data_trans(host,
-                                                       mmcsd_cfg.rw_threshold);
-                               }
+       if (qstatus & MMCSD_EVENT_BLOCK_XFERRED) {
+               /* Block sent/received */
+               if (host->data != NULL) {
+                       if ((host->do_dma == 0) && (host->bytes_left > 0)) {
+                               /* if datasize<mmcsd_cfg.rw_threshold
+                                * no RX ints are generated
+                                */
+                               davinci_fifo_data_trans(host,
+                                               mmcsd_cfg.rw_threshold);
                        }
+                       end_transfer = 1;
+               } else {
+                       dev_warn(&mmc_dev, "TC:host->data is NULL\n");
+               }
+       }
 
-                       if (host->data_dir == DAVINCI_MMC_DATADIR_READ) {
-                               if (status & MMCSD_EVENT_READ) {
-                                       /* Buffer almost empty */
-                                       if (host->bytes_left > 0)
-                                               davinci_fifo_data_trans(host,
-                                                       mmcsd_cfg.rw_threshold);
-                               }
-                       }
+       if (qstatus & MMCSD_EVENT_ERROR_DATATIMEOUT) {
+               /* Data timeout */
+               if ((host->data) && (new_card_state != 0)) {
+                       host->data->error = -ETIMEDOUT;
+                       spin_lock_irqsave(&mmc_lock, flags);
+                       is_card_removed = 1;
+                       new_card_state = 0;
+                       is_card_initialized = 0;
+                       spin_unlock_irqrestore(&mmc_lock, flags);
+                       dev_dbg(&mmc_dev, "MMCSD: Data timeout, "
+                               "CMD%d and status is %x\r\n",
+                               host->cmd->opcode, status);
 
-                       if (status & MMCSD_EVENT_BLOCK_XFERRED) {
-                               /* Block sent/received */
-                               if (host->data != NULL) {
-                                       if (host->do_dma == 1) {
-                                               end_transfer = 1;
-                                       } else {
-                                               /* if datasize<32 no RX ints 
are generated */
-                                               if (host->bytes_left > 0) {
-                                                       davinci_fifo_data_trans
-                                                         (host,
-                                                         mmcsd_cfg.rw_threshold
-                                                         );
-                                               }
-                                               end_transfer = 1;
-                                       }
-                               } else {
-                                       dev_warn(&mmc_dev,
-                                                "TC:host->data is NULL\n");
-                               }
-                       }
+                       if (host->cmd)
+                               host->cmd->error = -ETIMEDOUT;
+                       end_transfer = 1;
+               }
+       }
 
-                       if (status & MMCSD_EVENT_ERROR_DATATIMEOUT) {
-                               /* Data timeout */
-                               if ((host->data) && (new_card_state != 0)) {
-                                       host->data->error = -ETIMEDOUT;
-                                       spin_lock_irqsave(&mmc_lock, flags);
-                                       is_card_removed = 1;
-                                       new_card_state = 0;
-                                       is_card_initialized = 0;
-                                       spin_unlock_irqrestore(&mmc_lock,
-                                               flags);
-                                       dev_dbg(&mmc_dev,
-                                               "MMCSD: Data timeout, CMD%d and 
status is %x\r\n",
-                                               host->cmd->opcode, status);
-
-                                       if (host->cmd) {
-                                               host->cmd->error = -ETIMEDOUT;
-                                       }
-                                       end_transfer = 1;
-                               }
-                       }
+       if (qstatus & MMCSD_EVENT_ERROR_DATACRC) {
+               /* DAT line portion is disabled and in reset state */
+               mmcsd_regs->mmc_ctl |= (1 << 1);
+               udelay(10);
+               mmcsd_regs->mmc_ctl &= ~(1 << 1);
+
+               /* Data CRC error */
+               if (host->data) {
+                       host->data->error = -EILSEQ;
+                       dev_dbg(&mmc_dev, "MMCSD: Data CRC error, "
+                               "bytes left %d\r\n", host->bytes_left);
+                       end_transfer = 1;
+               } else {
+                       dev_dbg(&mmc_dev, "MMCSD: Data CRC error\r\n");
+               }
+       }
 
-                       if (status & MMCSD_EVENT_ERROR_DATACRC) {
-                               /* DAT line portion is diabled and in reset 
state */
-                               mmcsd_regs->mmc_ctl =
-                                   mmcsd_regs->mmc_ctl | (1 << 1);
-                               udelay(10);
-                               mmcsd_regs->mmc_ctl =
-                                   mmcsd_regs->mmc_ctl & ~(1 << 1);
-
-                               /* Data CRC error */
-                               if (host->data) {
-                                       host->data->error = -EILSEQ;
-                                       dev_dbg(&mmc_dev,
-                                               "MMCSD: Data CRC error, bytes 
left %d\r\n",
-                                               host->bytes_left);
-                                       end_transfer = 1;
-                               } else {
-                                       dev_dbg(&mmc_dev,
-                                               "MMCSD: Data CRC error\r\n");
-                               }
+       if (qstatus & MMCSD_EVENT_ERROR_CMDTIMEOUT) {
+               if (host->do_dma)
+                       davinci_abort_dma(host);
+
+               /* Command timeout */
+               if (host->cmd) {
+                       /* Timeouts are normal in case of
+                        * MMC_SEND_STATUS
+                        */
+                       if (host->cmd->opcode != MMC_ALL_SEND_CID) {
+                               dev_dbg(&mmc_dev, "MMCSD: CMD%d timeout,"
+                                       " status %x\r\n", host->cmd->opcode,
+                                       status);
+                               spin_lock_irqsave(&mmc_lock, flags);
+                               new_card_state = 0;
+                               is_card_initialized = 0;
+                               spin_unlock_irqrestore(&mmc_lock, flags);
                        }
+                       host->cmd->error = -ETIMEDOUT;
+                       end_command = 1;
+               }
+       }
 
-                       if (status & MMCSD_EVENT_ERROR_CMDTIMEOUT) {
-                               if (host->do_dma)
-                                       /* abort DMA transfer */
-                                       davinci_abort_dma(host);
-
-                               /* Command timeout */
-                               if (host->cmd) {
-                                       /* Timeouts are normal in case of
-                                        * MMC_SEND_STATUS
-                                        */
-                                       if (host->cmd->opcode !=
-                                                       MMC_ALL_SEND_CID) {
-                                               dev_dbg(&mmc_dev,
-                                                       "MMCSD: CMD%d timeout,"
-                                                       " status %x\r\n",
-                                                       host->cmd->opcode,
-                                                       status);
-                                               spin_lock_irqsave(&mmc_lock,
-                                                       flags);
-                                               new_card_state = 0;
-                                               is_card_initialized = 0;
-                                               spin_unlock_irqrestore(
-                                                       &mmc_lock, flags);
-                                       }
-                                       host->cmd->error = -ETIMEDOUT;
-                                       end_command = 1;
-
-                               }
-                       }
+       if (qstatus & MMCSD_EVENT_ERROR_CMDCRC) {
+               /* Command CRC error */
+               dev_dbg(&mmc_dev, "Command CRC error\r\n");
+               if (host->cmd) {
+                       /* Ignore CMD CRC errors during high speed operation */
+                       if (host->mmc->ios.clock <= 25000000)
+                               host->cmd->error = -EILSEQ;
+                       end_command = 1;
+               }
+       }
 
-                       if (status & MMCSD_EVENT_ERROR_CMDCRC) {
-                               /* Command CRC error */
-                               dev_dbg(&mmc_dev, "Command CRC error\r\n");
-                               if (host->cmd) {
-                                       /* Ignore CMD CRC errors during high 
speed operation */
-                                       if (host->mmc->ios.clock <= 25000000) {
-                                               host->cmd->error = -EILSEQ;
-                                       }
-                                       end_command = 1;
-                               }
-                       }
+       if (qstatus & MMCSD_EVENT_EOFCMD) {
+               /* End of command phase */
+               end_command = 1;
+       }
 
-                       if (status & MMCSD_EVENT_EOFCMD) {
-                               /* End of command phase */
-                               end_command = 1;
-                       }
+       if (end_command)
+               mmc_davinci_cmd_done(host, host->cmd);
+       if (end_transfer)
+               mmc_davinci_xfer_done(host, host->data);
+       return 0;
+}
 
-                       if (host->data == NULL) {
-                               status = mmcsd_regs->mmc_st0;
-                               if (status != 0) {
-                                       dev_dbg(&mmc_dev,
-                                               "Status is %x at end of ISR 
when host->data is NULL",
-                                               status);
-                                       status = 0;
+static inline void handle_other_commands(
+               struct mmc_davinci_host *host, unsigned int status)
+{
+       unsigned long flags;
+       if (host->cmd_code == 13) {
+               if (status & MMCSD_EVENT_EOFCMD) {
+                       spin_lock_irqsave(&mmc_lock, flags);
+                       new_card_state = 1;
+                       spin_unlock_irqrestore(&mmc_lock, flags);
 
-                               }
-                       } else {
-                               status = mmcsd_regs->mmc_st0;
-                       }
+               } else {
+                       spin_lock_irqsave(&mmc_lock, flags);
+                       is_card_removed = 1;
+                       new_card_state = 0;
+                       is_card_initialized = 0;
+                       spin_unlock_irqrestore(&mmc_lock, flags);
                }
 
-               if (end_command)
-                       mmc_davinci_cmd_done(host, host->cmd);
-               if (end_transfer)
-                       mmc_davinci_xfer_done(host, host->data);
+               spin_lock_irqsave(&mmc_lock, flags);
+               is_card_detect_progress = 0;
+               spin_unlock_irqrestore(&mmc_lock, flags);
 
-       } else {
-               if (host->cmd_code == 13) {
-                       if (status & MMCSD_EVENT_EOFCMD) {
-                               spin_lock_irqsave(&mmc_lock, flags);
-                               new_card_state = 1;
-                               spin_unlock_irqrestore(&mmc_lock, flags);
+               if (is_req_queued_up) {
+                       mmc_davinci_request(que_mmc_host, que_mmc_request);
+                       spin_lock_irqsave(&mmc_lock, flags);
+                       is_req_queued_up = 0;
+                       spin_unlock_irqrestore(&mmc_lock, flags);
+               }
 
-                       } else {
-                               spin_lock_irqsave(&mmc_lock, flags);
-                               is_card_removed = 1;
-                               new_card_state = 0;
-                               is_card_initialized = 0;
-                               spin_unlock_irqrestore(&mmc_lock, flags);
-                       }
+       }
 
+       if (host->cmd_code == 1 || host->cmd_code == 55) {
+               if (status & MMCSD_EVENT_EOFCMD) {
                        spin_lock_irqsave(&mmc_lock, flags);
-                       is_card_detect_progress = 0;
+                       is_card_removed = 0;
+                       new_card_state = 1;
+                       is_card_initialized = 0;
                        spin_unlock_irqrestore(&mmc_lock, flags);
+               } else {
 
-                       if (is_req_queued_up) {
-                               mmc_davinci_request(que_mmc_host,
-                                               que_mmc_request);
-                               spin_lock_irqsave(&mmc_lock, flags);
-                               is_req_queued_up = 0;
-                               spin_unlock_irqrestore(&mmc_lock, flags);
-                       }
+                       spin_lock_irqsave(&mmc_lock, flags);
+                       is_card_removed = 1;
+                       new_card_state = 0;
+                       is_card_initialized = 0;
+                       spin_unlock_irqrestore(&mmc_lock, flags);
+               }
+
+               spin_lock_irqsave(&mmc_lock, flags);
+               is_card_detect_progress = 0;
+               spin_unlock_irqrestore(&mmc_lock, flags);
 
+               if (is_req_queued_up) {
+                       mmc_davinci_request(que_mmc_host, que_mmc_request);
+                       spin_lock_irqsave(&mmc_lock, flags);
+                       is_req_queued_up = 0;
+                       spin_unlock_irqrestore(&mmc_lock, flags);
                }
+       }
 
-               if (host->cmd_code == 1 || host->cmd_code == 55) {
-                       if (status & MMCSD_EVENT_EOFCMD) {
-                               spin_lock_irqsave(&mmc_lock, flags);
-                               is_card_removed = 0;
-                               new_card_state = 1;
-                               is_card_initialized = 0;
-                               spin_unlock_irqrestore(&mmc_lock, flags);
-                       } else {
+       if (host->cmd_code == 0) {
+               if (status & MMCSD_EVENT_EOFCMD) {
+                       static int flag_sd_mmc;
+                       host->is_core_command = 0;
 
-                               spin_lock_irqsave(&mmc_lock, flags);
-                               is_card_removed = 1;
-                               new_card_state = 0;
-                               is_card_initialized = 0;
-                               spin_unlock_irqrestore(&mmc_lock, flags);
+                       if (flag_sd_mmc) {
+                               flag_sd_mmc = 0;
+                               host->cmd_code = 1;
+                               /* Issue cmd1 */
+                               mmcsd_regs->mmc_arghl = 0x80300000;
+                               mmcsd_regs->mmc_cmd = 0x00000601;
+                       } else {
+                               flag_sd_mmc = 1;
+                               host->cmd_code = 55;
+                               /* Issue cmd55 */
+                               mmcsd_regs->mmc_arghl = 0x0;
+                               mmcsd_regs->mmc_cmd = (0x0 | (1 << 9) | 55);
                        }
 
+                       dev_dbg(&mmc_dev, "MMC-Probing mmc with cmd%d\n",
+                               host->cmd_code);
+               } else {
                        spin_lock_irqsave(&mmc_lock, flags);
+                       new_card_state = 0;
+                       is_card_initialized = 0;
                        is_card_detect_progress = 0;
                        spin_unlock_irqrestore(&mmc_lock, flags);
-
-                       if (is_req_queued_up) {
-                               mmc_davinci_request(que_mmc_host,
-                                               que_mmc_request);
-                               spin_lock_irqsave(&mmc_lock, flags);
-                               is_req_queued_up = 0;
-                               spin_unlock_irqrestore(&mmc_lock, flags);
-                       }
                }
+       }
+}
 
-               if (host->cmd_code == 0) {
-                       if (status & MMCSD_EVENT_EOFCMD) {
-                               static int flag_sd_mmc;
-                               host->is_core_command = 0;
-
-                               if (flag_sd_mmc) {
-                                       flag_sd_mmc = 0;
-                                       host->cmd_code = 1;
-                                       /* Issue cmd1 */
-                                       mmcsd_regs->mmc_arghl = 0x80300000;
-                                       mmcsd_regs->mmc_cmd = 0x00000601;
-                               } else {
-                                       flag_sd_mmc = 1;
-                                       host->cmd_code = 55;
-                                       /* Issue cmd55 */
-                                       mmcsd_regs->mmc_arghl = 0x0;
-                                       mmcsd_regs->mmc_cmd =
-                                           ((0x0 | (1 << 9) | 55));
-                               }
-
-                               dev_dbg(&mmc_dev,
-                                       "MMC-Probing mmc with cmd%d\n",
-                                       host->cmd_code);
-                       } else {
-                               spin_lock_irqsave(&mmc_lock, flags);
-                               new_card_state = 0;
-                               is_card_initialized = 0;
-                               is_card_detect_progress = 0;
-                               spin_unlock_irqrestore(&mmc_lock, flags);
-                       }
-               }
+static irqreturn_t mmc_davinci_irq(int irq, void *dev_id)
+{
+       struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id;
+       unsigned int status;
 
+       if (host->is_core_command) {
+               if (host->cmd == NULL && host->data == NULL) {
+                       status = mmcsd_regs->mmc_st0;
+                       dev_dbg(&mmc_dev, "Spurious interrupt 0x%04x\r\n",
+                               status);
+                       /* Disable the interrupt from mmcsd */
+                       mmcsd_regs->mmc_im = 0;
+                       return IRQ_HANDLED;
+               }
        }
+       do {
+               status = mmcsd_regs->mmc_st0;
+               if (status == 0)
+                       break;
+
+               if (host->is_core_command) {
+                       if (handle_core_command(host, status))
+                               break;
+               } else {
+                       handle_other_commands(host, status);
+               }
+       } while (1);
        return IRQ_HANDLED;
 }
 
-- 
1.5.4

_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to