Re-implement am53c974 driver
Subsystems (2)
v3 cover Re-implement am53c974 driver
Hi all,
having found some issues with the current tmscsim driver I looked at the code and found is really awkward to clean up.
Seeing that the am53c974 chip is actually based on the 'ESP' chip design I've re-implemented it based on the common esp_scsi routines. This new driver (cunningly named 'am53c974') provides all features found on the tmscsim driver, with the goal of obsoleting the old tmscsim driver.
Tested with Tekram DC390 and qemu esp-scsi.
Changes to v1:
- Include suggestions from Paolo Bonzini
- Remove the tmscsim driver
- Update MAINTAINERS file
Changes to v2:
- Include review from David Miller
- Include review from Christoph Hellwig
- Add Reviewed-by/Acked-by tags where applicable
Hannes Reinecke (11):
esp_scsi: spellcheck 'driver'
esp_scsi: make number of tags configurable
esp_scsi: convert to dev_printk
esp_scsi: debug event and command
esp_scsi: read status registers
esp_scsi: use FIFO for command submission
scsi: add 'am53c974' driver
am53c974: BLAST residual handling
esp: correctly detect am53c974
esp: enable CONFIG2_FENAB for am53c974 Replace tmscsim by am53c974
Paolo Bonzini (1):
esp_scsi: let DMA driver provide a config2 value
MAINTAINERS | 7 +- drivers/scsi/Kconfig | 8 +- drivers/scsi/Makefile | 2 +- drivers/scsi/am53c974.c | 586 +++++++++++ drivers/scsi/esp_scsi.c | 411 +++++--- drivers/scsi/esp_scsi.h | 22 +- drivers/scsi/tmscsim.c | 2626 ----------------------------------------------- drivers/scsi/tmscsim.h | 549 ---------- 8 files changed, 859 insertions(+), 3352 deletions(-) create mode 100644 drivers/scsi/am53c974.c delete mode 100644 drivers/scsi/tmscsim.c delete mode 100644 drivers/scsi/tmscsim.h
Signature · 1 line
1.8.5.2
PATCH v3 1/12 esp_scsi: spellcheck 'driver'
--- drivers/scsi/esp_scsi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/esp_scsi.h +1 -1
@@ -1,4 +1,4 @@ -/* esp_scsi.h: Defines and structures for the ESP drier. +/* esp_scsi.h: Defines and structures for the ESP driver. * * Copyright (C) 2007 David S. Miller ([email protected]) */
Signature · 1 line
1.8.5.2
PATCH v3 2/12 esp_scsi: make number of tags configurable
In reply to Hannes ReineckeAdd a field 'num_tags' to the esp structure to allow drivers to overwrite the number of avialable tags if required. Default is ESP_DEFAULT_TAGS.
--- drivers/scsi/esp_scsi.c | 12 ++++++------ drivers/scsi/esp_scsi.h | 3 +-- 2 files changed, 7 insertions(+), 8 deletions(-)
drivers/scsi/esp_scsi.c +6 -6
@@ -2317,6 +2317,10 @@ int scsi_esp_register(struct esp *esp, struct device *dev)static int instance;int err; +if (!esp->num_tags) + esp->num_tags =ESP_DEFAULT_TAGS ; +else if (esp->num_tags >=ESP_MAX_TAG ) + esp->num_tags =ESP_MAX_TAG -1 ; esp->host->transportt = esp_transport_template; esp->host->max_lun =ESP_MAX_LUN ; esp->host->cmd_per_lun =2 ;
@@ -2403,12 +2407,8 @@ static int esp_slave_configure(struct scsi_device *dev)struct esp *esp =shost_priv (dev->host);struct esp_target_data *tp = &esp->target[dev->id]; -if (dev->tagged_supported) { -/* XXX make this configurable somehow XXX */ -int goal_tags =min (ESP_DEFAULT_TAGS ,ESP_MAX_TAG ); - -scsi_adjust_queue_depth (dev, goal_tags); - } +if (dev->tagged_supported) +scsi_adjust_queue_depth (dev, esp->num_tags); tp->flags |=ESP_TGT_DISCONNECT ;
drivers/scsi/esp_scsi.h +1 -2
@@ -283,7 +283,6 @@ struct esp_cmd_entry {struct completion *eh_done; }; -/* XXX make this configurable somehow XXX */ #define ESP_DEFAULT_TAGS 16#define ESP_MAX_TARGET 16
@@ -445,7 +444,7 @@ struct esp {u8 prev_soff;u8 prev_stp;u8 prev_cfg3; -u8 __pad; +u8 num_tags;struct list_head esp_cmd_pool;
Signature · 1 line
1.8.5.2
PATCH v3 3/12 esp_scsi: convert to dev_printk
In reply to Hannes ReineckeUse dev_printk functions for correct device annotations.
--- drivers/scsi/esp_scsi.c | 212 ++++++++++++++++++++++++------------------------ 1 file changed, 106 insertions(+), 106 deletions(-)
drivers/scsi/esp_scsi.c +106 -106
@@ -52,52 +52,52 @@ static u32 esp_debug; #define esp_log_intr(f, a...) \ do { if (esp_debug & ESP_DEBUG_INTR) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_reset(f, a...) \ do { if (esp_debug & ESP_DEBUG_RESET) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_msgin(f, a...) \ do { if (esp_debug & ESP_DEBUG_MSGIN) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_msgout(f, a...) \ do { if (esp_debug & ESP_DEBUG_MSGOUT) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_cmddone(f, a...) \ do { if (esp_debug & ESP_DEBUG_CMDDONE) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_disconnect(f, a...) \ do { if (esp_debug & ESP_DEBUG_DISCONNECT) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_datastart(f, a...) \ do { if (esp_debug & ESP_DEBUG_DATASTART) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_datadone(f, a...) \ do { if (esp_debug & ESP_DEBUG_DATADONE) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_reconnect(f, a...) \ do { if (esp_debug & ESP_DEBUG_RECONNECT) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0) #define esp_log_autosense(f, a...) \ do { if (esp_debug & ESP_DEBUG_AUTOSENSE) \ - printk(f, ## a); \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ } while (0)#define esp_read8 (REG ) esp->ops->esp_read8(esp, REG)
@@ -150,19 +150,17 @@ static void esp_dump_cmd_log(struct esp *esp)int idx = esp->esp_event_cur;int stop = idx; - printk(KERN_INFO PFX "esp%d: Dumping command log\n", - esp->host->unique_id); +shost_printk (KERN_INFO , esp->host,"Dumping command log\n" );do {struct esp_event_ent *p = &esp->esp_event_log[idx]; - printk(KERN_INFO PFX "esp%d: ent[%d] %s ", - esp->host->unique_id, idx, - p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT"); - -printk ("val[%02x] sreg[%02x] seqreg[%02x] " -"sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n" , - p->val, p->sreg, p->seqreg, - p->sreg2, p->ireg, p->select_state, p->event); +shost_printk (KERN_INFO , esp->host, +"ent[%d] %s val[%02x] sreg[%02x] seqreg[%02x] " +"sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n" , + idx, + p->type ==ESP_EVENT_TYPE_CMD ?"CMD" :"EVENT" , + p->val, p->sreg, p->seqreg, + p->sreg2, p->ireg, p->select_state, p->event); idx = (idx +1 ) & (ESP_EVENT_LOG_SZ -1 ); }while (idx != stop);
@@ -176,9 +174,8 @@ static void esp_flush_fifo(struct esp *esp)while (esp_read8 (ESP_FFLAGS ) &ESP_FF_FBYTES ) {if (--lim ==0 ) { - printk(KERN_ALERT PFX "esp%d: ESP_FF_BYTES " -"will not clear!\n" , - esp->host->unique_id); +shost_printk (KERN_ALERT , esp->host, +"ESP_FF_BYTES will not clear!\n" );break ; }udelay (1 );
@@ -383,12 +380,11 @@ static void esp_advance_dma(struct esp *esp, struct esp_cmd_entry *ent, p->cur_residue -= len; p->tot_residue -= len;if (p->cur_residue <0 || p->tot_residue <0 ) { - printk(KERN_ERR PFX "esp%d: Data transfer overflow.\n", - esp->host->unique_id); - printk(KERN_ERR PFX "esp%d: cur_residue[%d] tot_residue[%d] " -"len[%u]\n" , - esp->host->unique_id, - p->cur_residue, p->tot_residue, len); +shost_printk (KERN_ERR , esp->host, +"Data transfer overflow.\n" ); +shost_printk (KERN_ERR , esp->host, +"cur_residue[%d] tot_residue[%d] len[%u]\n" , + p->cur_residue, p->tot_residue, len); p->cur_residue =0 ; p->tot_residue =0 ; }
@@ -604,9 +600,8 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)if (!ent->sense_ptr) { -esp_log_autosense ("esp%d: Doing auto-sense for " -"tgt[%d] lun[%d]\n" , - esp->host->unique_id, tgt, lun); +esp_log_autosense ("Doing auto-sense for tgt[%d] lun[%d]\n" , + tgt, lun); ent->sense_ptr = cmd->sense_buffer; ent->sense_dma = esp->ops->map_single(esp,
@@ -953,8 +948,8 @@ static int esp_check_gross_error(struct esp *esp)* - DMA programmed with wrong direction * - improper phase change */ - printk(KERN_ERR PFX "esp%d: Gross error sreg[%02x]\n", - esp->host->unique_id, esp->sreg); +shost_printk (KERN_ERR , esp->host, +"Gross error sreg[%02x]\n" , esp->sreg);/* XXX Reset the chip. XXX */ return 1 ; }
@@ -982,14 +977,13 @@ static int esp_check_spur_intr(struct esp *esp)* ESP is not, the only possibility is a DMA error. */ if (!esp->ops->dma_error (esp)) { - printk(KERN_ERR PFX "esp%d: Spurious irq, " -"sreg=%02x.\n" , - esp->host->unique_id, esp->sreg); +shost_printk (KERN_ERR , esp->host, +"Spurious irq, sreg=%02x.\n" , + esp->sreg);return -1 ; } - printk(KERN_ERR PFX "esp%d: DMA error\n", - esp->host->unique_id); +shost_printk (KERN_ERR , esp->host,"DMA error\n" );/* XXX Reset the chip. XXX */ return -1 ;
@@ -1002,7 +996,7 @@ static int esp_check_spur_intr(struct esp *esp)static void esp_schedule_reset (struct esp *esp) { -esp_log_reset ("ESP: esp_schedule_reset() from %pf\n" , +esp_log_reset ("esp_schedule_reset() from %pf\n" ,__builtin_return_address (0 )); esp->flags |=ESP_FLAG_RESETTING ;esp_event (esp,ESP_EVENT_RESET );
@@ -1019,20 +1013,20 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,int i;if (!lp->num_tagged) { - printk(KERN_ERR PFX "esp%d: Reconnect w/num_tagged==0\n", - esp->host->unique_id); +shost_printk (KERN_ERR , esp->host, +"Reconnect w/num_tagged==0\n" );return NULL ; } -esp_log_reconnect ("ESP: reconnect tag, " ); +esp_log_reconnect ("reconnect tag, " );for (i =0 ; i <ESP_QUICKIRQ_LIMIT ; i++) {if (esp->ops->irq_pending (esp))break ; }if (i ==ESP_QUICKIRQ_LIMIT ) { - printk(KERN_ERR PFX "esp%d: Reconnect IRQ1 timeout\n", - esp->host->unique_id); +shost_printk (KERN_ERR , esp->host, +"Reconnect IRQ1 timeout\n" );return NULL ; }
@@ -1043,14 +1037,14 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp, i, esp->ireg, esp->sreg);if (esp->ireg &ESP_INTR_DC ) { - printk(KERN_ERR PFX "esp%d: Reconnect, got disconnect.\n", - esp->host->unique_id); +shost_printk (KERN_ERR , esp->host, +"Reconnect, got disconnect.\n" );return NULL ; }if ((esp->sreg &ESP_STAT_PMASK ) !=ESP_MIP ) { - printk(KERN_ERR PFX "esp%d: Reconnect, not MIP sreg[%02x].\n", - esp->host->unique_id, esp->sreg); +shost_printk (KERN_ERR , esp->host, +"Reconnect, not MIP sreg[%02x].\n" , esp->sreg);return NULL ; }
@@ -1073,8 +1067,7 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,udelay (1 ); }if (i ==ESP_RESELECT_TAG_LIMIT ) { - printk(KERN_ERR PFX "esp%d: Reconnect IRQ2 timeout\n", - esp->host->unique_id); +shost_printk (KERN_ERR , esp->host,"Reconnect IRQ2 timeout\n" );return NULL ; } esp->ops->dma_drain (esp);
@@ -1087,17 +1080,17 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,if (esp->command_block[0 ] <SIMPLE_QUEUE_TAG || esp->command_block[0 ] >ORDERED_QUEUE_TAG ) { - printk(KERN_ERR PFX "esp%d: Reconnect, bad tag " -"type %02x.\n" , - esp->host->unique_id, esp->command_block[0]); +shost_printk (KERN_ERR , esp->host, +"Reconnect, bad tag type %02x.\n" , + esp->command_block[0 ]);return NULL ; } ent = lp->tagged_cmds[esp->command_block[1 ]];if (!ent) { - printk(KERN_ERR PFX "esp%d: Reconnect, no entry for " -"tag %02x.\n" , - esp->host->unique_id, esp->command_block[1]); +shost_printk (KERN_ERR , esp->host, +"Reconnect, no entry for tag %02x.\n" , + esp->command_block[1 ]);return NULL ; }
@@ -1163,9 +1156,9 @@ static int esp_reconnect(struct esp *esp) tp = &esp->target[target]; dev =__scsi_device_lookup_by_target (tp->starget, lun);if (!dev) { - printk(KERN_ERR PFX "esp%d: Reconnect, no lp " -"tgt[%u] lun[%u]\n" , - esp->host->unique_id, target, lun); +shost_printk (KERN_ERR , esp->host, +"Reconnect, no lp tgt[%u] lun[%u]\n" , + target, lun); goto do_reset; } lp = dev->hostdata;
@@ -1291,8 +1284,8 @@ static int esp_finish_select(struct esp *esp)return 0 ; } -printk ("ESP: Unexpected selection completion ireg[%x].\n" , - esp->ireg); +shost_printk (KERN_INFO , esp->host, +"Unexpected selection completion ireg[%x]\n" , esp->ireg);esp_schedule_reset (esp);return 0 ; }
@@ -1556,8 +1549,8 @@ static void esp_msgin_extended(struct esp *esp)return ; } -printk ("ESP: Unexpected extended msg type %x\n" , - esp->msg_in[2 ]); +shost_printk (KERN_INFO , esp->host, +"Unexpected extended msg type %x\n" , esp->msg_in[2 ]); esp->msg_out[0 ] =ABORT_TASK_SET ; esp->msg_out_len =1 ;
@@ -1574,7 +1567,8 @@ static int esp_msgin_process(struct esp *esp)if (msg0 &0x80 ) {/* Identify */ -printk ("ESP: Unexpected msgin identify\n" ); +shost_printk (KERN_INFO , esp->host, +"Unexpected msgin identify\n" );return 0 ; }
@@ -1673,8 +1667,9 @@ again:break ;default : -printk ("ESP: Unexpected phase, sreg=%02x\n" , - esp->sreg); +shost_printk (KERN_INFO , esp->host, +"Unexpected phase, sreg=%02x\n" , + esp->sreg);esp_schedule_reset (esp);return 0 ; }
@@ -1708,18 +1703,17 @@ again: esp->data_dma_len = dma_len;if (!dma_len) { - printk(KERN_ERR PFX "esp%d: DMA length is zero!\n", - esp->host->unique_id); - printk(KERN_ERR PFX "esp%d: cur adr[%08llx] len[%08x]\n", - esp->host->unique_id, - (unsigned long long )esp_cur_dma_addr (ent, cmd), - esp_cur_dma_len(ent, cmd)); +shost_printk (KERN_ERR , esp->host, +"DMA length is zero!\n" ); +shost_printk (KERN_ERR , esp->host, +"cur adr[%08llx] len[%08x]\n" , + (unsigned long long )esp_cur_dma_addr (ent, cmd), +esp_cur_dma_len (ent, cmd));esp_schedule_reset (esp);return 0 ; } -esp_log_datastart ("ESP: start data addr[%08llx] len[%u] " -"write(%d)\n" , +esp_log_datastart ("start data addr[%08llx] len[%u] write(%d)\n" , (unsigned long long )dma_addr, dma_len, write); esp->ops->send_dma_cmd(esp, dma_addr, dma_len, dma_len,
@@ -1733,7 +1727,8 @@ again:int bytes_sent;if (esp->ops->dma_error (esp)) { -printk ("ESP: data done, DMA error, resetting\n" ); +shost_printk (KERN_INFO , esp->host, +"data done, DMA error, resetting\n" );esp_schedule_reset (esp);return 0 ; }
@@ -1749,14 +1744,15 @@ again:/* We should always see exactly a bus-service * interrupt at the end of a successful transfer. */ -printk ("ESP: data done, not BSERV, resetting\n" ); +shost_printk (KERN_INFO , esp->host, +"data done, not BSERV, resetting\n" );esp_schedule_reset (esp);return 0 ; } bytes_sent =esp_data_bytes_sent (esp, ent, cmd); -esp_log_datadone ("ESP: data done flgs[%x] sent[%d]\n" , +esp_log_datadone ("data done flgs[%x] sent[%d]\n" , ent->flags, bytes_sent);if (bytes_sent <0 ) {
@@ -1785,8 +1781,9 @@ again: }if (ent->message !=COMMAND_COMPLETE ) { -printk ("ESP: Unexpected message %x in status\n" , - ent->message); +shost_printk (KERN_INFO , esp->host, +"Unexpected message %x in status\n" , + ent->message);esp_schedule_reset (esp);return 0 ; }
@@ -1804,8 +1801,7 @@ again:scsi_esp_cmd (esp,ESP_CMD_ESEL );if (ent->message ==COMMAND_COMPLETE ) { -esp_log_cmddone ("ESP: Command done status[%x] " -"message[%x]\n" , +esp_log_cmddone ("Command done status[%x] message[%x]\n" , ent->status, ent->message);if (ent->status ==SAM_STAT_TASK_SET_FULL )esp_event_queue_full (esp, ent);
@@ -1821,16 +1817,16 @@ again: DID_OK)); } }else if (ent->message ==DISCONNECT ) { -esp_log_disconnect ("ESP: Disconnecting tgt[%d] " -"tag[%x:%x]\n" , +esp_log_disconnect ("Disconnecting tgt[%d] tag[%x:%x]\n" , cmd->device->id, ent->tag[0 ], ent->tag[1 ]); esp->active_cmd =NULL ;esp_maybe_execute_command (esp); }else { -printk ("ESP: Unexpected message %x in freebus\n" , - ent->message); +shost_printk (KERN_INFO , esp->host, +"Unexpected message %x in freebus\n" , + ent->message);esp_schedule_reset (esp);return 0 ; }
@@ -1917,7 +1913,7 @@ again: val =esp_read8 (ESP_FDATA ); esp->msg_in[esp->msg_in_len++] = val; -esp_log_msgin ("ESP: Got msgin byte %x\n" , val); +esp_log_msgin ("Got msgin byte %x\n" , val);if (!esp_msgin_process (esp)) esp->msg_in_len =0 ;
@@ -1930,7 +1926,8 @@ again:if (esp->event !=ESP_EVENT_FREE_BUS )esp_event (esp,ESP_EVENT_CHECK_PHASE ); }else { -printk ("ESP: MSGIN neither BSERV not FDON, resetting" ); +shost_printk (KERN_INFO , esp->host, +"MSGIN neither BSERV not FDON, resetting" );esp_schedule_reset (esp);return 0 ; }
@@ -1961,8 +1958,8 @@ again:break ;default : -printk ("ESP: Unexpected event %x, resetting\n" , - esp->event); +shost_printk (KERN_INFO , esp->host, +"Unexpected event %x, resetting\n" , esp->event);esp_schedule_reset (esp);return 0 ;break ;
@@ -2085,14 +2082,15 @@ static void __esp_interrupt(struct esp *esp) } } -esp_log_intr ("ESP: intr sreg[%02x] seqreg[%02x] " +esp_log_intr ("intr sreg[%02x] seqreg[%02x] " "sreg2[%02x] ireg[%02x]\n" , esp->sreg, esp->seqreg, esp->sreg2, esp->ireg); intr_done =0 ;if (esp->ireg & (ESP_INTR_S |ESP_INTR_SATN |ESP_INTR_IC )) { -printk ("ESP: unexpected IREG %02x\n" , esp->ireg); +shost_printk (KERN_INFO , esp->host, +"unexpected IREG %02x\n" , esp->ireg);if (esp->ireg &ESP_INTR_IC )esp_dump_cmd_log (esp);
@@ -2334,12 +2332,13 @@ int scsi_esp_register(struct esp *esp, struct device *dev)esp_bootup_reset (esp); - printk(KERN_INFO PFX "esp%u, regs[%1p:%1p] irq[%u]\n", - esp->host->unique_id, esp->regs, esp->dma_regs, - esp->host->irq); - printk(KERN_INFO PFX "esp%u is a %s, %u MHz (ccf=%u), SCSI ID %u\n", - esp->host->unique_id, esp_chip_names[esp->rev], - esp->cfreq / 1000000, esp->cfact, esp->scsi_id); +dev_printk (KERN_INFO , dev,"esp%u: regs[%1p:%1p] irq[%u]\n" , + esp->host->unique_id, esp->regs, esp->dma_regs, + esp->host->irq); +dev_printk (KERN_INFO , dev, +"esp%u: is a %s, %u MHz (ccf=%u), SCSI ID %u\n" , + esp->host->unique_id, esp_chip_names[esp->rev], + esp->cfreq /1000000 , esp->cfact, esp->scsi_id);/* Let the SCSI bus reset settle. */ ssleep (esp_bus_reset_settle);
@@ -2437,19 +2436,20 @@ static int esp_eh_abort_handler(struct scsi_cmnd *cmd)* XXX much for the final driver. */ spin_lock_irqsave (esp->host->host_lock, flags); - printk(KERN_ERR PFX "esp%d: Aborting command [%p:%02x]\n", - esp->host->unique_id, cmd, cmd->cmnd[0]); +shost_printk (KERN_ERR , esp->host,"Aborting command [%p:%02x]\n" , + cmd, cmd->cmnd[0 ]); ent = esp->active_cmd;if (ent) - printk(KERN_ERR PFX "esp%d: Current command [%p:%02x]\n", - esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0 ]); +shost_printk (KERN_ERR , esp->host, +"Current command [%p:%02x]\n" , + ent->cmd, ent->cmd->cmnd[0 ]);list_for_each_entry (ent, &esp->queued_cmds, list) { - printk(KERN_ERR PFX "esp%d: Queued command [%p:%02x]\n", - esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]); +shost_printk (KERN_ERR , esp->host,"Queued command [%p:%02x]\n" , + ent->cmd, ent->cmd->cmnd[0 ]); }list_for_each_entry (ent, &esp->active_cmds, list) { - printk(KERN_ERR PFX "esp%d: Active command [%p:%02x]\n", - esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]); +shost_printk (KERN_ERR , esp->host," Active command [%p:%02x]\n" , + ent->cmd, ent->cmd->cmnd[0 ]); }esp_dump_cmd_log (esp);spin_unlock_irqrestore (esp->host->host_lock, flags);
Signature · 1 line
1.8.5.2
PATCH v3 4/12 esp_scsi: debug event and command
In reply to Hannes ReineckeAdd new debug definitions for event and command logging.
--- drivers/scsi/esp_scsi.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/scsi/esp_scsi.c +15 -0
@@ -49,6 +49,8 @@ static u32 esp_debug;#define ESP_DEBUG_DATADONE 0x00000100#define ESP_DEBUG_RECONNECT 0x00000200#define ESP_DEBUG_AUTOSENSE 0x00000400 +#define ESP_DEBUG_EVENT 0x00000800 +#define ESP_DEBUG_COMMAND 0x00001000 #define esp_log_intr(f, a...) \ do { if (esp_debug & ESP_DEBUG_INTR) \
@@ -100,6 +102,16 @@ do { if (esp_debug & ESP_DEBUG_AUTOSENSE) \ shost_printk(KERN_DEBUG, esp->host, f, ## a); \ }while (0 ) +#define esp_log_event(f, a...) \ +do {if (esp_debug &ESP_DEBUG_EVENT ) \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ +} while (0) + +#define esp_log_command(f, a...) \ +do { if (esp_debug & ESP_DEBUG_COMMAND) \ + shost_printk(KERN_DEBUG, esp->host, f, ## a); \ +} while (0) +#define esp_read8 (REG ) esp->ops->esp_read8(esp, REG)#define esp_write8 (VAL ,REG ) esp->ops->esp_write8(esp, VAL, REG)
@@ -126,6 +138,7 @@ void scsi_esp_cmd(struct esp *esp, u8 val) esp->esp_event_cur = (idx +1 ) & (ESP_EVENT_LOG_SZ -1 ); +esp_log_command ("cmd[%02x]\n" , val);esp_write8 (val,ESP_CMD ); }EXPORT_SYMBOL (scsi_esp_cmd);
@@ -1638,6 +1651,8 @@ static int esp_process_event(struct esp *esp) again: write =0 ; +esp_log_event ("process event %d phase %x\n" , + esp->event, esp->sreg &ESP_STAT_PMASK );switch (esp->event) {case ESP_EVENT_CHECK_PHASE :switch (esp->sreg &ESP_STAT_PMASK ) {
Signature · 1 line
1.8.5.2
PATCH v3 5/12 esp_scsi: read status registers
In reply to Hannes ReineckeA read to ESP_INTRPT will clear ESP_STATUS and ESP_SSTEP. So read all status registers in one go to avoid losing information.
--- drivers/scsi/esp_scsi.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/scsi/esp_scsi.c +5 -3
@@ -982,7 +982,6 @@ static int esp_check_spur_intr(struct esp *esp)default :if (!(esp->sreg &ESP_STAT_INTR )) { - esp->ireg =esp_read8 (ESP_INTRPT );if (esp->ireg &ESP_INTR_SR )return 1 ;
@@ -2056,7 +2055,12 @@ static void __esp_interrupt(struct esp *esp)int finish_reset, intr_done;u8 phase; +/* +* Once INTRPT is read STATUS and SSTEP are cleared. +*/ esp->sreg =esp_read8 (ESP_STATUS ); + esp->seqreg =esp_read8 (ESP_SSTEP ); + esp->ireg =esp_read8 (ESP_INTRPT );if (esp->flags &ESP_FLAG_RESETTING ) { finish_reset =1 ;
@@ -2069,8 +2073,6 @@ static void __esp_interrupt(struct esp *esp)return ; } - esp->ireg =esp_read8 (ESP_INTRPT ); -if (esp->ireg &ESP_INTR_SR ) finish_reset =1 ;
Signature · 1 line
1.8.5.2
PATCH v3 6/12 esp_scsi: use FIFO for command submission
In reply to Hannes ReineckeUsing DMA for command submission has the drawback that it might generate additional DMA completion interrupts after the command has been submitted to the device.
Additionally the am53c974 has a design flaw causing it to generate spurious interrupts even though DMA completion interrupts are not enabled.
This can be avoided by using the FIFO for command submission.
--- drivers/scsi/esp_scsi.c | 46 +++++++++++++++++++++++++++++----------------- drivers/scsi/esp_scsi.h | 1 + 2 files changed, 30 insertions(+), 17 deletions(-)
drivers/scsi/esp_scsi.c +29 -17
@@ -143,6 +143,24 @@ void scsi_esp_cmd(struct esp *esp, u8 val) }EXPORT_SYMBOL (scsi_esp_cmd); +static void esp_send_dma_cmd (struct esp *esp,int len,int max_len,int cmd) +{ +if (esp->flags &ESP_FLAG_USE_FIFO ) { +int i; + +scsi_esp_cmd (esp,ESP_CMD_FLUSH ); +for (i =0 ; i < len; i++) +esp_write8 (esp->command_block[i],ESP_FDATA ); +scsi_esp_cmd (esp, cmd); + }else { +if (esp->rev ==FASHME ) +scsi_esp_cmd (esp,ESP_CMD_FLUSH ); + cmd |=ESP_CMD_DMA ; + esp->ops->send_dma_cmd (esp, esp->command_block_dma, + len, max_len,0 , cmd); + } +} +static void esp_event (struct esp *esp,u8 val) {struct esp_event_ent *p;
@@ -650,10 +668,7 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent) val = (p - esp->command_block); -if (esp->rev ==FASHME ) -scsi_esp_cmd (esp,ESP_CMD_FLUSH ); - esp->ops->send_dma_cmd (esp, esp->command_block_dma, - val,16 ,0 ,ESP_CMD_DMA |ESP_CMD_SELA ); +esp_send_dma_cmd (esp, val,16 ,ESP_CMD_SELA ); }static struct esp_cmd_entry *find_and_prep_issuable_command (struct esp *esp)
@@ -789,12 +804,12 @@ build_identify: }if (!(esp->flags &ESP_FLAG_DOING_SLOWCMD )) { - start_cmd =ESP_CMD_DMA |ESP_CMD_SELA ; + start_cmd =ESP_CMD_SELA ;if (ent->tag[0 ]) { *p++ = ent->tag[0 ]; *p++ = ent->tag[1 ]; - start_cmd =ESP_CMD_DMA |ESP_CMD_SA3 ; + start_cmd =ESP_CMD_SA3 ; }for (i =0 ; i < cmd->cmd_len; i++)
@@ -814,7 +829,7 @@ build_identify: esp->msg_out_len +=2 ; } - start_cmd =ESP_CMD_DMA |ESP_CMD_SELAS ; + start_cmd =ESP_CMD_SELAS ; esp->select_state =ESP_SELECT_MSGOUT ; } val = tgt;
@@ -834,10 +849,7 @@ build_identify:printk ("]\n" ); } -if (esp->rev ==FASHME ) -scsi_esp_cmd (esp,ESP_CMD_FLUSH ); - esp->ops->send_dma_cmd (esp, esp->command_block_dma, - val,16 ,0 , start_cmd); +esp_send_dma_cmd (esp, val,16 , start_cmd); }static struct esp_cmd_entry *esp_get_ent (struct esp *esp)
@@ -1646,7 +1658,7 @@ static int esp_msgin_process(struct esp *esp)static int esp_process_event (struct esp *esp) { -int write; +int write, i; again: write =0 ;
@@ -1872,6 +1884,10 @@ again:if (esp->msg_out_len ==1 ) {esp_write8 (esp->msg_out[0 ],ESP_FDATA );scsi_esp_cmd (esp,ESP_CMD_TI ); + }else if (esp->flags &ESP_FLAG_USE_FIFO ) { +for (i =0 ; i < esp->msg_out_len; i++) +esp_write8 (esp->msg_out[i],ESP_FDATA ); +scsi_esp_cmd (esp,ESP_CMD_TI ); }else {/* Use DMA. */ memcpy(esp->command_block,
@@ -1949,11 +1965,7 @@ again:case ESP_EVENT_CMD_START :memcpy (esp->command_block, esp->cmd_bytes_ptr, esp->cmd_bytes_left); -if (esp->rev ==FASHME ) -scsi_esp_cmd (esp,ESP_CMD_FLUSH ); - esp->ops->send_dma_cmd (esp, esp->command_block_dma, - esp->cmd_bytes_left,16 ,0 , -ESP_CMD_DMA |ESP_CMD_TI ); +esp_send_dma_cmd (esp, esp->cmd_bytes_left,16 ,ESP_CMD_TI );esp_event (esp,ESP_EVENT_CMD_DONE ); esp->flags |=ESP_FLAG_QUICKIRQ_CHECK ;break ;
drivers/scsi/esp_scsi.h +1 -0
@@ -478,6 +478,7 @@ struct esp {#define ESP_FLAG_WIDE_CAPABLE 0x00000008#define ESP_FLAG_QUICKIRQ_CHECK 0x00000010#define ESP_FLAG_DISABLE_SYNC 0x00000020 +#define ESP_FLAG_USE_FIFO 0x00000040u8 select_state;#define ESP_SELECT_NONE 0x00/* Not selecting */
Signature · 1 line
1.8.5.2
PATCH v3 7/12 scsi: add 'am53c974' driver
In reply to Hannes ReineckeThis patch adds a new implementation for the Tekram DC-390T / AMD AM53c974 SCSI controller, based on the generic esp_scsi infrastructure.
--- drivers/scsi/Kconfig | 18 ++ drivers/scsi/Makefile | 1 + drivers/scsi/am53c974.c | 537 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 556 insertions(+) create mode 100644 drivers/scsi/am53c974.c
drivers/scsi/Kconfig +18 -0
@@ -1357,6 +1357,24 @@ config SCSI_DC390T To compile this driver as a module, choose M here: the module will be called tmscsim. +config SCSI_AM53C974 + tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)" + depends on PCI && SCSI + select SCSI_SPI_ATTRS + ---help--- + This driver supports PCI SCSI host adapters based on the Am53C974A + chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard + PCscsi/PCnet (Am53/79C974) solutions. + This is a new implementation base on the generic esp_scsi driver. + + Documentation can be found in <file:Documentation/scsi/tmscsim.txt>. + + Note that this driver does NOT support Tekram DC390W/U/F, which are + based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those. + + To compile this driver as a module, choose M here: the + module will be called am53c974. + config SCSI_T128 tristate "Trantor T128/T128F/T228 SCSI support" depends on ISA && SCSI
drivers/scsi/Makefile +1 -0
@@ -101,6 +101,7 @@ obj-$(CONFIG_SCSI_7000FASST) += wd7000.o obj-$(CONFIG_SCSI_EATA) += eata.o obj-$(CONFIG_SCSI_DC395x) += dc395x.o obj-$(CONFIG_SCSI_DC390T) += tmscsim.o +obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/ obj-$(CONFIG_MEGARAID_SAS) += megaraid/
drivers/scsi/am53c974.c new file +537 -0
537 lines not on this page · raw message
Signature · 1 line
1.8.5.2
PATCH v3 8/12 am53c974: BLAST residual handling
In reply to Hannes ReineckeThe 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.
--- drivers/scsi/am53c974.c | 6 ++++++ drivers/scsi/esp_scsi.c | 29 +++++++++++++++++++++++++++++ drivers/scsi/esp_scsi.h | 1 + 3 files changed, 36 insertions(+)
drivers/scsi/am53c974.c +6 -0
@@ -200,6 +200,12 @@ static void pci_esp_dma_drain(struct esp *esp) }pci_esp_write8 (esp,ESP_DMA_CMD_DIR |ESP_DMA_CMD_IDLE ,ESP_DMA_CMD );esp_dma_log ("DMA blast done (%d tries, %d bytes left)\n" , lim, resid); +/* BLAST residual handling is currently untested */ +if (WARN_ON_ONCE (resid ==1 )) { +struct esp_cmd_entry *ent = esp->active_cmd; + + ent->flags |=ESP_CMD_FLAG_RESIDUAL ; + } }static void pci_esp_dma_invalidate (struct esp *esp)
drivers/scsi/esp_scsi.c +29 -0
@@ -1334,6 +1334,35 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent, bytes_sent = esp->data_dma_len; bytes_sent -= ecount; +/* +* The am53c974 has a DMA 'pecularity'. The doc states: +* In some odd byte conditions, one residual byte will +* be left in the SCSI FIFO, and the FIFO Flags will +* never count to '0 '. When this happens, the residual +* byte should be retrieved via PIO following completion +* of the BLAST operation. +*/ +if (fifo_cnt ==1 && ent->flags &ESP_CMD_FLAG_RESIDUAL ) { +size_t count =1 ; +size_t offset = bytes_sent; +u8 bval =esp_read8 (ESP_FDATA ); + +if (ent->flags &ESP_CMD_FLAG_AUTOSENSE ) + ent->sense_ptr[bytes_sent] = bval; +else { +struct esp_cmd_priv *p =ESP_CMD_PRIV (cmd); +u8 *ptr; + + ptr =scsi_kmap_atomic_sg (p->cur_sg, p->u.num_sg, + &offset, &count); +if (likely (ptr)) { + *(ptr + offset) = bval; +scsi_kunmap_atomic_sg (ptr); + } + } + bytes_sent += fifo_cnt; + ent->flags &= ~ESP_CMD_FLAG_RESIDUAL ; + }if (!(ent->flags &ESP_CMD_FLAG_WRITE )) bytes_sent -= fifo_cnt;
drivers/scsi/esp_scsi.h +1 -0
@@ -269,6 +269,7 @@ struct esp_cmd_entry {#define ESP_CMD_FLAG_WRITE 0x01/* DMA is a write */ #define ESP_CMD_FLAG_ABORT 0x02/* being aborted */ #define ESP_CMD_FLAG_AUTOSENSE 0x04/* Doing automatic REQUEST_SENSE */ +#define ESP_CMD_FLAG_RESIDUAL 0x08/* AM53c974 BLAST residual */ u8 tag[2 ];u8 orig_tag[2 ];
Signature · 1 line
1.8.5.2
PATCH v3 9/12 esp: correctly detect am53c974
In reply to Hannes ReineckeThe am53c974 returns the same ID as the FAS236, but implements things slightly differently. So detect the am53c974 by checking for ESP_CONFIG4 register.
--- drivers/scsi/am53c974.c | 2 ++ drivers/scsi/esp_scsi.c | 17 ++++++++++++++++- drivers/scsi/esp_scsi.h | 15 +++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-)
drivers/scsi/am53c974.c +2 -0
@@ -368,6 +368,8 @@ static void dc390_check_eeprom(struct esp *esp) } esp->scsi_id = EEbuf[DC390_EE_ADAPT_SCSI_ID ]; esp->num_tags =2 << EEbuf[DC390_EE_TAG_CMD_NUM ]; +if (EEbuf[DC390_EE_MODE2 ] &DC390_EE_MODE2_ACTIVE_NEGATION ) + esp->config4 |=ESP_CONFIG4_RADE |ESP_CONFIG4_RAE ; } static int pci_esp_probe_one(struct pci_dev *pdev,
drivers/scsi/esp_scsi.c +16 -1
@@ -268,6 +268,19 @@ static void esp_reset_esp(struct esp *esp) }else { esp->min_period = ((5 * esp->ccycle) /1000 ); } +if (esp->rev ==FAS236 ) { +/* +* The AM53c974 chip returns the same ID as FAS236; +* try to configure glitch eater. +*/ +u8 config4 =ESP_CONFIG4_GE1 ; +esp_write8 (config4,ESP_CFG4 ); + config4 =esp_read8 (ESP_CFG4 ); +if (config4 &ESP_CONFIG4_GE1 ) { + esp->rev =PCSCSI ; +esp_write8 (esp->config4,ESP_CFG4 ); + } + } esp->max_period = (esp->max_period +3 )>>2 ; esp->min_period = (esp->min_period +3 )>>2 ;
@@ -293,7 +306,8 @@ static void esp_reset_esp(struct esp *esp)/* fallthrough... */ case FAS236 : -/* Fast 236 or HME */ +case PCSCSI : +/* Fast 236, AM53c974 or HME */ esp_write8 (esp->config2,ESP_CFG2 );if (esp->rev ==FASHME ) {u8 cfg3 = esp->target[0 ].esp_config3;
@@ -2364,6 +2378,7 @@ static const char *esp_chip_names[] = {"FAS100A" ,"FAST" ,"FASHME" , + "AM53C974", };static struct scsi_transport_template *esp_transport_template;
drivers/scsi/esp_scsi.h +15 -0
@@ -25,6 +25,7 @@#define ESP_CTEST 0x0aUL/* wo Chip test register 0x28 */ #define ESP_CFG2 0x0bUL/* rw Second cfg register 0x2c */ #define ESP_CFG3 0x0cUL/* rw Third cfg register 0x30 */ +#define ESP_CFG4 0x0dUL/* rw Fourth cfg register 0x34 */ #define ESP_TCHI 0x0eUL/* rw High bits transf count 0x38 */ #define ESP_UID ESP_TCHI/* ro Unique ID code 0x38 */ #define FAS_RLO ESP_TCHI/* rw HME extended counter 0x38 */
@@ -76,6 +77,18 @@#define ESP_CONFIG3_IMS 0x80/* ID msg chk'ng (esp/fas236) */ #define ESP_CONFIG3_OBPUSH 0x80/* Push odd-byte to dma (hme) */ +/* ESP config register 4 read-write, found only on am53c974 chips */ +#define ESP_CONFIG4_RADE 0x04/* Active negation */ +#define ESP_CONFIG4_RAE 0x08/* Active negation on REQ and ACK */ +#define ESP_CONFIG4_PWD 0x20/* Reduced power feature */ +#define ESP_CONFIG4_GE0 0x40/* Glitch eater bit 0 */ +#define ESP_CONFIG4_GE1 0x80/* Glitch eater bit 1 */ + +#define ESP_CONFIG_GE_12NS (0) +#define ESP_CONFIG_GE_25NS (ESP_CONFIG_GE1) +#define ESP_CONFIG_GE_35NS (ESP_CONFIG_GE0) +#define ESP_CONFIG_GE_0NS (ESP_CONFIG_GE0 | ESP_CONFIG_GE1) +/* ESP command register read-write */ /* Group 1 commands: These may be sent at any point in time to the ESP * chip. None of them can generate interrupts 'cept
@@ -254,6 +267,7 @@ enum esp_rev {FAS100A =0x04 ,FAST =0x05 ,FASHME =0x06 , + PCSCSI = 0x07, /* AM53c974 */ }; struct esp_cmd_entry {
@@ -466,6 +480,7 @@ struct esp {u8 bursts;u8 config1;u8 config2; +u8 config4;u8 scsi_id;u32 scsi_id_mask;
Signature · 1 line
1.8.5.2
PATCH v3 10/12 esp_scsi: let DMA driver provide a config2 value
In reply to Hannes ReineckeFrom: Paolo Bonzini <[email protected]>
On PCscsi, the FENAB configuration also enables 24-bit DMA transfer lengths (and provides the chip id in TCHI after reset). We want to be able to enable this parameter from the DMA driver.
Check if the caller of scsi_esp_register provided a value for esp->config2. If this is the case, assume this is not an ESP100, skip the detection phase and leave esp->config2 untouched. It will be used in esp_reset_esp.
--- drivers/scsi/esp_scsi.c | 70 ++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 33 deletions(-)
drivers/scsi/esp_scsi.c +37 -33
@@ -2219,46 +2219,50 @@ static void esp_get_revision(struct esp *esp)u8 val; esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id &7 )); - esp->config2 = (ESP_CONFIG2_SCSI2ENAB |ESP_CONFIG2_REGPARITY ); +if (esp->config2 ==0 ) { + esp->config2 = (ESP_CONFIG2_SCSI2ENAB |ESP_CONFIG2_REGPARITY ); +esp_write8 (esp->config2,ESP_CFG2 ); + + val =esp_read8 (ESP_CFG2 ); + val &= ~ESP_CONFIG2_MAGIC ; + + esp->config2 =0 ; +if (val != (ESP_CONFIG2_SCSI2ENAB |ESP_CONFIG2_REGPARITY )) { +/* +* If what we write to cfg2 does not come back, +* cfg2 is not implemented. +* Therefore this must be a plain esp100. +*/ + esp->rev =ESP100 ; +return ; + } + } + +esp_set_all_config3 (esp,5 ); + esp->prev_cfg3 =5 ;esp_write8 (esp->config2,ESP_CFG2 ); +esp_write8 (0 ,ESP_CFG3 ); +esp_write8 (esp->prev_cfg3,ESP_CFG3 ); - val =esp_read8 (ESP_CFG2 ); - val &= ~ESP_CONFIG2_MAGIC ; -if (val != (ESP_CONFIG2_SCSI2ENAB |ESP_CONFIG2_REGPARITY )) { -/* If what we write to cfg2 does not come back, cfg2 is not -* implemented, therefore this must be a plain esp100. + val =esp_read8 (ESP_CFG3 ); +if (val !=5 ) { +/* The cfg2 register is implemented, however +* cfg3 is not, must be esp100a. */ - esp->rev =ESP100 ; + esp->rev =ESP100A ; }else { - esp->config2 =0 ; -esp_set_all_config3 (esp,5 ); - esp->prev_cfg3 =5 ; -esp_write8 (esp->config2,ESP_CFG2 ); -esp_write8 (0 ,ESP_CFG3 ); +esp_set_all_config3 (esp,0 ); + esp->prev_cfg3 =0 ;esp_write8 (esp->prev_cfg3,ESP_CFG3 ); - val =esp_read8 (ESP_CFG3 ); -if (val !=5 ) { -/* The cfg2 register is implemented, however -* cfg3 is not, must be esp100a. -*/ - esp->rev =ESP100A ; +/* All of cfg{1,2,3} implemented, must be one of +* the fas variants, figure out which one. +*/ +if (esp->cfact ==0 || esp->cfact >ESP_CCF_F5 ) { + esp->rev =FAST ; + esp->sync_defp =SYNC_DEFP_FAST ; }else { -esp_set_all_config3 (esp,0 ); - esp->prev_cfg3 =0 ; -esp_write8 (esp->prev_cfg3,ESP_CFG3 ); - -/* All of cfg{1,2,3} implemented, must be one of -* the fas variants, figure out which one. -*/ -if (esp->cfact ==0 || esp->cfact >ESP_CCF_F5 ) { - esp->rev =FAST ; - esp->sync_defp =SYNC_DEFP_FAST ; - }else { - esp->rev =ESP236 ; - } - esp->config2 =0 ; -esp_write8 (esp->config2,ESP_CFG2 ); + esp->rev =ESP236 ; } } }
Signature · 1 line
1.8.5.2
PATCH v3 11/12 esp: enable CONFIG2_FENAB for am53c974
In reply to Hannes ReineckeCONFIG2_FENAB ('feature enable') changed definition between chip revisions, from 'Latch SCSI Phase' to 'Latch SCSI Phase, display chip ID upon reset, and enable 24 bit addresses'.
So only enable it for am53c974 where we know what it's doing.
--- drivers/scsi/am53c974.c | 40 ++++++++++++++++++++++++++++++++++++++++ drivers/scsi/esp_scsi.c | 2 ++ 2 files changed, 42 insertions(+)
drivers/scsi/am53c974.c +40 -0
@@ -18,6 +18,7 @@#define DRV_MODULE_VERSION "1.00"static bool am53c974_debug; +static bool am53c974_fenab = true; #define esp_dma_log(f, a...) \ do { \
@@ -256,6 +257,8 @@ static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,pci_esp_write8 (esp, (esp_count >>0 ) &0xff ,ESP_TCLOW );pci_esp_write8 (esp, (esp_count >>8 ) &0xff ,ESP_TCMED ); +if (esp->config2 &ESP_CONFIG2_FENAB ) +pci_esp_write8 (esp, (esp_count >>16 ) &0xff ,ESP_TCHI );pci_esp_write32 (esp, esp_count,ESP_DMA_STC );pci_esp_write32 (esp, addr,ESP_DMA_SPA );
@@ -268,6 +271,33 @@ static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,pci_esp_write8 (esp,ESP_DMA_CMD_START | val,ESP_DMA_CMD ); } +static u32 pci_esp_dma_length_limit (struct esp *esp,u32 dma_addr,u32 dma_len) +{ +int dma_limit =16 ; +u32 base, end; + +/* +* If CONFIG2_FENAB is set we can +* handle up to 24 bit addresses +*/ +if (esp->config2 &ESP_CONFIG2_FENAB ) + dma_limit =24 ; + +if (dma_len > (1U << dma_limit)) + dma_len = (1U << dma_limit); + +/* +* Prevent crossing a 24-bit address boundary. +*/ + base = dma_addr & ((1U <<24 ) -1U ); + end = base + dma_len; +if (end > (1U <<24 )) + end = (1U <<24 ); + dma_len = end - base; + +return dma_len; +} +static const struct esp_driver_ops pci_esp_ops = { .esp_write8 = pci_esp_write8, .esp_read8 = pci_esp_read8,
@@ -281,6 +311,7 @@ static const struct esp_driver_ops pci_esp_ops = { .dma_invalidate = pci_esp_dma_invalidate, .send_dma_cmd = pci_esp_send_dma_cmd, .dma_error = pci_esp_dma_error, + .dma_length_limit = pci_esp_dma_length_limit, };/*
@@ -418,6 +449,12 @@ static int pci_esp_probe_one(struct pci_dev *pdev,* DMA for command submission. */ esp->flags |=ESP_FLAG_USE_FIFO ; +/* +* Enable CONFIG2_FENAB to allow for large DMA transfers +*/ +if (am53c974_fenab) + esp->config2 |=ESP_CONFIG2_FENAB ; + pep->esp = esp;if (pci_request_regions (pdev,DRV_MODULE_NAME )) {
@@ -541,5 +578,8 @@ MODULE_VERSION(DRV_MODULE_VERSION);module_param (am53c974_debug, bool,0644 );MODULE_PARM_DESC (am53c974_debug,"Enable debugging" ); +module_param (am53c974_fenab, bool,0444 ); +MODULE_PARM_DESC (am53c974_fenab,"Enable 24-bit DMA transfer sizes" ); +module_init (am53c974_module_init);module_exit (am53c974_module_exit);
drivers/scsi/esp_scsi.c +2 -0
@@ -1343,6 +1343,8 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent, (((unsigned int)esp_read8(ESP_TCMED)) << 8));if (esp->rev ==FASHME ) ecount |= ((unsigned int )esp_read8 (FAS_RLO )) <<16 ; +if (esp->rev ==PCSCSI && (esp->config2 &ESP_CONFIG2_FENAB )) + ecount |= ((unsigned int )esp_read8 (ESP_TCHI )) <<16 ; } bytes_sent = esp->data_dma_len;
Signature · 1 line
1.8.5.2
PATCH v3 12/12 Replace tmscsim by am53c974
In reply to Hannes ReineckeThe am53c974 is a re-implementation of the tmscsim driver, and provides the same functionality.
So remove the tmscsim driver and make am53c974 an alias to tmscsim.
--- MAINTAINERS | 7 +- drivers/scsi/Kconfig | 16 - drivers/scsi/Makefile | 1 - drivers/scsi/am53c974.c | 1 + drivers/scsi/tmscsim.c | 2626 ----------------------------------------------- drivers/scsi/tmscsim.h | 549 ---------- 6 files changed, 4 insertions(+), 3196 deletions(-) delete mode 100644 drivers/scsi/tmscsim.c delete mode 100644 drivers/scsi/tmscsim.h
MAINTAINERS +3 -4
@@ -2862,11 +2862,10 @@ F: Documentation/networking/dmfe.txt F: drivers/net/ethernet/dec/tulip/dmfe.c DC390/AM53C974 SCSI driver -M: Kurt Garloff <[email protected]> -W: http://www.garloff.de/kurt/linux/dc390/ -M: Guennadi Liakhovetski <[email protected]> +M: Hannes Reinecke <[email protected]> +L: [email protected] S: Maintained -F: drivers/scsi/tmscsim.* +F: drivers/scsi/am53c974.c DC395x SCSI driver M: Oliver Neukum <[email protected]>
drivers/scsi/Kconfig +0 -16
@@ -1341,22 +1341,6 @@ config SCSI_DC395x To compile this driver as a module, choose M here: the module will be called dc395x. -config SCSI_DC390T - tristate "Tekram DC390(T) and Am53/79C974 SCSI support" - depends on PCI && SCSI - ---help--- - This driver supports PCI SCSI host adapters based on the Am53C974A - chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard - PCscsi/PCnet (Am53/79C974) solutions. - - Documentation can be found in <file:Documentation/scsi/tmscsim.txt>. - - Note that this driver does NOT support Tekram DC390W/U/F, which are - based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those. - - To compile this driver as a module, choose M here: the - module will be called tmscsim. - config SCSI_AM53C974 tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)" depends on PCI && SCSI
drivers/scsi/Makefile +0 -1
@@ -100,7 +100,6 @@ obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o obj-$(CONFIG_SCSI_7000FASST) += wd7000.o obj-$(CONFIG_SCSI_EATA) += eata.o obj-$(CONFIG_SCSI_DC395x) += dc395x.o -obj-$(CONFIG_SCSI_DC390T) += tmscsim.o obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
drivers/scsi/am53c974.c +1 -0
@@ -574,6 +574,7 @@ MODULE_DESCRIPTION("AM53C974 SCSI driver");MODULE_AUTHOR ("Hannes Reinecke <[email protected]>" );MODULE_LICENSE ("GPL" );MODULE_VERSION (DRV_MODULE_VERSION ); +MODULE_ALIAS ("tmscsim" );module_param (am53c974_debug, bool,0644 );MODULE_PARM_DESC (am53c974_debug,"Enable debugging" );
drivers/scsi/tmscsim.c deleted +0 -2626
2,626 lines not on this page · raw message
drivers/scsi/tmscsim.h deleted +0 -549
324 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
1.8.5.2
Part of the diff is not shown here. View the raw message.
Christoph Hellwig
AppliedThanks,
applied to drivers-for-3.19.