Commit aa2423a7 authored by Adam Radford's avatar Adam Radford Committed by Dave Jones

[PATCH] 3ware driver update for 2.5.8-pre1

Self explanatory driver update from vendor.
parent 4ca462ce
...@@ -133,6 +133,14 @@ ...@@ -133,6 +133,14 @@
some SMP systems. some SMP systems.
1.02.00.020 - Add pci_set_dma_mask(), rewrite kmalloc()/virt_to_bus() to 1.02.00.020 - Add pci_set_dma_mask(), rewrite kmalloc()/virt_to_bus() to
pci_alloc/free_consistent(). pci_alloc/free_consistent().
Better alignment checking in tw_allocate_memory().
Cleanup tw_initialize_device_extension().
1.02.00.021 - Bump cmd_per_lun in SHT to 255 for better jbod performance.
Improve handling of errors in tw_interrupt().
Add handling/clearing of controller queue error.
Empty stale responses before draining aen queue.
Fix tw_scsi_eh_abort() to not reset on every io abort.
Set can_queue in SHT to 255 to prevent hang from AEN.
*/ */
#include <linux/module.h> #include <linux/module.h>
...@@ -182,7 +190,7 @@ static struct notifier_block tw_notifier = { ...@@ -182,7 +190,7 @@ static struct notifier_block tw_notifier = {
}; };
/* Globals */ /* Globals */
char *tw_driver_version="1.02.00.020"; char *tw_driver_version="1.02.00.021";
TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT]; TW_Device_Extension *tw_device_extension_list[TW_MAX_SLOT];
int tw_device_extension_count = 0; int tw_device_extension_count = 0;
...@@ -284,6 +292,9 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev) ...@@ -284,6 +292,9 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
} }
tw_clear_attention_interrupt(tw_dev); tw_clear_attention_interrupt(tw_dev);
/* Empty response queue */
tw_empty_response_que(tw_dev);
/* Initialize command packet */ /* Initialize command packet */
if (tw_dev->command_packet_virtual_address[request_id] == NULL) { if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n"); printk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Bad command packet virtual address.\n");
...@@ -337,7 +348,7 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev) ...@@ -337,7 +348,7 @@ int tw_aen_drain_queue(TW_Device_Extension *tw_dev)
status_reg_value = inl(status_reg_addr); status_reg_value = inl(status_reg_addr);
if (tw_check_bits(status_reg_value)) { if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_aen_drain_queue(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value); tw_decode_bits(tw_dev, status_reg_value, 0);
return 1; return 1;
} }
if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
...@@ -451,7 +462,7 @@ int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id) ...@@ -451,7 +462,7 @@ int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id)
status_reg_value = inl(status_reg_addr); status_reg_value = inl(status_reg_addr);
if (tw_check_bits(status_reg_value)) { if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_aen_read_queue(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value); tw_decode_bits(tw_dev, status_reg_value, 1);
return 1; return 1;
} }
if (tw_dev->command_packet_virtual_address[request_id] == NULL) { if (tw_dev->command_packet_virtual_address[request_id] == NULL) {
...@@ -571,13 +582,23 @@ int tw_check_errors(TW_Device_Extension *tw_dev) ...@@ -571,13 +582,23 @@ int tw_check_errors(TW_Device_Extension *tw_dev)
status_reg_value = inl(status_reg_addr); status_reg_value = inl(status_reg_addr);
if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value)) { if (TW_STATUS_ERRORS(status_reg_value) || tw_check_bits(status_reg_value)) {
tw_decode_bits(tw_dev, status_reg_value); tw_decode_bits(tw_dev, status_reg_value, 0);
return 1; return 1;
} }
return 0; return 0;
} /* End tw_check_errors() */ } /* End tw_check_errors() */
/* This function will clear all interrupts on the controller */
void tw_clear_all_interrupts(TW_Device_Extension *tw_dev)
{
u32 control_reg_addr, control_reg_value;
control_reg_addr = tw_dev->registers.control_reg_addr;
control_reg_value = TW_STATUS_VALID_INTERRUPT;
outl(control_reg_value, control_reg_addr);
} /* End tw_clear_all_interrupts() */
/* This function will clear the attention interrupt */ /* This function will clear the attention interrupt */
void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev) void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev)
{ {
...@@ -632,30 +653,51 @@ static void tw_copy_mem_info(TW_Info *info, char *data, int len) ...@@ -632,30 +653,51 @@ static void tw_copy_mem_info(TW_Info *info, char *data, int len)
} }
} /* End tw_copy_mem_info() */ } /* End tw_copy_mem_info() */
/* This function will print readable messages from statsu register errors */ /* This function will print readable messages from status register errors */
void tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value) int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host)
{ {
char host[16];
dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n"); dprintk(KERN_WARNING "3w-xxxx: tw_decode_bits()\n");
if (print_host)
sprintf(host, " scsi%d:", tw_dev->host->host_no);
else
host[0] = '\0';
switch (status_reg_value & TW_STATUS_UNEXPECTED_BITS) { switch (status_reg_value & TW_STATUS_UNEXPECTED_BITS) {
case TW_STATUS_PCI_PARITY_ERROR: case TW_STATUS_PCI_PARITY_ERROR:
printk(KERN_WARNING "3w-xxxx: PCI Parity Error: clearing.\n"); printk(KERN_WARNING "3w-xxxx:%s PCI Parity Error: clearing.\n", host);
outl(TW_CONTROL_CLEAR_PARITY_ERROR, tw_dev->registers.control_reg_addr); outl(TW_CONTROL_CLEAR_PARITY_ERROR, tw_dev->registers.control_reg_addr);
break; break;
case TW_STATUS_MICROCONTROLLER_ERROR: case TW_STATUS_MICROCONTROLLER_ERROR:
printk(KERN_WARNING "3w-xxxx: Microcontroller Error.\n"); if (tw_dev->reset_print == 0) {
break; printk(KERN_WARNING "3w-xxxx:%s Microcontroller Error: clearing.\n", host);
tw_dev->reset_print = 1;
}
return 1;
case TW_STATUS_PCI_ABORT: case TW_STATUS_PCI_ABORT:
printk(KERN_WARNING "3w-xxxx: PCI Abort: clearing.\n"); printk(KERN_WARNING "3w-xxxx:%s PCI Abort: clearing.\n", host);
outl(TW_CONTROL_CLEAR_PCI_ABORT, tw_dev->registers.control_reg_addr); outl(TW_CONTROL_CLEAR_PCI_ABORT, tw_dev->registers.control_reg_addr);
pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT); pci_write_config_word(tw_dev->tw_pci_dev, PCI_STATUS, TW_PCI_CLEAR_PCI_ABORT);
break; break;
case TW_STATUS_QUEUE_ERROR:
printk(KERN_WARNING "3w-xxxx:%s Controller Queue Error: clearing.\n", host);
outl(TW_CONTROL_CLEAR_QUEUE_ERROR, tw_dev->registers.control_reg_addr);
break;
case TW_STATUS_SBUF_WRITE_ERROR:
printk(KERN_WARNING "3w-xxxx:%s SBUF Write Error: clearing.\n", host);
outl(TW_CONTROL_CLEAR_SBUF_WRITE_ERROR, tw_dev->registers.control_reg_addr);
break;
} }
return 0;
} /* End tw_decode_bits() */ } /* End tw_decode_bits() */
/* This function will return valid sense buffer information for failed cmds */ /* This function will return valid sense buffer information for failed cmds */
void tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense) int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense)
{ {
int i, found=0; int i;
TW_Command *command; TW_Command *command;
dprintk(KERN_WARNING "3w-xxxx: tw_decode_sense()\n"); dprintk(KERN_WARNING "3w-xxxx: tw_decode_sense()\n");
...@@ -668,7 +710,6 @@ void tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense ...@@ -668,7 +710,6 @@ void tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense
if ((command->status == 0xc7) || (command->status == 0xcb)) { if ((command->status == 0xc7) || (command->status == 0xcb)) {
for (i=0;i<(sizeof(tw_sense_table)/sizeof(tw_sense_table[0]));i++) { for (i=0;i<(sizeof(tw_sense_table)/sizeof(tw_sense_table[0]));i++) {
if (command->flags == tw_sense_table[i][0]) { if (command->flags == tw_sense_table[i][0]) {
found=1;
/* Valid bit and 'current errors' */ /* Valid bit and 'current errors' */
tw_dev->srb[request_id]->sense_buffer[0] = (0x1 << 7 | 0x70); tw_dev->srb[request_id]->sense_buffer[0] = (0x1 << 7 | 0x70);
...@@ -686,13 +727,16 @@ void tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense ...@@ -686,13 +727,16 @@ void tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense
tw_dev->srb[request_id]->sense_buffer[13] = tw_sense_table[i][3]; tw_dev->srb[request_id]->sense_buffer[13] = tw_sense_table[i][3];
tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1); tw_dev->srb[request_id]->result = (DID_OK << 16) | (CHECK_CONDITION << 1);
return TW_ISR_DONT_RESULT; /* Special case for isr to not over-write result */
} }
} }
} }
/* If no table match, error so we get a reset */ /* If no table match, error so we get a reset */
if (found == 0) return 1;
tw_dev->srb[request_id]->result = (DID_RESET << 16);
} }
return 0;
} /* End tw_decode_sense() */ } /* End tw_decode_sense() */
/* This function will disable interrupts on the controller */ /* This function will disable interrupts on the controller */
...@@ -706,7 +750,7 @@ void tw_disable_interrupts(TW_Device_Extension *tw_dev) ...@@ -706,7 +750,7 @@ void tw_disable_interrupts(TW_Device_Extension *tw_dev)
} /* End tw_disable_interrupts() */ } /* End tw_disable_interrupts() */
/* This function will empty the response que */ /* This function will empty the response que */
int tw_empty_response_que(TW_Device_Extension *tw_dev) void tw_empty_response_que(TW_Device_Extension *tw_dev)
{ {
u32 status_reg_addr, status_reg_value; u32 status_reg_addr, status_reg_value;
u32 response_que_addr, response_que_value; u32 response_que_addr, response_que_value;
...@@ -716,22 +760,10 @@ int tw_empty_response_que(TW_Device_Extension *tw_dev) ...@@ -716,22 +760,10 @@ int tw_empty_response_que(TW_Device_Extension *tw_dev)
status_reg_value = inl(status_reg_addr); status_reg_value = inl(status_reg_addr);
if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 1.\n");
tw_decode_bits(tw_dev, status_reg_value);
return 1;
}
while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
response_que_value = inl(response_que_addr); response_que_value = inl(response_que_addr);
status_reg_value = inl(status_reg_addr); status_reg_value = inl(status_reg_addr);
if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_empty_response_queue(): Unexpected bits 2.\n");
tw_decode_bits(tw_dev, status_reg_value);
return 1;
}
} }
return 0;
} /* End tw_empty_response_que() */ } /* End tw_empty_response_que() */
/* This function will enable interrupts on the controller */ /* This function will enable interrupts on the controller */
...@@ -812,7 +844,7 @@ int tw_findcards(Scsi_Host_Template *tw_host) ...@@ -812,7 +844,7 @@ int tw_findcards(Scsi_Host_Template *tw_host)
/* Check for errors and clear them */ /* Check for errors and clear them */
status_reg_value = inl(tw_dev->registers.status_reg_addr); status_reg_value = inl(tw_dev->registers.status_reg_addr);
if (TW_STATUS_ERRORS(status_reg_value)) if (TW_STATUS_ERRORS(status_reg_value))
tw_decode_bits(tw_dev, status_reg_value); tw_decode_bits(tw_dev, status_reg_value, 0);
/* Poll status register for 60 secs for 'Controller Ready' flag */ /* Poll status register for 60 secs for 'Controller Ready' flag */
if (tw_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY, 60)) { if (tw_poll_status(tw_dev, TW_STATUS_MICROCONTROLLER_READY, 60)) {
...@@ -843,14 +875,6 @@ int tw_findcards(Scsi_Host_Template *tw_host) ...@@ -843,14 +875,6 @@ int tw_findcards(Scsi_Host_Template *tw_host)
continue; continue;
} }
/* Empty the response queue */
error = tw_empty_response_que(tw_dev);
if (error) {
printk(KERN_WARNING "3w-xxxx: Couldn't empty response queue, retrying for card %d.\n", numcards);
tries++;
continue;
}
/* Now the controller is in a good state */ /* Now the controller is in a good state */
break; break;
} }
...@@ -877,7 +901,7 @@ int tw_findcards(Scsi_Host_Template *tw_host) ...@@ -877,7 +901,7 @@ int tw_findcards(Scsi_Host_Template *tw_host)
request_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE, TW_DEVICE_NAME); request_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE, TW_DEVICE_NAME);
error = tw_initialize_units(tw_dev); error = tw_initialize_units(tw_dev);
if (error) { if (error) {
printk(KERN_WARNING "3w-xxxx: tw_findcards(): Couldn't initialize units for card %d.\n", numcards); printk(KERN_WARNING "3w-xxxx: No valid units for for card %d.\n", numcards);
release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE); release_region((tw_dev->tw_pci_dev->resource[0].start), TW_IO_ADDRESS_RANGE);
tw_free_device_extension(tw_dev); tw_free_device_extension(tw_dev);
kfree(tw_dev); kfree(tw_dev);
...@@ -895,7 +919,7 @@ int tw_findcards(Scsi_Host_Template *tw_host) ...@@ -895,7 +919,7 @@ int tw_findcards(Scsi_Host_Template *tw_host)
/* Calculate max cmds per lun, and setup queues */ /* Calculate max cmds per lun, and setup queues */
if (tw_dev->num_units > 0) { if (tw_dev->num_units > 0) {
tw_host->cmd_per_lun = (TW_Q_LENGTH-1)/tw_dev->num_units; /* Use SHT cmd_per_lun here */
tw_dev->free_head = TW_Q_START; tw_dev->free_head = TW_Q_START;
tw_dev->free_tail = TW_Q_LENGTH - 1; tw_dev->free_tail = TW_Q_LENGTH - 1;
tw_dev->free_wrap = TW_Q_LENGTH - 1; tw_dev->free_wrap = TW_Q_LENGTH - 1;
...@@ -1064,7 +1088,7 @@ int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits) ...@@ -1064,7 +1088,7 @@ int tw_initconnection(TW_Device_Extension *tw_dev, int message_credits)
status_reg_value = inl(status_reg_addr); status_reg_value = inl(status_reg_addr);
if (tw_check_bits(status_reg_value)) { if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_initconnection(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value); tw_decode_bits(tw_dev, status_reg_value, 0);
return 1; return 1;
} }
if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
...@@ -1191,7 +1215,7 @@ int tw_initialize_units(TW_Device_Extension *tw_dev) ...@@ -1191,7 +1215,7 @@ int tw_initialize_units(TW_Device_Extension *tw_dev)
status_reg_value = inl(status_reg_addr); status_reg_value = inl(status_reg_addr);
if (tw_check_bits(status_reg_value)) { if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_initialize_units(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value); tw_decode_bits(tw_dev, status_reg_value, 0);
return 1; return 1;
} }
if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
...@@ -1251,51 +1275,52 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -1251,51 +1275,52 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
u32 response_que_addr; u32 response_que_addr;
TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance; TW_Device_Extension *tw_dev = (TW_Device_Extension *)dev_instance;
TW_Response_Queue response_que; TW_Response_Queue response_que;
int error = 0; int error = 0, retval = 0;
int do_response_interrupt=0;
int do_attention_interrupt=0;
int do_host_interrupt=0;
int do_command_interrupt=0;
unsigned long flags = 0; unsigned long flags = 0;
TW_Command *command_packet; TW_Command *command_packet;
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt()\n");
/* See if we are already running on another processor */
if (test_and_set_bit(TW_IN_INTR, &tw_dev->flags)) if (test_and_set_bit(TW_IN_INTR, &tw_dev->flags))
return; return;
/* Get the host lock for io completions */
spin_lock_irqsave(tw_dev->host->host_lock, flags); spin_lock_irqsave(tw_dev->host->host_lock, flags);
/* See if the interrupt matches this instance */
if (tw_dev->tw_pci_dev->irq == irq) { if (tw_dev->tw_pci_dev->irq == irq) {
/* Make sure io isn't queueing */
spin_lock(&tw_dev->tw_lock); spin_lock(&tw_dev->tw_lock);
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt()\n");
/* Read the registers */ /* Read the registers */
status_reg_addr = tw_dev->registers.status_reg_addr; status_reg_addr = tw_dev->registers.status_reg_addr;
response_que_addr = tw_dev->registers.response_que_addr; response_que_addr = tw_dev->registers.response_que_addr;
status_reg_value = inl(status_reg_addr); status_reg_value = inl(status_reg_addr);
/* Check if this is our interrupt, otherwise bail */
if (!(status_reg_value & TW_STATUS_VALID_INTERRUPT))
goto tw_interrupt_bail;
/* Check controller for errors */
if (tw_check_bits(status_reg_value)) { if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value); if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
tw_clear_all_interrupts(tw_dev);
goto tw_interrupt_bail;
}
} }
/* Check which interrupt */
if (status_reg_value & TW_STATUS_HOST_INTERRUPT)
do_host_interrupt=1;
if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT)
do_attention_interrupt=1;
if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT)
do_command_interrupt=1;
if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT)
do_response_interrupt=1;
/* Handle host interrupt */ /* Handle host interrupt */
if (do_host_interrupt) { if (status_reg_value & TW_STATUS_HOST_INTERRUPT) {
dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n"); dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received host interrupt.\n");
tw_clear_host_interrupt(tw_dev); tw_clear_host_interrupt(tw_dev);
} }
/* Handle attention interrupt */ /* Handle attention interrupt */
if (do_attention_interrupt) { if (status_reg_value & TW_STATUS_ATTENTION_INTERRUPT) {
dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n"); dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Received attention interrupt.\n");
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Clearing attention interrupt.\n");
tw_clear_attention_interrupt(tw_dev); tw_clear_attention_interrupt(tw_dev);
tw_state_request_start(tw_dev, &request_id); tw_state_request_start(tw_dev, &request_id);
error = tw_aen_read_queue(tw_dev, request_id); error = tw_aen_read_queue(tw_dev, request_id);
...@@ -1307,7 +1332,7 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -1307,7 +1332,7 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
} }
/* Handle command interrupt */ /* Handle command interrupt */
if (do_command_interrupt) { if (status_reg_value & TW_STATUS_COMMAND_INTERRUPT) {
/* Drain as many pending commands as we can */ /* Drain as many pending commands as we can */
while (tw_dev->pending_request_count > 0) { while (tw_dev->pending_request_count > 0) {
request_id = tw_dev->pending_queue[tw_dev->pending_head]; request_id = tw_dev->pending_queue[tw_dev->pending_head];
...@@ -1323,6 +1348,7 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -1323,6 +1348,7 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
} }
tw_dev->pending_request_count--; tw_dev->pending_request_count--;
} else { } else {
printk(KERN_WARNING "3w-xxxx: scsi%d: Error posting pending commands.\n", tw_dev->host->host_no);
break; break;
} }
} }
...@@ -1332,40 +1358,40 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -1332,40 +1358,40 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
} }
/* Handle response interrupt */ /* Handle response interrupt */
if (do_response_interrupt) { if (status_reg_value & TW_STATUS_RESPONSE_INTERRUPT) {
/* Drain the response queue from the board */ /* Drain the response queue from the board */
while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { while ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
/* Read response queue register */
response_que.value = inl(response_que_addr); response_que.value = inl(response_que_addr);
request_id = response_que.u.response_id; request_id = response_que.u.response_id;
command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id]; command_packet = (TW_Command *)tw_dev->command_packet_virtual_address[request_id];
error = 0; error = 0;
/* Check for bad response */
if (command_packet->status != 0) { if (command_packet->status != 0) {
/* Bad response */ /* If internal command, don't error, don't fill sense */
if (tw_dev->srb[request_id] != 0) if (tw_dev->srb[request_id] == 0) {
tw_decode_sense(tw_dev, request_id, 1); tw_decode_sense(tw_dev, request_id, 0);
error = 3; } else {
error = tw_decode_sense(tw_dev, request_id, 1);
}
} }
/* Check for correct state */
if (tw_dev->state[request_id] != TW_S_POSTED) { if (tw_dev->state[request_id] != TW_S_POSTED) {
printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode); printk(KERN_WARNING "3w-xxxx: scsi%d: Received a request id (%d) (opcode = 0x%x) that wasn't posted.\n", tw_dev->host->host_no, request_id, command_packet->byte0.opcode);
error = 1; error = 1;
} }
if (TW_STATUS_ERRORS(status_reg_value)) {
tw_decode_bits(tw_dev, status_reg_value);
error = 1;
}
dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id); dprintk(KERN_NOTICE "3w-xxxx: tw_interrupt(): Response queue request id: %d.\n", request_id);
/* Check for internal command */
/* Check for internal command completion */
if (tw_dev->srb[request_id] == 0) { if (tw_dev->srb[request_id] == 0) {
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Found internally posted command.\n");
error = tw_aen_complete(tw_dev, request_id); retval = tw_aen_complete(tw_dev, request_id);
if (error) { if (retval) {
printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no); printk(KERN_WARNING "3w-xxxx: scsi%d: Error completing aen.\n", tw_dev->host->host_no);
} }
status_reg_value = inl(status_reg_addr);
if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value);
}
} else { } else {
switch (tw_dev->srb[request_id]->cmnd[0]) { switch (tw_dev->srb[request_id]->cmnd[0]) {
case READ_10: case READ_10:
...@@ -1389,20 +1415,22 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -1389,20 +1415,22 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
error = tw_ioctl_complete(tw_dev, request_id); error = tw_ioctl_complete(tw_dev, request_id);
break; break;
default: default:
printk(KERN_WARNING "3w-xxxx: scsi%d: Unknown scsi opcode: 0x%x.\n", tw_dev->host->host_no, tw_dev->srb[request_id]->cmnd[0]); printk(KERN_WARNING "3w-xxxx: case slip in tw_interrupt()\n");
tw_dev->srb[request_id]->result = (DID_BAD_TARGET << 16); error = 1;
tw_dev->srb[request_id]->scsi_done(tw_dev->srb[request_id]);
}
if (error == 1) {
/* Tell scsi layer there was an error */
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Scsi Error.\n");
tw_dev->srb[request_id]->result = (DID_RESET << 16);
} }
/* If no error command was a success */
if (error == 0) { if (error == 0) {
/* Tell scsi layer command was a success */
tw_dev->srb[request_id]->result = (DID_OK << 16); tw_dev->srb[request_id]->result = (DID_OK << 16);
} }
if (error != 2) {
/* If error, command failed */
if (error == 1) {
tw_dev->srb[request_id]->result = (DID_RESET << 16);
}
/* Now complete the io */
if ((error != TW_ISR_DONT_COMPLETE)) {
tw_dev->state[request_id] = TW_S_COMPLETED; tw_dev->state[request_id] = TW_S_COMPLETED;
tw_state_request_finish(tw_dev, request_id); tw_state_request_finish(tw_dev, request_id);
tw_dev->posted_request_count--; tw_dev->posted_request_count--;
...@@ -1410,16 +1438,24 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs) ...@@ -1410,16 +1438,24 @@ static void tw_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
} }
}
/* Check for valid status after each drain */
status_reg_value = inl(status_reg_addr); status_reg_value = inl(status_reg_addr);
if (tw_check_bits(status_reg_value)) { if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_interrupt(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value); if (tw_decode_bits(tw_dev, status_reg_value, 1)) {
tw_clear_all_interrupts(tw_dev);
goto tw_interrupt_bail;
} }
} }
} }
} }
tw_interrupt_bail:
spin_unlock(&tw_dev->tw_lock); spin_unlock(&tw_dev->tw_lock);
} } else
dprintk(KERN_WARNING "3w-xxxx: tw_interrupt() called for wrong instance.\n");
spin_unlock_irqrestore(tw_dev->host->host_lock, flags); spin_unlock_irqrestore(tw_dev->host->host_lock, flags);
clear_bit(TW_IN_INTR, &tw_dev->flags); clear_bit(TW_IN_INTR, &tw_dev->flags);
} /* End tw_interrupt() */ } /* End tw_interrupt() */
...@@ -1782,7 +1818,7 @@ int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id) ...@@ -1782,7 +1818,7 @@ int tw_ioctl_complete(TW_Device_Extension *tw_dev, int request_id)
break; break;
case TW_CMD_PACKET_WITH_DATA: case TW_CMD_PACKET_WITH_DATA:
dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_ioctl_complete(): caught TW_CMD_PACKET_WITH_DATA.\n");
return 2; /* Special case for isr to not complete io */ return TW_ISR_DONT_COMPLETE; /* Special case for isr to not complete io */
default: default:
memset(buff, 0, tw_dev->srb[request_id]->request_bufflen); memset(buff, 0, tw_dev->srb[request_id]->request_bufflen);
param = (TW_Param *)tw_dev->alignment_virtual_address[request_id]; param = (TW_Param *)tw_dev->alignment_virtual_address[request_id];
...@@ -1852,7 +1888,7 @@ int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds) ...@@ -1852,7 +1888,7 @@ int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
if (tw_check_bits(status_reg_value)) { if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value); tw_decode_bits(tw_dev, status_reg_value, 0);
} }
while ((status_reg_value & flag) != flag) { while ((status_reg_value & flag) != flag) {
...@@ -1860,7 +1896,7 @@ int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds) ...@@ -1860,7 +1896,7 @@ int tw_poll_status(TW_Device_Extension *tw_dev, u32 flag, int seconds)
if (tw_check_bits(status_reg_value)) { if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_poll_status(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value); tw_decode_bits(tw_dev, status_reg_value, 0);
} }
do_gettimeofday(&timeout); do_gettimeofday(&timeout);
...@@ -1887,7 +1923,7 @@ int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id) ...@@ -1887,7 +1923,7 @@ int tw_post_command_packet(TW_Device_Extension *tw_dev, int request_id)
if (tw_check_bits(status_reg_value)) { if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_post_command_packet(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value); tw_decode_bits(tw_dev, status_reg_value, 1);
} }
if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) { if ((status_reg_value & TW_STATUS_COMMAND_QUEUE_FULL) == 0) {
...@@ -1941,7 +1977,6 @@ int tw_reset_device_extension(TW_Device_Extension *tw_dev) ...@@ -1941,7 +1977,6 @@ int tw_reset_device_extension(TW_Device_Extension *tw_dev)
(tw_dev->state[i] != TW_S_COMPLETED)) { (tw_dev->state[i] != TW_S_COMPLETED)) {
srb = tw_dev->srb[i]; srb = tw_dev->srb[i];
if (srb != NULL) { if (srb != NULL) {
srb = tw_dev->srb[i];
srb->result = (DID_RESET << 16); srb->result = (DID_RESET << 16);
tw_dev->srb[i]->scsi_done(tw_dev->srb[i]); tw_dev->srb[i]->scsi_done(tw_dev->srb[i]);
tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]); tw_unmap_scsi_data(tw_dev->tw_pci_dev, tw_dev->srb[i]);
...@@ -1960,6 +1995,7 @@ int tw_reset_device_extension(TW_Device_Extension *tw_dev) ...@@ -1960,6 +1995,7 @@ int tw_reset_device_extension(TW_Device_Extension *tw_dev)
tw_dev->pending_request_count = 0; tw_dev->pending_request_count = 0;
tw_dev->pending_head = TW_Q_START; tw_dev->pending_head = TW_Q_START;
tw_dev->pending_tail = TW_Q_START; tw_dev->pending_tail = TW_Q_START;
tw_dev->reset_print = 0;
return 0; return 0;
} /* End tw_reset_device_extension() */ } /* End tw_reset_device_extension() */
...@@ -1991,14 +2027,6 @@ int tw_reset_sequence(TW_Device_Extension *tw_dev) ...@@ -1991,14 +2027,6 @@ int tw_reset_sequence(TW_Device_Extension *tw_dev)
continue; continue;
} }
/* Empty the response queue again */
error = tw_empty_response_que(tw_dev);
if (error) {
printk(KERN_WARNING "3w-xxxx: scsi%d: Couldn't empty response queue, retrying.\n", tw_dev->host->host_no);
tries++;
continue;
}
/* Now the controller is in a good state */ /* Now the controller is in a good state */
break; break;
} }
...@@ -2086,11 +2114,6 @@ int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt) ...@@ -2086,11 +2114,6 @@ int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt)
return (FAILED); return (FAILED);
} }
/* We have to let AEN requests through before the reset */
spin_unlock_irq(tw_dev->host->host_lock);
mdelay(TW_AEN_WAIT_TIME);
spin_lock_irq(tw_dev->host->host_lock);
spin_lock(&tw_dev->tw_lock); spin_lock(&tw_dev->tw_lock);
tw_dev->num_aborts++; tw_dev->num_aborts++;
...@@ -2117,18 +2140,26 @@ int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt) ...@@ -2117,18 +2140,26 @@ int tw_scsi_eh_abort(Scsi_Cmnd *SCpnt)
spin_unlock(&tw_dev->tw_lock); spin_unlock(&tw_dev->tw_lock);
return (SUCCESS); return (SUCCESS);
} }
} if (tw_dev->state[i] == TW_S_POSTED) {
}
/* If the command has already been posted, we have to reset the card */ /* If the command has already been posted, we have to reset the card */
printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, (u32)SCpnt); printk(KERN_WARNING "3w-xxxx: scsi%d: Command (0x%x) timed out, resetting card.\n", tw_dev->host->host_no, (u32)SCpnt);
/* We have to let AEN requests through before the reset */
spin_unlock(&tw_dev->tw_lock);
spin_unlock_irq(tw_dev->host->host_lock);
mdelay(TW_AEN_WAIT_TIME);
spin_lock_irq(tw_dev->host->host_lock);
spin_lock(&tw_dev->tw_lock);
if (tw_reset_device_extension(tw_dev)) { if (tw_reset_device_extension(tw_dev)) {
dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no); dprintk(KERN_WARNING "3w-xxxx: tw_scsi_eh_abort(): Reset failed for card %d.\n", tw_dev->host->host_no);
spin_unlock(&tw_dev->tw_lock); spin_unlock(&tw_dev->tw_lock);
return (FAILED); return (FAILED);
} }
spin_unlock(&tw_dev->tw_lock); }
}
}
spin_unlock(&tw_dev->tw_lock);
return (SUCCESS); return (SUCCESS);
} /* End tw_scsi_eh_abort() */ } /* End tw_scsi_eh_abort() */
...@@ -2593,7 +2624,7 @@ int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) ...@@ -2593,7 +2624,7 @@ int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
} }
command_packet->byte0.sgl_offset = 3; command_packet->byte0.sgl_offset = 3;
command_packet->size = 5; command_packet->size = 3;
command_packet->request_id = request_id; command_packet->request_id = request_id;
command_packet->byte3.unit = srb->target; command_packet->byte3.unit = srb->target;
command_packet->byte3.host_id = 0; command_packet->byte3.host_id = 0;
...@@ -2628,6 +2659,7 @@ int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) ...@@ -2628,6 +2659,7 @@ int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]); buffaddr = tw_map_scsi_single_data(tw_dev->tw_pci_dev, tw_dev->srb[request_id]);
command_packet->byte8.io.sgl[0].address = buffaddr; command_packet->byte8.io.sgl[0].address = buffaddr;
command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen; command_packet->byte8.io.sgl[0].length = tw_dev->srb[request_id]->request_bufflen;
command_packet->size+=2;
} }
/* Do this if we have multiple sg list entries */ /* Do this if we have multiple sg list entries */
...@@ -2638,8 +2670,6 @@ int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id) ...@@ -2638,8 +2670,6 @@ int tw_scsiop_read_write(TW_Device_Extension *tw_dev, int request_id)
command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]); command_packet->byte8.io.sgl[i].length = sg_dma_len(&sglist[i]);
command_packet->size+=2; command_packet->size+=2;
} }
if (tw_dev->srb[request_id]->use_sg >= 1)
command_packet->size-=2;
} }
/* Update SG statistics */ /* Update SG statistics */
...@@ -2754,7 +2784,7 @@ int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size, ...@@ -2754,7 +2784,7 @@ int tw_setfeature(TW_Device_Extension *tw_dev, int parm, int param_size,
status_reg_value = inl(status_reg_addr); status_reg_value = inl(status_reg_addr);
if (tw_check_bits(status_reg_value)) { if (tw_check_bits(status_reg_value)) {
dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n"); dprintk(KERN_WARNING "3w-xxxx: tw_setfeature(): Unexpected bits.\n");
tw_decode_bits(tw_dev, status_reg_value); tw_decode_bits(tw_dev, status_reg_value, 1);
return 1; return 1;
} }
if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) { if ((status_reg_value & TW_STATUS_RESPONSE_QUEUE_EMPTY) == 0) {
......
...@@ -92,10 +92,11 @@ static char *tw_aen_string[] = { ...@@ -92,10 +92,11 @@ static char *tw_aen_string[] = {
"Verify failed: Port #", // 0x02A "Verify failed: Port #", // 0x02A
"Verify complete: Unit #", // 0x02B "Verify complete: Unit #", // 0x02B
"Overwrote bad sector during rebuild: Port #", //0x2C "Overwrote bad sector during rebuild: Port #", //0x2C
"Encountered bad sector during rebuild: Port #" //0x2D "Encountered bad sector during rebuild: Port #", //0x2D
"Replacement drive is too small: Port #" //0x2E
}; };
#define TW_AEN_STRING_MAX 0x02E #define TW_AEN_STRING_MAX 0x02F
/* /*
Sense key lookup table Sense key lookup table
...@@ -134,7 +135,9 @@ static unsigned char tw_sense_table[][4] = ...@@ -134,7 +135,9 @@ static unsigned char tw_sense_table[][4] =
#define TW_CONTROL_DISABLE_INTERRUPTS 0x00000040 #define TW_CONTROL_DISABLE_INTERRUPTS 0x00000040
#define TW_CONTROL_ISSUE_HOST_INTERRUPT 0x00000020 #define TW_CONTROL_ISSUE_HOST_INTERRUPT 0x00000020
#define TW_CONTROL_CLEAR_PARITY_ERROR 0x00800000 #define TW_CONTROL_CLEAR_PARITY_ERROR 0x00800000
#define TW_CONTROL_CLEAR_QUEUE_ERROR 0x00400000
#define TW_CONTROL_CLEAR_PCI_ABORT 0x00100000 #define TW_CONTROL_CLEAR_PCI_ABORT 0x00100000
#define TW_CONTROL_CLEAR_SBUF_WRITE_ERROR 0x00000008
/* Status register bit definitions */ /* Status register bit definitions */
#define TW_STATUS_MAJOR_VERSION_MASK 0xF0000000 #define TW_STATUS_MAJOR_VERSION_MASK 0xF0000000
...@@ -154,7 +157,9 @@ static unsigned char tw_sense_table[][4] = ...@@ -154,7 +157,9 @@ static unsigned char tw_sense_table[][4] =
#define TW_STATUS_ALL_INTERRUPTS 0x000F0000 #define TW_STATUS_ALL_INTERRUPTS 0x000F0000
#define TW_STATUS_CLEARABLE_BITS 0x00D00000 #define TW_STATUS_CLEARABLE_BITS 0x00D00000
#define TW_STATUS_EXPECTED_BITS 0x00002000 #define TW_STATUS_EXPECTED_BITS 0x00002000
#define TW_STATUS_UNEXPECTED_BITS 0x00F80000 #define TW_STATUS_UNEXPECTED_BITS 0x00F00008
#define TW_STATUS_SBUF_WRITE_ERROR 0x00000008
#define TW_STATUS_VALID_INTERRUPT 0x00DF0008
/* RESPONSE QUEUE BIT DEFINITIONS */ /* RESPONSE QUEUE BIT DEFINITIONS */
#define TW_RESPONSE_ID_MASK 0x00000FF0 #define TW_RESPONSE_ID_MASK 0x00000FF0
...@@ -214,7 +219,7 @@ static unsigned char tw_sense_table[][4] = ...@@ -214,7 +219,7 @@ static unsigned char tw_sense_table[][4] =
#define TW_MAX_PCI_BUSES 255 #define TW_MAX_PCI_BUSES 255
#define TW_MAX_RESET_TRIES 3 #define TW_MAX_RESET_TRIES 3
#define TW_UNIT_INFORMATION_TABLE_BASE 0x300 #define TW_UNIT_INFORMATION_TABLE_BASE 0x300
#define TW_MAX_CMDS_PER_LUN (TW_Q_LENGTH-2)/TW_MAX_UNITS #define TW_MAX_CMDS_PER_LUN 255
#define TW_BLOCK_SIZE 0x200 /* 512-byte blocks */ #define TW_BLOCK_SIZE 0x200 /* 512-byte blocks */
#define TW_IOCTL 0x80 #define TW_IOCTL 0x80
#define TW_MAX_AEN_TRIES 100 #define TW_MAX_AEN_TRIES 100
...@@ -223,6 +228,8 @@ static unsigned char tw_sense_table[][4] = ...@@ -223,6 +228,8 @@ static unsigned char tw_sense_table[][4] =
#define TW_MAX_SECTORS 256 #define TW_MAX_SECTORS 256
#define TW_AEN_WAIT_TIME 1000 #define TW_AEN_WAIT_TIME 1000
#define TW_IOCTL_WAIT_TIME (1 * HZ) /* 1 second */ #define TW_IOCTL_WAIT_TIME (1 * HZ) /* 1 second */
#define TW_ISR_DONT_COMPLETE 2
#define TW_ISR_DONT_RESULT 3
/* Macros */ /* Macros */
#define TW_STATUS_ERRORS(x) \ #define TW_STATUS_ERRORS(x) \
...@@ -235,7 +242,7 @@ static unsigned char tw_sense_table[][4] = ...@@ -235,7 +242,7 @@ static unsigned char tw_sense_table[][4] =
#ifdef TW_DEBUG #ifdef TW_DEBUG
#define dprintk(msg...) printk(msg) #define dprintk(msg...) printk(msg)
#else #else
#define dprintk(msg...) do { } while(0); #define dprintk(msg...) do { } while(0)
#endif #endif
/* Scatter Gather List Entry */ /* Scatter Gather List Entry */
...@@ -402,8 +409,9 @@ typedef struct TAG_TW_Device_Extension { ...@@ -402,8 +409,9 @@ typedef struct TAG_TW_Device_Extension {
unsigned short aen_queue[TW_Q_LENGTH]; unsigned short aen_queue[TW_Q_LENGTH];
unsigned char aen_head; unsigned char aen_head;
unsigned char aen_tail; unsigned char aen_tail;
long flags; /* long req'd for set_bit --RR */ volatile long flags; /* long req'd for set_bit --RR */
char *ioctl_data[TW_Q_LENGTH]; char *ioctl_data[TW_Q_LENGTH];
int reset_print;
} TW_Device_Extension; } TW_Device_Extension;
/* Function prototypes */ /* Function prototypes */
...@@ -413,12 +421,13 @@ int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id); ...@@ -413,12 +421,13 @@ int tw_aen_read_queue(TW_Device_Extension *tw_dev, int request_id);
int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which); int tw_allocate_memory(TW_Device_Extension *tw_dev, int size, int which);
int tw_check_bits(u32 status_reg_value); int tw_check_bits(u32 status_reg_value);
int tw_check_errors(TW_Device_Extension *tw_dev); int tw_check_errors(TW_Device_Extension *tw_dev);
void tw_clear_all_interrupts(TW_Device_Extension *tw_dev);
void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev); void tw_clear_attention_interrupt(TW_Device_Extension *tw_dev);
void tw_clear_host_interrupt(TW_Device_Extension *tw_dev); void tw_clear_host_interrupt(TW_Device_Extension *tw_dev);
void tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value); int tw_decode_bits(TW_Device_Extension *tw_dev, u32 status_reg_value, int print_host);
void tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense); int tw_decode_sense(TW_Device_Extension *tw_dev, int request_id, int fill_sense);
void tw_disable_interrupts(TW_Device_Extension *tw_dev); void tw_disable_interrupts(TW_Device_Extension *tw_dev);
int tw_empty_response_que(TW_Device_Extension *tw_dev); void tw_empty_response_que(TW_Device_Extension *tw_dev);
void tw_enable_interrupts(TW_Device_Extension *tw_dev); void tw_enable_interrupts(TW_Device_Extension *tw_dev);
void tw_enable_and_clear_interrupts(TW_Device_Extension *tw_dev); void tw_enable_and_clear_interrupts(TW_Device_Extension *tw_dev);
int tw_findcards(Scsi_Host_Template *tw_host); int tw_findcards(Scsi_Host_Template *tw_host);
...@@ -478,7 +487,7 @@ void tw_unmask_command_interrupt(TW_Device_Extension *tw_dev); ...@@ -478,7 +487,7 @@ void tw_unmask_command_interrupt(TW_Device_Extension *tw_dev);
reset : NULL, \ reset : NULL, \
slave_attach : NULL, \ slave_attach : NULL, \
bios_param : tw_scsi_biosparam, \ bios_param : tw_scsi_biosparam, \
can_queue : TW_Q_LENGTH, \ can_queue : TW_Q_LENGTH-1, \
this_id: -1, \ this_id: -1, \
sg_tablesize : TW_MAX_SGL_LENGTH, \ sg_tablesize : TW_MAX_SGL_LENGTH, \
cmd_per_lun: TW_MAX_CMDS_PER_LUN, \ cmd_per_lun: TW_MAX_CMDS_PER_LUN, \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment