8 May
2007
8 May
'07
16:04
I have never done that before, not even sure where to begin at this point. How would go about this an using the new kernel at installation time. Jack > > Why don't you try to build a 10.2 kernel with drivers/scsi/3w-9xxx.c > and > taken from the 10.3 Alpha kernel? Or apply the following diff (though I > haven't checked wether it builds and/or works). > > Philipp > > --- linux-2.6.18/drivers/scsi/3w-9xxx.c 2006-09-20 05:42:06.000000000 > +0200 > +++ linux-2.6.21/drivers/scsi/3w-9xxx.c 2007-04-26 05:08:32.000000000 > +0200 > @@ -66,6 +66,9 @@ > 2.26.02.006 - Fix 9550SX pchip reset timeout. > Add big endian support. > 2.26.02.007 - Disable local interrupts during kmap/unmap_atomic(). > + 2.26.02.008 - Free irq handler in __twa_shutdown(). > + Serialize reset code. > + Add support for 9650SE controllers. > */ > > #include <linux/module.h> > @@ -89,7 +92,7 @@ > #include "3w-9xxx.h" > > /* Globals */ > -#define TW_DRIVER_VERSION "2.26.02.007" > +#define TW_DRIVER_VERSION "2.26.02.008" > static TW_Device_Extension *twa_device_extension_list[TW_MAX_SLOT]; > static unsigned int twa_device_extension_count; > static int twa_major = -1; > @@ -194,7 +197,7 @@ static struct class_device_attribute *tw > }; > > /* File operations struct for character device */ > -static struct file_operations twa_fops = { > +static const struct file_operations twa_fops = { > .owner = THIS_MODULE, > .ioctl = twa_chrdev_ioctl, > .open = twa_chrdev_open, > @@ -566,9 +569,9 @@ static int twa_check_srl(TW_Device_Exten > goto out; > } > > - tw_dev->working_srl = fw_on_ctlr_srl; > - tw_dev->working_branch = fw_on_ctlr_branch; > - tw_dev->working_build = fw_on_ctlr_build; > + tw_dev->tw_compat_info.working_srl = fw_on_ctlr_srl; > + tw_dev->tw_compat_info.working_branch = fw_on_ctlr_branch; > + tw_dev->tw_compat_info.working_build = fw_on_ctlr_build; > > /* Try base mode compatibility */ > if (!(init_connect_result & TW_CTLR_FW_COMPATIBLE)) { > @@ -590,10 +593,23 @@ static int twa_check_srl(TW_Device_Exten > } > goto out; > } > - tw_dev->working_srl = TW_BASE_FW_SRL; > - tw_dev->working_branch = TW_BASE_FW_BRANCH; > - tw_dev->working_build = TW_BASE_FW_BUILD; > - } > + tw_dev->tw_compat_info.working_srl = TW_BASE_FW_SRL; > + tw_dev->tw_compat_info.working_branch = TW_BASE_FW_BRANCH; > + tw_dev->tw_compat_info.working_build = TW_BASE_FW_BUILD; > + } > + > + /* Load rest of compatibility struct */ > + strncpy(tw_dev->tw_compat_info.driver_version, TW_DRIVER_VERSION, > strlen(TW_DRIVER_VERSION)); > + tw_dev->tw_compat_info.driver_srl_high = TW_CURRENT_DRIVER_SRL; > + tw_dev->tw_compat_info.driver_branch_high = > TW_CURRENT_DRIVER_BRANCH; > + tw_dev->tw_compat_info.driver_build_high = > TW_CURRENT_DRIVER_BUILD; > + tw_dev->tw_compat_info.driver_srl_low = TW_BASE_FW_SRL; > + tw_dev->tw_compat_info.driver_branch_low = TW_BASE_FW_BRANCH; > + tw_dev->tw_compat_info.driver_build_low = TW_BASE_FW_BUILD; > + tw_dev->tw_compat_info.fw_on_ctlr_srl = fw_on_ctlr_srl; > + tw_dev->tw_compat_info.fw_on_ctlr_branch = fw_on_ctlr_branch; > + tw_dev->tw_compat_info.fw_on_ctlr_build = fw_on_ctlr_build; > + > retval = 0; > out: > return retval; > @@ -631,7 +647,7 @@ static int twa_chrdev_ioctl(struct inode > goto out2; > > /* Check data buffer size */ > - if (driver_command.buffer_length > TW_MAX_SECTORS * 512) { > + if (driver_command.buffer_length > TW_MAX_SECTORS * 2048) { > retval = TW_IOCTL_ERROR_OS_EINVAL; > goto out2; > } > @@ -680,13 +696,6 @@ static int twa_chrdev_ioctl(struct inode > /* Now wait for command to complete */ > timeout = wait_event_timeout(tw_dev->ioctl_wqueue, tw_dev- > >chrdev_request_id == TW_IOCTL_CHRDEV_FREE, timeout); > > - /* See if we reset while waiting for the ioctl to complete > */ > - if (test_bit(TW_IN_RESET, &tw_dev->flags)) { > - clear_bit(TW_IN_RESET, &tw_dev->flags); > - retval = TW_IOCTL_ERROR_OS_ERESTARTSYS; > - goto out3; > - } > - > /* We timed out, and didn't get an interrupt */ > if (tw_dev->chrdev_request_id != TW_IOCTL_CHRDEV_FREE) { > /* Now we need to reset the board */ > @@ -694,11 +703,6 @@ static int twa_chrdev_ioctl(struct inode > tw_dev->host->host_no, TW_DRIVER, 0xc, > cmd); > retval = TW_IOCTL_ERROR_OS_EIO; > - spin_lock_irqsave(tw_dev->host->host_lock, flags); > - tw_dev->state[request_id] = TW_S_COMPLETED; > - twa_free_request_id(tw_dev, request_id); > - tw_dev->posted_request_count--; > - spin_unlock_irqrestore(tw_dev->host->host_lock, > flags); > twa_reset_device_extension(tw_dev, 1); > goto out3; > } > @@ -717,16 +721,7 @@ static int twa_chrdev_ioctl(struct inode > tw_ioctl->driver_command.status = 0; > /* Copy compatiblity struct into ioctl data buffer */ > tw_compat_info = (TW_Compatibility_Info *)tw_ioctl- > >data_buffer; > - strncpy(tw_compat_info->driver_version, TW_DRIVER_VERSION, > strlen(TW_DRIVER_VERSION)); > - tw_compat_info->working_srl = tw_dev->working_srl; > - tw_compat_info->working_branch = tw_dev->working_branch; > - tw_compat_info->working_build = tw_dev->working_build; > - tw_compat_info->driver_srl_high = TW_CURRENT_DRIVER_SRL; > - tw_compat_info->driver_branch_high = > TW_CURRENT_DRIVER_BRANCH; > - tw_compat_info->driver_build_high = > TW_CURRENT_DRIVER_BUILD; > - tw_compat_info->driver_srl_low = TW_BASE_FW_SRL; > - tw_compat_info->driver_branch_low = TW_BASE_FW_BRANCH; > - tw_compat_info->driver_build_low = TW_BASE_FW_BUILD; > + memcpy(tw_compat_info, &tw_dev->tw_compat_info, > sizeof(TW_Compatibility_Info)); > break; > case TW_IOCTL_GET_LAST_EVENT: > if (tw_dev->event_queue_wrapped) { > @@ -895,7 +890,8 @@ static int twa_decode_bits(TW_Device_Ext > } > > if (status_reg_value & TW_STATUS_QUEUE_ERROR) { > - TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller Queue > Error: clearing"); > + if ((tw_dev->tw_pci_dev->device != > PCI_DEVICE_ID_3WARE_9650SE) || (!test_bit(TW_IN_RESET, &tw_dev- > >flags))) > + TW_PRINTK(tw_dev->host, TW_DRIVER, 0xe, "Controller > Queue Error: clearing"); > writel(TW_CONTROL_CLEAR_QUEUE_ERROR, > TW_CONTROL_REG_ADDR(tw_dev)); > } > > @@ -939,10 +935,12 @@ static int twa_empty_response_queue_larg > unsigned long before; > int retval = 1; > > - if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) { > + if ((tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9550SX) || > + (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE)) { > before = jiffies; > while ((response_que_value & TW_9550SX_DRAIN_COMPLETED) != > TW_9550SX_DRAIN_COMPLETED) { > response_que_value = > readl(TW_RESPONSE_QUEUE_REG_ADDR_LARGE(tw_dev)); > + msleep(1); > if (time_after(jiffies, before + HZ * 30)) > goto out; > } > @@ -1192,7 +1190,7 @@ out: > } /* End twa_initialize_device_extension() */ > > /* This function is the interrupt service routine */ > -static irqreturn_t twa_interrupt(int irq, void *dev_instance, struct > pt_regs *regs) > +static irqreturn_t twa_interrupt(int irq, void *dev_instance) > { > int request_id, error = 0; > u32 status_reg_value; > @@ -1214,6 +1212,10 @@ static irqreturn_t twa_interrupt(int irq > > handled = 1; > > + /* If we are resetting, bail */ > + if (test_bit(TW_IN_RESET, &tw_dev->flags)) > + goto twa_interrupt_bail; > + > /* Check controller for errors */ > if (twa_check_bits(status_reg_value)) { > if (twa_decode_bits(tw_dev, status_reg_value)) { > @@ -1355,8 +1357,8 @@ static void twa_load_sgl(TW_Command_Full > > if (TW_OP_OUT(full_command_packet- > >command.newcommand.opcode__reserved) == TW_OP_EXECUTE_SCSI) { > newcommand = &full_command_packet->command.newcommand; > - newcommand->request_id__lunl = > - TW_REQ_LUN_IN(TW_LUN_OUT(newcommand- > >request_id__lunl), request_id); > + newcommand->request_id__lunl = > + cpu_to_le16(TW_REQ_LUN_IN(TW_LUN_OUT(newcommand- > >request_id__lunl), request_id)); > newcommand->sg_list[0].address = TW_CPU_TO_SGL(dma_handle + > sizeof(TW_Ioctl_Buf_Apache) - 1); > newcommand->sg_list[0].length = cpu_to_le32(length); > newcommand->sgl_entries__lunh = > @@ -1531,6 +1533,13 @@ static int twa_post_command_packet(TW_De > int retval = 1; > > command_que_value = tw_dev->command_packet_phys[request_id]; > + > + /* For 9650SE write low 4 bytes first */ > + if (tw_dev->tw_pci_dev->device == PCI_DEVICE_ID_3WARE_9650SE) { > + command_que_value += TW_COMMAND_OFFSET; > + writel((u32)command_que_value, > TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev)); > + } > + > status_reg_value = readl(TW_STATUS_REG_ADDR(tw_dev)); > > if (twa_check_bits(status_reg_value)) > @@ -1557,13 +1566,17 @@ static int twa_post_command_packet(TW_De > TW_UNMASK_COMMAND_INTERRUPT(tw_dev); > goto out; > } else { > - /* We successfully posted the command packet */ > - if (sizeof(dma_addr_t) > 4) { > - command_que_value += TW_COMMAND_OFFSET; > - writel((u32)command_que_value, > TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); > - writel((u32)((u64)command_que_value >> 32), > TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4); > + if (tw_dev->tw_pci_dev->device == > PCI_DEVICE_ID_3WARE_9650SE) { > + /* Now write upper 4 bytes */ > + writel((u32)((u64)command_que_value >> 32), > TW_COMMAND_QUEUE_REG_ADDR_LARGE(tw_dev) + 0x4); > } else { > - writel(TW_COMMAND_OFFSET + command_que_value, > TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); > + if (sizeof(dma_addr_t) > 4) { > + command_que_value += TW_COMMAND_OFFSET; > + writel((u32)command_que_value, > TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); > + writel((u32)((u64)command_que_value >> 32), > TW_COMMAND_QUEUE_REG_ADDR(tw_dev) + 0x4); > + } else { > + writel(TW_COMMAND_OFFSET + command_que_value, > TW_COMMAND_QUEUE_REG_ADDR(tw_dev)); > + } > } > tw_dev->state[request_id] = TW_S_POSTED; > tw_dev->posted_request_count++; > @@ -1620,14 +1633,9 @@ static int twa_reset_device_extension(TW > goto out; > > TW_ENABLE_AND_CLEAR_INTERRUPTS(tw_dev); > + clear_bit(TW_IN_RESET, &tw_dev->flags); > + tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; > > - /* Wake up any ioctl that was pending before the reset */ > - if ((tw_dev->chrdev_request_id == TW_IOCTL_CHRDEV_FREE) || > (ioctl_reset)) { > - clear_bit(TW_IN_RESET, &tw_dev->flags); > - } else { > - tw_dev->chrdev_request_id = TW_IOCTL_CHRDEV_FREE; > - wake_up(&tw_dev->ioctl_wqueue); > - } > retval = 0; > out: > return retval; > @@ -1736,6 +1744,9 @@ static int twa_scsi_eh_reset(struct scsi > "WARNING: (0x%02X:0x%04X): Command (0x%x) timed out, > resetting card.\n", > TW_DRIVER, 0x2c, SCpnt->cmnd[0]); > > + /* Make sure we are not issuing an ioctl or resetting from ioctl > */ > + mutex_lock(&tw_dev->ioctl_lock); > + > /* Now reset the card and some of the device extension data */ > if (twa_reset_device_extension(tw_dev, 0)) { > TW_PRINTK(tw_dev->host, TW_DRIVER, 0x2b, "Controller reset > failed during scsi host reset"); > @@ -1744,6 +1755,7 @@ static int twa_scsi_eh_reset(struct scsi > > retval = SUCCESS; > out: > + mutex_unlock(&tw_dev->ioctl_lock); > return retval; > } /* End twa_scsi_eh_reset() */ > > @@ -1753,8 +1765,14 @@ static int twa_scsi_queue(struct scsi_cm > int request_id, retval; > TW_Device_Extension *tw_dev = (TW_Device_Extension *)SCpnt- > >device->host->hostdata; > > + /* If we are resetting due to timed out ioctl, report as busy */ > + if (test_bit(TW_IN_RESET, &tw_dev->flags)) { > + retval = SCSI_MLQUEUE_HOST_BUSY; > + goto out; > + } > + > /* Check if this FW supports luns */ > - if ((SCpnt->device->lun != 0) && (tw_dev->working_srl < > TW_FW_SRL_LUNS_SUPPORTED)) { > + if ((SCpnt->device->lun != 0) && (tw_dev- > >tw_compat_info.working_srl < TW_FW_SRL_LUNS_SUPPORTED)) { > SCpnt->result = (DID_BAD_TARGET << 16); > done(SCpnt); > retval = 0; > @@ -1960,6 +1978,9 @@ static void __twa_shutdown(TW_Device_Ext > /* Disable interrupts */ > TW_DISABLE_INTERRUPTS(tw_dev); > > + /* Free up the IRQ */ > + free_irq(tw_dev->tw_pci_dev->irq, tw_dev); > + > printk(KERN_WARNING "3w-9xxx: Shutting down host %d.\n", tw_dev- > >host->host_no); > > /* Tell the card we are shutting down */ > @@ -2091,21 +2112,25 @@ static int __devinit twa_probe(struct pc > > /* Initialize the card */ > if (twa_reset_sequence(tw_dev, 0)) > - goto out_release_mem_region; > + goto out_iounmap; > > /* Set host specific parameters */ > - host->max_id = TW_MAX_UNITS; > + if (pdev->device == PCI_DEVICE_ID_3WARE_9650SE) > + host->max_id = TW_MAX_UNITS_9650SE; > + else > + host->max_id = TW_MAX_UNITS; > + > host->max_cmd_len = TW_MAX_CDB_LEN; > > /* Channels aren't supported by adapter */ > - host->max_lun = TW_MAX_LUNS(tw_dev->working_srl); > + host->max_lun = TW_MAX_LUNS(tw_dev->tw_compat_info.working_srl); > host->max_channel = 0; > > /* Register the card with the kernel SCSI layer */ > retval = scsi_add_host(host, &pdev->dev); > if (retval) { > TW_PRINTK(tw_dev->host, TW_DRIVER, 0x27, "scsi add host > failed"); > - goto out_release_mem_region; > + goto out_iounmap; > } > > pci_set_drvdata(pdev, host); > @@ -2145,6 +2170,8 @@ static int __devinit twa_probe(struct pc > > out_remove_host: > scsi_remove_host(host); > +out_iounmap: > + iounmap(tw_dev->base_addr); > out_release_mem_region: > pci_release_regions(pdev); > out_free_device_extension: > @@ -2170,12 +2197,12 @@ static void twa_remove(struct pci_dev *p > twa_major = -1; > } > > - /* Free up the IRQ */ > - free_irq(tw_dev->tw_pci_dev->irq, tw_dev); > - > /* Shutdown the card */ > __twa_shutdown(tw_dev); > > + /* Free IO remapping */ > + iounmap(tw_dev->base_addr); > + > /* Free up the mem region */ > pci_release_regions(pdev); > > @@ -2193,6 +2220,8 @@ static struct pci_device_id twa_pci_tbl[ > PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, > { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9550SX, > PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, > + { PCI_VENDOR_ID_3WARE, PCI_DEVICE_ID_3WARE_9650SE, > + PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, > { } > }; > MODULE_DEVICE_TABLE(pci, twa_pci_tbl); > @@ -2211,7 +2240,7 @@ static int __init twa_init(void) > { > printk(KERN_WARNING "3ware 9000 Storage Controller device driver > for Linux v%s.\n", TW_DRIVER_VERSION); > > - return pci_module_init(&twa_driver); > + return pci_register_driver(&twa_driver); > } /* End twa_init() */ > > /* This function is called on driver exit */ > -- > To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org > For additional commands, e-mail: opensuse+help@opensuse.org -- To unsubscribe, e-mail: opensuse+unsubscribe@opensuse.org For additional commands, e-mail: opensuse+help@opensuse.org