aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/megaraid/megaraid_sas.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/megaraid/megaraid_sas.c')
-rw-r--r--drivers/scsi/megaraid/megaraid_sas.c119
1 files changed, 116 insertions, 3 deletions
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c
index fc7ac158476c..97b763378e7d 100644
--- a/drivers/scsi/megaraid/megaraid_sas.c
+++ b/drivers/scsi/megaraid/megaraid_sas.c
@@ -10,7 +10,7 @@
10 * 2 of the License, or (at your option) any later version. 10 * 2 of the License, or (at your option) any later version.
11 * 11 *
12 * FILE : megaraid_sas.c 12 * FILE : megaraid_sas.c
13 * Version : v00.00.03.20-rc1 13 * Version : v00.00.04.01-rc1
14 * 14 *
15 * Authors: 15 * Authors:
16 * (email-id : megaraidlinux@lsi.com) 16 * (email-id : megaraidlinux@lsi.com)
@@ -71,6 +71,10 @@ static struct pci_device_id megasas_pci_table[] = {
71 /* ppc IOP */ 71 /* ppc IOP */
72 {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)}, 72 {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)},
73 /* ppc IOP */ 73 /* ppc IOP */
74 {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)},
75 /* gen2*/
76 {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)},
77 /* gen2*/
74 {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, 78 {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)},
75 /* xscale IOP, vega */ 79 /* xscale IOP, vega */
76 {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, 80 {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)},
@@ -198,6 +202,9 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs)
198 */ 202 */
199 writel(status, &regs->outbound_intr_status); 203 writel(status, &regs->outbound_intr_status);
200 204
205 /* Dummy readl to force pci flush */
206 readl(&regs->outbound_intr_status);
207
201 return 0; 208 return 0;
202} 209}
203 210
@@ -293,6 +300,9 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs)
293 */ 300 */
294 writel(status, &regs->outbound_doorbell_clear); 301 writel(status, &regs->outbound_doorbell_clear);
295 302
303 /* Dummy readl to force pci flush */
304 readl(&regs->outbound_doorbell_clear);
305
296 return 0; 306 return 0;
297} 307}
298/** 308/**
@@ -318,6 +328,99 @@ static struct megasas_instance_template megasas_instance_template_ppc = {
318}; 328};
319 329
320/** 330/**
331* The following functions are defined for gen2 (deviceid : 0x78 0x79)
332* controllers
333*/
334
335/**
336 * megasas_enable_intr_gen2 - Enables interrupts
337 * @regs: MFI register set
338 */
339static inline void
340megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs)
341{
342 writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear);
343
344 /* write ~0x00000005 (4 & 1) to the intr mask*/
345 writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask);
346
347 /* Dummy readl to force pci flush */
348 readl(&regs->outbound_intr_mask);
349}
350
351/**
352 * megasas_disable_intr_gen2 - Disables interrupt
353 * @regs: MFI register set
354 */
355static inline void
356megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs)
357{
358 u32 mask = 0xFFFFFFFF;
359 writel(mask, &regs->outbound_intr_mask);
360 /* Dummy readl to force pci flush */
361 readl(&regs->outbound_intr_mask);
362}
363
364/**
365 * megasas_read_fw_status_reg_gen2 - returns the current FW status value
366 * @regs: MFI register set
367 */
368static u32
369megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs)
370{
371 return readl(&(regs)->outbound_scratch_pad);
372}
373
374/**
375 * megasas_clear_interrupt_gen2 - Check & clear interrupt
376 * @regs: MFI register set
377 */
378static int
379megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs)
380{
381 u32 status;
382 /*
383 * Check if it is our interrupt
384 */
385 status = readl(&regs->outbound_intr_status);
386
387 if (!(status & MFI_GEN2_ENABLE_INTERRUPT_MASK))
388 return 1;
389
390 /*
391 * Clear the interrupt by writing back the same value
392 */
393 writel(status, &regs->outbound_doorbell_clear);
394
395 /* Dummy readl to force pci flush */
396 readl(&regs->outbound_intr_status);
397
398 return 0;
399}
400/**
401 * megasas_fire_cmd_gen2 - Sends command to the FW
402 * @frame_phys_addr : Physical address of cmd
403 * @frame_count : Number of frames for the command
404 * @regs : MFI register set
405 */
406static inline void
407megasas_fire_cmd_gen2(dma_addr_t frame_phys_addr, u32 frame_count,
408 struct megasas_register_set __iomem *regs)
409{
410 writel((frame_phys_addr | (frame_count<<1))|1,
411 &(regs)->inbound_queue_port);
412}
413
414static struct megasas_instance_template megasas_instance_template_gen2 = {
415
416 .fire_cmd = megasas_fire_cmd_gen2,
417 .enable_intr = megasas_enable_intr_gen2,
418 .disable_intr = megasas_disable_intr_gen2,
419 .clear_intr = megasas_clear_intr_gen2,
420 .read_fw_status_reg = megasas_read_fw_status_reg_gen2,
421};
422
423/**
321* This is the end of set of functions & definitions 424* This is the end of set of functions & definitions
322* specific to ppc (deviceid : 0x60) controllers 425* specific to ppc (deviceid : 0x60) controllers
323*/ 426*/
@@ -1976,7 +2079,12 @@ static int megasas_init_mfi(struct megasas_instance *instance)
1976 /* 2079 /*
1977 * Map the message registers 2080 * Map the message registers
1978 */ 2081 */
1979 instance->base_addr = pci_resource_start(instance->pdev, 0); 2082 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) ||
2083 (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) {
2084 instance->base_addr = pci_resource_start(instance->pdev, 1);
2085 } else {
2086 instance->base_addr = pci_resource_start(instance->pdev, 0);
2087 }
1980 2088
1981 if (pci_request_regions(instance->pdev, "megasas: LSI")) { 2089 if (pci_request_regions(instance->pdev, "megasas: LSI")) {
1982 printk(KERN_DEBUG "megasas: IO memory region busy!\n"); 2090 printk(KERN_DEBUG "megasas: IO memory region busy!\n");
@@ -1998,6 +2106,10 @@ static int megasas_init_mfi(struct megasas_instance *instance)
1998 case PCI_DEVICE_ID_LSI_SAS1078DE: 2106 case PCI_DEVICE_ID_LSI_SAS1078DE:
1999 instance->instancet = &megasas_instance_template_ppc; 2107 instance->instancet = &megasas_instance_template_ppc;
2000 break; 2108 break;
2109 case PCI_DEVICE_ID_LSI_SAS1078GEN2:
2110 case PCI_DEVICE_ID_LSI_SAS0079GEN2:
2111 instance->instancet = &megasas_instance_template_gen2;
2112 break;
2001 case PCI_DEVICE_ID_LSI_SAS1064R: 2113 case PCI_DEVICE_ID_LSI_SAS1064R:
2002 case PCI_DEVICE_ID_DELL_PERC5: 2114 case PCI_DEVICE_ID_DELL_PERC5:
2003 default: 2115 default:
@@ -2857,6 +2969,7 @@ static void megasas_shutdown(struct pci_dev *pdev)
2857{ 2969{
2858 struct megasas_instance *instance = pci_get_drvdata(pdev); 2970 struct megasas_instance *instance = pci_get_drvdata(pdev);
2859 megasas_flush_cache(instance); 2971 megasas_flush_cache(instance);
2972 megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN);
2860} 2973}
2861 2974
2862/** 2975/**
@@ -3292,7 +3405,7 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun
3292 return retval; 3405 return retval;
3293} 3406}
3294 3407
3295static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl, 3408static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl,
3296 megasas_sysfs_set_dbg_lvl); 3409 megasas_sysfs_set_dbg_lvl);
3297 3410
3298static ssize_t 3411static ssize_t