diff options
author | Finn Thain <fthain@telegraphics.com.au> | 2009-12-04 20:30:42 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-01-18 11:48:10 -0500 |
commit | 02507a80b35edd720480540d917e9f92cc371009 (patch) | |
tree | 0da90f4cc680093926073f34fb9ddcb84f4a1aea /drivers/scsi/mac_esp.c | |
parent | f2818663c82b7297ff4aa38cbddb870dc02f7104 (diff) |
[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>
Diffstat (limited to 'drivers/scsi/mac_esp.c')
-rw-r--r-- | drivers/scsi/mac_esp.c | 95 |
1 files changed, 49 insertions, 46 deletions
diff --git a/drivers/scsi/mac_esp.c b/drivers/scsi/mac_esp.c index c24e86f07804..dd808ae942a1 100644 --- a/drivers/scsi/mac_esp.c +++ b/drivers/scsi/mac_esp.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <asm/irq.h> | 23 | #include <asm/irq.h> |
24 | #include <asm/dma.h> | 24 | #include <asm/dma.h> |
25 | |||
26 | #include <asm/macints.h> | 25 | #include <asm/macints.h> |
27 | #include <asm/macintosh.h> | 26 | #include <asm/macintosh.h> |
28 | 27 | ||
@@ -279,24 +278,27 @@ static void mac_esp_send_pdma_cmd(struct esp *esp, u32 addr, u32 esp_count, | |||
279 | * Programmed IO routines follow. | 278 | * Programmed IO routines follow. |
280 | */ | 279 | */ |
281 | 280 | ||
282 | static inline int mac_esp_wait_for_fifo(struct esp *esp) | 281 | static inline unsigned int mac_esp_wait_for_fifo(struct esp *esp) |
283 | { | 282 | { |
284 | int i = 500000; | 283 | int i = 500000; |
285 | 284 | ||
286 | do { | 285 | do { |
287 | if (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES) | 286 | unsigned int fbytes = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES; |
288 | return 0; | 287 | |
288 | if (fbytes) | ||
289 | return fbytes; | ||
289 | 290 | ||
290 | udelay(2); | 291 | udelay(2); |
291 | } while (--i); | 292 | } while (--i); |
292 | 293 | ||
293 | printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n", | 294 | printk(KERN_ERR PFX "FIFO is empty (sreg %02x)\n", |
294 | esp_read8(ESP_STATUS)); | 295 | esp_read8(ESP_STATUS)); |
295 | return 1; | 296 | return 0; |
296 | } | 297 | } |
297 | 298 | ||
298 | static inline int mac_esp_wait_for_intr(struct esp *esp) | 299 | static inline int mac_esp_wait_for_intr(struct esp *esp) |
299 | { | 300 | { |
301 | struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp); | ||
300 | int i = 500000; | 302 | int i = 500000; |
301 | 303 | ||
302 | do { | 304 | do { |
@@ -308,6 +310,7 @@ static inline int mac_esp_wait_for_intr(struct esp *esp) | |||
308 | } while (--i); | 310 | } while (--i); |
309 | 311 | ||
310 | printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg); | 312 | printk(KERN_ERR PFX "IRQ timeout (sreg %02x)\n", esp->sreg); |
313 | mep->error = 1; | ||
311 | return 1; | 314 | return 1; |
312 | } | 315 | } |
313 | 316 | ||
@@ -347,11 +350,10 @@ static inline int mac_esp_wait_for_intr(struct esp *esp) | |||
347 | static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, | 350 | static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, |
348 | u32 dma_count, int write, u8 cmd) | 351 | u32 dma_count, int write, u8 cmd) |
349 | { | 352 | { |
350 | unsigned long flags; | ||
351 | struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp); | 353 | struct mac_esp_priv *mep = MAC_ESP_GET_PRIV(esp); |
352 | u8 *fifo = esp->regs + ESP_FDATA * 16; | 354 | u8 *fifo = esp->regs + ESP_FDATA * 16; |
353 | 355 | ||
354 | local_irq_save(flags); | 356 | disable_irq(esp->host->irq); |
355 | 357 | ||
356 | cmd &= ~ESP_CMD_DMA; | 358 | cmd &= ~ESP_CMD_DMA; |
357 | mep->error = 0; | 359 | mep->error = 0; |
@@ -359,11 +361,35 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, | |||
359 | if (write) { | 361 | if (write) { |
360 | scsi_esp_cmd(esp, cmd); | 362 | scsi_esp_cmd(esp, cmd); |
361 | 363 | ||
362 | if (!mac_esp_wait_for_intr(esp)) { | 364 | while (1) { |
363 | if (mac_esp_wait_for_fifo(esp)) | 365 | unsigned int n; |
364 | esp_count = 0; | 366 | |
365 | } else { | 367 | n = mac_esp_wait_for_fifo(esp); |
366 | esp_count = 0; | 368 | if (!n) |
369 | break; | ||
370 | |||
371 | if (n > esp_count) | ||
372 | n = esp_count; | ||
373 | esp_count -= n; | ||
374 | |||
375 | MAC_ESP_PIO_LOOP("%2@,%0@+", n); | ||
376 | |||
377 | if (!esp_count) | ||
378 | break; | ||
379 | |||
380 | if (mac_esp_wait_for_intr(esp)) | ||
381 | break; | ||
382 | |||
383 | if (((esp->sreg & ESP_STAT_PMASK) != ESP_DIP) && | ||
384 | ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP)) | ||
385 | break; | ||
386 | |||
387 | esp->ireg = esp_read8(ESP_INTRPT); | ||
388 | if ((esp->ireg & (ESP_INTR_DC | ESP_INTR_BSERV)) != | ||
389 | ESP_INTR_BSERV) | ||
390 | break; | ||
391 | |||
392 | scsi_esp_cmd(esp, ESP_CMD_TI); | ||
367 | } | 393 | } |
368 | } else { | 394 | } else { |
369 | scsi_esp_cmd(esp, ESP_CMD_FLUSH); | 395 | 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, | |||
374 | MAC_ESP_PIO_LOOP("%0@+,%2@", esp_count); | 400 | MAC_ESP_PIO_LOOP("%0@+,%2@", esp_count); |
375 | 401 | ||
376 | scsi_esp_cmd(esp, cmd); | 402 | scsi_esp_cmd(esp, cmd); |
377 | } | ||
378 | |||
379 | while (esp_count) { | ||
380 | unsigned int n; | ||
381 | |||
382 | if (mac_esp_wait_for_intr(esp)) { | ||
383 | mep->error = 1; | ||
384 | break; | ||
385 | } | ||
386 | |||
387 | if (esp->sreg & ESP_STAT_SPAM) { | ||
388 | printk(KERN_ERR PFX "gross error\n"); | ||
389 | mep->error = 1; | ||
390 | break; | ||
391 | } | ||
392 | 403 | ||
393 | n = esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES; | 404 | while (esp_count) { |
394 | 405 | unsigned int n; | |
395 | if (write) { | ||
396 | if (n > esp_count) | ||
397 | n = esp_count; | ||
398 | esp_count -= n; | ||
399 | |||
400 | MAC_ESP_PIO_LOOP("%2@,%0@+", n); | ||
401 | 406 | ||
402 | if ((esp->sreg & ESP_STAT_PMASK) == ESP_STATP) | 407 | if (mac_esp_wait_for_intr(esp)) |
403 | break; | 408 | break; |
404 | 409 | ||
405 | if (esp_count) { | 410 | if (((esp->sreg & ESP_STAT_PMASK) != ESP_DOP) && |
406 | esp->ireg = esp_read8(ESP_INTRPT); | 411 | ((esp->sreg & ESP_STAT_PMASK) != ESP_MOP)) |
407 | if (esp->ireg & ESP_INTR_DC) | 412 | break; |
408 | break; | ||
409 | 413 | ||
410 | scsi_esp_cmd(esp, ESP_CMD_TI); | ||
411 | } | ||
412 | } else { | ||
413 | esp->ireg = esp_read8(ESP_INTRPT); | 414 | esp->ireg = esp_read8(ESP_INTRPT); |
414 | if (esp->ireg & ESP_INTR_DC) | 415 | if ((esp->ireg & (ESP_INTR_DC | ESP_INTR_BSERV)) != |
416 | ESP_INTR_BSERV) | ||
415 | break; | 417 | break; |
416 | 418 | ||
417 | n = MAC_ESP_FIFO_SIZE - n; | 419 | n = MAC_ESP_FIFO_SIZE - |
420 | (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES); | ||
418 | if (n > esp_count) | 421 | if (n > esp_count) |
419 | n = esp_count; | 422 | n = esp_count; |
420 | 423 | ||
@@ -429,7 +432,7 @@ static void mac_esp_send_pio_cmd(struct esp *esp, u32 addr, u32 esp_count, | |||
429 | } | 432 | } |
430 | } | 433 | } |
431 | 434 | ||
432 | local_irq_restore(flags); | 435 | enable_irq(esp->host->irq); |
433 | } | 436 | } |
434 | 437 | ||
435 | static int mac_esp_irq_pending(struct esp *esp) | 438 | static int mac_esp_irq_pending(struct esp *esp) |