Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

am53c974: BLAST residual handling

The am53c974 has an design issue where a single byte might be
left in the SCSI FIFO after a DMA transfer.
As the handling code is currently untested add a WARN_ON()
statement here.

Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Hannes Reinecke <hare@suse.de>
Signed-off-by: Christoph Hellwig <hch@lst.de>

authored by

Hannes Reinecke and committed by
Christoph Hellwig
6df388f2 3a7e7be2

+36
+6
drivers/scsi/am53c974.c
··· 200 200 } 201 201 pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_IDLE, ESP_DMA_CMD); 202 202 esp_dma_log("DMA blast done (%d tries, %d bytes left)\n", lim, resid); 203 + /* BLAST residual handling is currently untested */ 204 + if (WARN_ON_ONCE(resid == 1)) { 205 + struct esp_cmd_entry *ent = esp->active_cmd; 206 + 207 + ent->flags |= ESP_CMD_FLAG_RESIDUAL; 208 + } 203 209 } 204 210 205 211 static void pci_esp_dma_invalidate(struct esp *esp)
+29
drivers/scsi/esp_scsi.c
··· 1334 1334 bytes_sent = esp->data_dma_len; 1335 1335 bytes_sent -= ecount; 1336 1336 1337 + /* 1338 + * The am53c974 has a DMA 'pecularity'. The doc states: 1339 + * In some odd byte conditions, one residual byte will 1340 + * be left in the SCSI FIFO, and the FIFO Flags will 1341 + * never count to '0 '. When this happens, the residual 1342 + * byte should be retrieved via PIO following completion 1343 + * of the BLAST operation. 1344 + */ 1345 + if (fifo_cnt == 1 && ent->flags & ESP_CMD_FLAG_RESIDUAL) { 1346 + size_t count = 1; 1347 + size_t offset = bytes_sent; 1348 + u8 bval = esp_read8(ESP_FDATA); 1349 + 1350 + if (ent->flags & ESP_CMD_FLAG_AUTOSENSE) 1351 + ent->sense_ptr[bytes_sent] = bval; 1352 + else { 1353 + struct esp_cmd_priv *p = ESP_CMD_PRIV(cmd); 1354 + u8 *ptr; 1355 + 1356 + ptr = scsi_kmap_atomic_sg(p->cur_sg, p->u.num_sg, 1357 + &offset, &count); 1358 + if (likely(ptr)) { 1359 + *(ptr + offset) = bval; 1360 + scsi_kunmap_atomic_sg(ptr); 1361 + } 1362 + } 1363 + bytes_sent += fifo_cnt; 1364 + ent->flags &= ~ESP_CMD_FLAG_RESIDUAL; 1365 + } 1337 1366 if (!(ent->flags & ESP_CMD_FLAG_WRITE)) 1338 1367 bytes_sent -= fifo_cnt; 1339 1368
+1
drivers/scsi/esp_scsi.h
··· 269 269 #define ESP_CMD_FLAG_WRITE 0x01 /* DMA is a write */ 270 270 #define ESP_CMD_FLAG_ABORT 0x02 /* being aborted */ 271 271 #define ESP_CMD_FLAG_AUTOSENSE 0x04 /* Doing automatic REQUEST_SENSE */ 272 + #define ESP_CMD_FLAG_RESIDUAL 0x08 /* AM53c974 BLAST residual */ 272 273 273 274 u8 tag[2]; 274 275 u8 orig_tag[2];