mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-04-22 14:23:58 +00:00
[SCSI] mac_esp: fix PIO mode, take 2
The mac_esp PIO algorithm no longer works in 2.6.31 and crashes my Centris 660av. So here's a better one. Also, force async with esp_set_offset() rather than esp_slave_configure(). One of the SCSI drives I tested still doesn't like the PIO mode and fails with "esp: esp0: Reconnect IRQ2 timeout" (the same drive works fine in PDMA mode). This failure happens when esp_reconnect_with_tag() tries to read in two tag bytes but the chip only provides one (0x20). I don't know what causes this. I decided not to waste any more time trying to fix it because the best solution is to rip out the PIO mode altogether and use the DMA engine. Signed-off-by: Finn Thain <fthain@telegraphics.com.au> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
f2818663c8
commit
02507a80b3
2 changed files with 53 additions and 56 deletions
|
@ -1449,9 +1449,6 @@ static void esp_msgin_sdtr(struct esp *esp, struct esp_target_data *tp)
|
||||||
if (offset > 15)
|
if (offset > 15)
|
||||||
goto do_reject;
|
goto do_reject;
|
||||||
|
|
||||||
if (esp->flags & ESP_FLAG_DISABLE_SYNC)
|
|
||||||
offset = 0;
|
|
||||||
|
|
||||||
if (offset) {
|
if (offset) {
|
||||||
int one_clock;
|
int one_clock;
|
||||||
|
|
||||||
|
@ -2405,12 +2402,6 @@ static int esp_slave_configure(struct scsi_device *dev)
|
||||||
struct esp_target_data *tp = &esp->target[dev->id];
|
struct esp_target_data *tp = &esp->target[dev->id];
|
||||||
int goal_tags, queue_depth;
|
int goal_tags, queue_depth;
|
||||||
|
|
||||||
if (esp->flags & ESP_FLAG_DISABLE_SYNC) {
|
|
||||||
/* Bypass async domain validation */
|
|
||||||
dev->ppr = 0;
|
|
||||||
dev->sdtr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
goal_tags = 0;
|
goal_tags = 0;
|
||||||
|
|
||||||
if (dev->tagged_supported) {
|
if (dev->tagged_supported) {
|
||||||
|
@ -2660,7 +2651,10 @@ static void esp_set_offset(struct scsi_target *target, int offset)
|
||||||
struct esp *esp = shost_priv(host);
|
struct esp *esp = shost_priv(host);
|
||||||
struct esp_target_data *tp = &esp->target[target->id];
|
struct esp_target_data *tp = &esp->target[target->id];
|
||||||
|
|
||||||
tp->nego_goal_offset = offset;
|
if (esp->flags & ESP_FLAG_DISABLE_SYNC)
|
||||||
|
tp->nego_goal_offset = 0;
|
||||||
|
else
|
||||||
|
tp->nego_goal_offset = offset;
|
||||||
tp->flags |= ESP_TGT_CHECK_NEGO;
|
tp->flags |= ESP_TGT_CHECK_NEGO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/dma.h>
|
#include <asm/dma.h>
|
||||||
|
|
||||||
#include <asm/macints.h>
|
#include <asm/macints.h>
|
||||||
#include <asm/macintosh.h>
|
#include <asm/macintosh.h>
|
||||||
|
|
||||||
|
@ -279,24 +278,27 @@ static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count,
|
||||||
* Programmed IO routines follow.
|
* Programmed IO routines follow.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline int mac_esp_wait_for_fifo(struct esp *esp)
|
static inline unsigned int mac_esp_wait_for_fifo(struct esp *esp)
|
||||||
{
|
{
|
||||||
int i = 500000;
|
int i = 500000;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES)
|
unsigned int fbytes = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES;
|
||||||
return 0;
|
|
||||||
|
if (fbytes)
|
||||||
|
return fbytes;
|
||||||
|
|
||||||
udelay(2);
|
udelay(2);
|
||||||
} while (--i);
|
} while (--i);
|
||||||
|
|
||||||
printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n",
|
printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n",
|
||||||
esp_read8(ESP_STATUS));
|
esp_read8(ESP_STATUS));
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int mac_esp_wait_for_intr(struct esp *esp)
|
static inline int mac_esp_wait_for_intr(struct esp *esp)
|
||||||
{
|
{
|
||||||
|
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
|
||||||
int i = 500000;
|
int i = 500000;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
@ -308,6 +310,7 @@ static inline int mac_esp_wait_for_intr(struct esp *esp)
|
||||||
} while (--i);
|
} while (--i);
|
||||||
|
|
||||||
printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg);
|
printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg);
|
||||||
|
mep->error = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -347,11 +350,10 @@ static inline int mac_esp_wait_for_intr(struct esp *esp)
|
||||||
static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
|
static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
|
||||||
u32 dma_count, int write, u8 cmd)
|
u32 dma_count, int write, u8 cmd)
|
||||||
{
|
{
|
||||||
unsigned long flags;
|
|
||||||
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
|
struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp);
|
||||||
u8 *fifo = esp->regs + ESP_FDATA * 16;
|
u8 *fifo = esp->regs + ESP_FDATA * 16;
|
||||||
|
|
||||||
local_irq_save(flags);
|
disable_irq(esp->host->irq);
|
||||||
|
|
||||||
cmd &= ~ESP_CMD_DMA;
|
cmd &= ~ESP_CMD_DMA;
|
||||||
mep->error = 0;
|
mep->error = 0;
|
||||||
|
@ -359,11 +361,35 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
|
||||||
if (write) {
|
if (write) {
|
||||||
scsi_esp_cmd(esp, cmd);
|
scsi_esp_cmd(esp, cmd);
|
||||||
|
|
||||||
if (!mac_esp_wait_for_intr(esp)) {
|
while (1) {
|
||||||
if (mac_esp_wait_for_fifo(esp))
|
unsigned int n;
|
||||||
esp_count = 0;
|
|
||||||
} else {
|
n = mac_esp_wait_for_fifo(esp);
|
||||||
esp_count = 0;
|
if (!n)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (n > esp_count)
|
||||||
|
n = esp_count;
|
||||||
|
esp_count -= n;
|
||||||
|
|
||||||
|
MAC_ESP_PIO_LOOP("%2@,%0@+", n);
|
||||||
|
|
||||||
|
if (!esp_count)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (mac_esp_wait_for_intr(esp))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (((esp->sreg & ESP_STAT_PMASK) != ESP_DIP) &&
|
||||||
|
((esp->sreg & ESP_STAT_PMASK) != ESP_MIP))
|
||||||
|
break;
|
||||||
|
|
||||||
|
esp->ireg = esp_read8(ESP_INTRPT);
|
||||||
|
if ((esp->ireg & (ESP_INTR_DC | ESP_INTR_BSERV)) !=
|
||||||
|
ESP_INTR_BSERV)
|
||||||
|
break;
|
||||||
|
|
||||||
|
scsi_esp_cmd(esp, ESP_CMD_TI);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
|
scsi_esp_cmd(esp, ESP_CMD_FLUSH);
|
||||||
|
@ -374,47 +400,24 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
|
||||||
MAC_ESP_PIO_LOOP("%0@+,%2@", esp_count);
|
MAC_ESP_PIO_LOOP("%0@+,%2@", esp_count);
|
||||||
|
|
||||||
scsi_esp_cmd(esp, cmd);
|
scsi_esp_cmd(esp, cmd);
|
||||||
}
|
|
||||||
|
|
||||||
while (esp_count) {
|
while (esp_count) {
|
||||||
unsigned int n;
|
unsigned int n;
|
||||||
|
|
||||||
if (mac_esp_wait_for_intr(esp)) {
|
if (mac_esp_wait_for_intr(esp))
|
||||||
mep->error = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (esp->sreg & ESP_STAT_SPAM) {
|
|
||||||
printk(KERN_ERR PFX "gross error\n");
|
|
||||||
mep->error = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
n = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES;
|
|
||||||
|
|
||||||
if (write) {
|
|
||||||
if (n > esp_count)
|
|
||||||
n = esp_count;
|
|
||||||
esp_count -= n;
|
|
||||||
|
|
||||||
MAC_ESP_PIO_LOOP("%2@,%0@+", n);
|
|
||||||
|
|
||||||
if ((esp->sreg & ESP_STAT_PMASK) == ESP_STATP)
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (esp_count) {
|
if (((esp->sreg & ESP_STAT_PMASK) != ESP_DOP) &&
|
||||||
esp->ireg = esp_read8(ESP_INTRPT);
|
((esp->sreg & ESP_STAT_PMASK) != ESP_MOP))
|
||||||
if (esp->ireg & ESP_INTR_DC)
|
break;
|
||||||
break;
|
|
||||||
|
|
||||||
scsi_esp_cmd(esp, ESP_CMD_TI);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
esp->ireg = esp_read8(ESP_INTRPT);
|
esp->ireg = esp_read8(ESP_INTRPT);
|
||||||
if (esp->ireg & ESP_INTR_DC)
|
if ((esp->ireg & (ESP_INTR_DC | ESP_INTR_BSERV)) !=
|
||||||
|
ESP_INTR_BSERV)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
n = MAC_ESP_FIFO_SIZE - n;
|
n = MAC_ESP_FIFO_SIZE -
|
||||||
|
(esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES);
|
||||||
if (n > esp_count)
|
if (n > esp_count)
|
||||||
n = esp_count;
|
n = esp_count;
|
||||||
|
|
||||||
|
@ -429,7 +432,7 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
local_irq_restore(flags);
|
enable_irq(esp->host->irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mac_esp_irq_pending(struct esp *esp)
|
static int mac_esp_irq_pending(struct esp *esp)
|
||||||
|
|
Loading…
Add table
Reference in a new issue