Ivan Sergio Borgonovo <i...@webthatworks.it> writes: > I've just tested 2.6.32-28 from latest iso and it still doesn't work. > The version of this driver included in experimental is reported to work > on other distribution (0.17). > > If you'd point me to some RTFM to help you test something that could > give some more chance to add support to these controller in the upcoming > stable I'd try to help.
A start would be to use the reportbug tool so that the kernel team got all the relevant data in the bug report, in particular the lspci listing. Took me a while to finally find a PCI device id to verify which devices you're after. Finally found it in http://launchpadlibrarian.net/51569322/Lspci.txt: 01:00.0 RAID bus controller [0104]: LSI Logic / Symbios Logic MegaRAID SAS 9240 [1000:0073] (rev 02) which was added to the driver between v2.6.32..v2.6.33. commit 879111224d in Linus' tree is the one that actually added the device to the module alias list. I've included it below. You could try and see if this is enough, or if the whole driver needs to be updated to the 2.6.33 version (which is LSI megasas version "00.00.04.12-rc1"). Bjørn
commit 879111224d0784eab623fe8130a1f4481e0e1966 Author: Yang, Bo <bo.y...@lsi.com> Date: Tue Oct 6 14:31:54 2009 -0600 [SCSI] megaraid_sas: Add new megaraid SAS 2 controller support to the driver Add the new megaraid sas 2 controller to the driver. megaraid sas2 is LSI next generation SAS products. driver add the interface to support this product. Signed-off-by Bo Yang<bo.y...@lsi.com> Signed-off-by: James Bottomley <james.bottom...@suse.de> diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 0121413..b6e4327 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -76,6 +76,10 @@ static struct pci_device_id megasas_pci_table[] = { /* gen2*/ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)}, /* gen2*/ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)}, + /* skinny*/ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)}, + /* skinny*/ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, /* xscale IOP, vega */ {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, @@ -335,6 +339,99 @@ static struct megasas_instance_template megasas_instance_template_ppc = { }; /** + * megasas_enable_intr_skinny - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs) +{ + writel(0xFFFFFFFF, &(regs)->outbound_intr_mask); + + writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr_skinny - Disables interrupt + * @regs: MFI register set + */ +static inline void +megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs) +{ + u32 mask = 0xFFFFFFFF; + writel(mask, ®s->outbound_intr_mask); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_read_fw_status_reg_skinny - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs) +{ + return readl(&(regs)->outbound_scratch_pad); +} + +/** + * megasas_clear_interrupt_skinny - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs) +{ + u32 status; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) { + return 1; + } + + /* + * Clear the interrupt by writing back the same value + */ + writel(status, ®s->outbound_intr_status); + + /* + * dummy read to flush PCI + */ + readl(®s->outbound_intr_status); + + return 0; +} + +/** + * megasas_fire_cmd_skinny - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_skinny(dma_addr_t frame_phys_addr, u32 frame_count, + struct megasas_register_set __iomem *regs) +{ + writel(0, &(regs)->inbound_high_queue_port); + writel((frame_phys_addr | (frame_count<<1))|1, + &(regs)->inbound_low_queue_port); +} + +static struct megasas_instance_template megasas_instance_template_skinny = { + + .fire_cmd = megasas_fire_cmd_skinny, + .enable_intr = megasas_enable_intr_skinny, + .disable_intr = megasas_disable_intr_skinny, + .clear_intr = megasas_clear_intr_skinny, + .read_fw_status_reg = megasas_read_fw_status_reg_skinny, +}; + + +/** * The following functions are defined for gen2 (deviceid : 0x78 0x79) * controllers */ @@ -1587,16 +1684,34 @@ megasas_transition_to_ready(struct megasas_instance* instance) /* * Set the CLR bit in inbound doorbell */ - writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, - &instance->reg_set->inbound_doorbell); + if ((instance->pdev->device == \ + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + + writel( + MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, + &instance->reg_set->reserved_0[0]); + } else { + writel( + MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, + &instance->reg_set->inbound_doorbell); + } max_wait = 2; cur_state = MFI_STATE_WAIT_HANDSHAKE; break; case MFI_STATE_BOOT_MESSAGE_PENDING: - writel(MFI_INIT_HOTPLUG, - &instance->reg_set->inbound_doorbell); + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + writel(MFI_INIT_HOTPLUG, + &instance->reg_set->reserved_0[0]); + } else + writel(MFI_INIT_HOTPLUG, + &instance->reg_set->inbound_doorbell); max_wait = 10; cur_state = MFI_STATE_BOOT_MESSAGE_PENDING; @@ -1607,7 +1722,15 @@ megasas_transition_to_ready(struct megasas_instance* instance) * Bring it to READY state; assuming max wait 10 secs */ instance->instancet->disable_intr(instance->reg_set); - writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell); + if ((instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || + (instance->pdev->device == + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { + writel(MFI_RESET_FLAGS, + &instance->reg_set->reserved_0[0]); + } else + writel(MFI_RESET_FLAGS, + &instance->reg_set->inbound_doorbell); max_wait = 60; cur_state = MFI_STATE_OPERATIONAL; @@ -2112,6 +2235,8 @@ static int megasas_init_mfi(struct megasas_instance *instance) * Map the message registers */ if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) { instance->base_addr = pci_resource_start(instance->pdev, 1); } else { @@ -2142,6 +2267,10 @@ static int megasas_init_mfi(struct megasas_instance *instance) case PCI_DEVICE_ID_LSI_SAS0079GEN2: instance->instancet = &megasas_instance_template_gen2; break; + case PCI_DEVICE_ID_LSI_SAS0073SKINNY: + case PCI_DEVICE_ID_LSI_SAS0071SKINNY: + instance->instancet = &megasas_instance_template_skinny; + break; case PCI_DEVICE_ID_LSI_SAS1064R: case PCI_DEVICE_ID_DELL_PERC5: default: diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 900359f..365a961 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -30,6 +30,8 @@ #define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413 #define PCI_DEVICE_ID_LSI_SAS1078GEN2 0x0078 #define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079 +#define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073 +#define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071 /* * ===================================== @@ -584,6 +586,8 @@ struct megasas_ctrl_info { #define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 #define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001 #define MFI_GEN2_ENABLE_INTERRUPT_MASK (0x00000001 | 0x00000004) +#define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT 0x40000000 +#define MFI_SKINNY_ENABLE_INTERRUPT_MASK (0x00000001) /* * register set for both 1068 and 1078 controllers