diff options
Diffstat (limited to 'drivers/scsi/megaraid')
-rw-r--r-- | drivers/scsi/megaraid/mbox_defs.h | 2 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_mbox.c | 10 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_mm.c | 1 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.c | 1017 | ||||
-rw-r--r-- | drivers/scsi/megaraid/megaraid_sas.h | 179 |
5 files changed, 1116 insertions, 93 deletions
diff --git a/drivers/scsi/megaraid/mbox_defs.h b/drivers/scsi/megaraid/mbox_defs.h index b25b74764ec3..ce2487a888ed 100644 --- a/drivers/scsi/megaraid/mbox_defs.h +++ b/drivers/scsi/megaraid/mbox_defs.h | |||
@@ -497,7 +497,7 @@ typedef struct { | |||
497 | * @inserted_drive : channel:Id of inserted drive | 497 | * @inserted_drive : channel:Id of inserted drive |
498 | * @battery_status : bit 0: battery module missing | 498 | * @battery_status : bit 0: battery module missing |
499 | * bit 1: VBAD | 499 | * bit 1: VBAD |
500 | * bit 2: temprature high | 500 | * bit 2: temperature high |
501 | * bit 3: battery pack missing | 501 | * bit 3: battery pack missing |
502 | * bit 4,5: | 502 | * bit 4,5: |
503 | * 00 - charge complete | 503 | * 00 - charge complete |
diff --git a/drivers/scsi/megaraid/megaraid_mbox.c b/drivers/scsi/megaraid/megaraid_mbox.c index 234f0b7eb21c..a7810a106b37 100644 --- a/drivers/scsi/megaraid/megaraid_mbox.c +++ b/drivers/scsi/megaraid/megaraid_mbox.c | |||
@@ -70,6 +70,7 @@ | |||
70 | * For history of changes, see Documentation/ChangeLog.megaraid | 70 | * For history of changes, see Documentation/ChangeLog.megaraid |
71 | */ | 71 | */ |
72 | 72 | ||
73 | #include <linux/slab.h> | ||
73 | #include "megaraid_mbox.h" | 74 | #include "megaraid_mbox.h" |
74 | 75 | ||
75 | static int megaraid_init(void); | 76 | static int megaraid_init(void); |
@@ -335,12 +336,17 @@ static struct device_attribute *megaraid_sdev_attrs[] = { | |||
335 | * megaraid_change_queue_depth - Change the device's queue depth | 336 | * megaraid_change_queue_depth - Change the device's queue depth |
336 | * @sdev: scsi device struct | 337 | * @sdev: scsi device struct |
337 | * @qdepth: depth to set | 338 | * @qdepth: depth to set |
339 | * @reason: calling context | ||
338 | * | 340 | * |
339 | * Return value: | 341 | * Return value: |
340 | * actual depth set | 342 | * actual depth set |
341 | */ | 343 | */ |
342 | static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth) | 344 | static int megaraid_change_queue_depth(struct scsi_device *sdev, int qdepth, |
345 | int reason) | ||
343 | { | 346 | { |
347 | if (reason != SCSI_QDEPTH_DEFAULT) | ||
348 | return -EOPNOTSUPP; | ||
349 | |||
344 | if (qdepth > MBOX_MAX_SCSI_CMDS) | 350 | if (qdepth > MBOX_MAX_SCSI_CMDS) |
345 | qdepth = MBOX_MAX_SCSI_CMDS; | 351 | qdepth = MBOX_MAX_SCSI_CMDS; |
346 | scsi_adjust_queue_depth(sdev, 0, qdepth); | 352 | scsi_adjust_queue_depth(sdev, 0, qdepth); |
@@ -2704,7 +2710,7 @@ megaraid_reset_handler(struct scsi_cmnd *scp) | |||
2704 | } | 2710 | } |
2705 | else { | 2711 | else { |
2706 | con_log(CL_ANN, (KERN_NOTICE | 2712 | con_log(CL_ANN, (KERN_NOTICE |
2707 | "megaraid mbox: reset sequence completed sucessfully\n")); | 2713 | "megaraid mbox: reset sequence completed successfully\n")); |
2708 | } | 2714 | } |
2709 | 2715 | ||
2710 | 2716 | ||
diff --git a/drivers/scsi/megaraid/megaraid_mm.c b/drivers/scsi/megaraid/megaraid_mm.c index f680561d2c6f..36e0b7d05c1d 100644 --- a/drivers/scsi/megaraid/megaraid_mm.c +++ b/drivers/scsi/megaraid/megaraid_mm.c | |||
@@ -15,6 +15,7 @@ | |||
15 | * Common management module | 15 | * Common management module |
16 | */ | 16 | */ |
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/slab.h> | ||
18 | #include <linux/smp_lock.h> | 19 | #include <linux/smp_lock.h> |
19 | #include "megaraid_mm.h" | 20 | #include "megaraid_mm.h" |
20 | 21 | ||
diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index a39addc3a596..99e4478c3f3e 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.04.01-rc1 | 13 | * Version : v00.00.04.17.1-rc1 |
14 | * | 14 | * |
15 | * Authors: | 15 | * Authors: |
16 | * (email-id : megaraidlinux@lsi.com) | 16 | * (email-id : megaraidlinux@lsi.com) |
@@ -35,11 +35,13 @@ | |||
35 | #include <linux/delay.h> | 35 | #include <linux/delay.h> |
36 | #include <linux/smp_lock.h> | 36 | #include <linux/smp_lock.h> |
37 | #include <linux/uio.h> | 37 | #include <linux/uio.h> |
38 | #include <linux/slab.h> | ||
38 | #include <asm/uaccess.h> | 39 | #include <asm/uaccess.h> |
39 | #include <linux/fs.h> | 40 | #include <linux/fs.h> |
40 | #include <linux/compat.h> | 41 | #include <linux/compat.h> |
41 | #include <linux/blkdev.h> | 42 | #include <linux/blkdev.h> |
42 | #include <linux/mutex.h> | 43 | #include <linux/mutex.h> |
44 | #include <linux/poll.h> | ||
43 | 45 | ||
44 | #include <scsi/scsi.h> | 46 | #include <scsi/scsi.h> |
45 | #include <scsi/scsi_cmnd.h> | 47 | #include <scsi/scsi_cmnd.h> |
@@ -75,6 +77,10 @@ static struct pci_device_id megasas_pci_table[] = { | |||
75 | /* gen2*/ | 77 | /* gen2*/ |
76 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)}, | 78 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)}, |
77 | /* gen2*/ | 79 | /* gen2*/ |
80 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0073SKINNY)}, | ||
81 | /* skinny*/ | ||
82 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0071SKINNY)}, | ||
83 | /* skinny*/ | ||
78 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, | 84 | {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, |
79 | /* xscale IOP, vega */ | 85 | /* xscale IOP, vega */ |
80 | {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, | 86 | {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, |
@@ -89,8 +95,14 @@ static struct megasas_mgmt_info megasas_mgmt_info; | |||
89 | static struct fasync_struct *megasas_async_queue; | 95 | static struct fasync_struct *megasas_async_queue; |
90 | static DEFINE_MUTEX(megasas_async_queue_mutex); | 96 | static DEFINE_MUTEX(megasas_async_queue_mutex); |
91 | 97 | ||
98 | static int megasas_poll_wait_aen; | ||
99 | static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait); | ||
100 | static u32 support_poll_for_event; | ||
92 | static u32 megasas_dbg_lvl; | 101 | static u32 megasas_dbg_lvl; |
93 | 102 | ||
103 | /* define lock for aen poll */ | ||
104 | spinlock_t poll_aen_lock; | ||
105 | |||
94 | static void | 106 | static void |
95 | megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | 107 | megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, |
96 | u8 alt_status); | 108 | u8 alt_status); |
@@ -215,7 +227,10 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) | |||
215 | * @regs : MFI register set | 227 | * @regs : MFI register set |
216 | */ | 228 | */ |
217 | static inline void | 229 | static inline void |
218 | megasas_fire_cmd_xscale(dma_addr_t frame_phys_addr,u32 frame_count, struct megasas_register_set __iomem *regs) | 230 | megasas_fire_cmd_xscale(struct megasas_instance *instance, |
231 | dma_addr_t frame_phys_addr, | ||
232 | u32 frame_count, | ||
233 | struct megasas_register_set __iomem *regs) | ||
219 | { | 234 | { |
220 | writel((frame_phys_addr >> 3)|(frame_count), | 235 | writel((frame_phys_addr >> 3)|(frame_count), |
221 | &(regs)->inbound_queue_port); | 236 | &(regs)->inbound_queue_port); |
@@ -312,7 +327,10 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) | |||
312 | * @regs : MFI register set | 327 | * @regs : MFI register set |
313 | */ | 328 | */ |
314 | static inline void | 329 | static inline void |
315 | megasas_fire_cmd_ppc(dma_addr_t frame_phys_addr, u32 frame_count, struct megasas_register_set __iomem *regs) | 330 | megasas_fire_cmd_ppc(struct megasas_instance *instance, |
331 | dma_addr_t frame_phys_addr, | ||
332 | u32 frame_count, | ||
333 | struct megasas_register_set __iomem *regs) | ||
316 | { | 334 | { |
317 | writel((frame_phys_addr | (frame_count<<1))|1, | 335 | writel((frame_phys_addr | (frame_count<<1))|1, |
318 | &(regs)->inbound_queue_port); | 336 | &(regs)->inbound_queue_port); |
@@ -328,6 +346,104 @@ static struct megasas_instance_template megasas_instance_template_ppc = { | |||
328 | }; | 346 | }; |
329 | 347 | ||
330 | /** | 348 | /** |
349 | * megasas_enable_intr_skinny - Enables interrupts | ||
350 | * @regs: MFI register set | ||
351 | */ | ||
352 | static inline void | ||
353 | megasas_enable_intr_skinny(struct megasas_register_set __iomem *regs) | ||
354 | { | ||
355 | writel(0xFFFFFFFF, &(regs)->outbound_intr_mask); | ||
356 | |||
357 | writel(~MFI_SKINNY_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); | ||
358 | |||
359 | /* Dummy readl to force pci flush */ | ||
360 | readl(®s->outbound_intr_mask); | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * megasas_disable_intr_skinny - Disables interrupt | ||
365 | * @regs: MFI register set | ||
366 | */ | ||
367 | static inline void | ||
368 | megasas_disable_intr_skinny(struct megasas_register_set __iomem *regs) | ||
369 | { | ||
370 | u32 mask = 0xFFFFFFFF; | ||
371 | writel(mask, ®s->outbound_intr_mask); | ||
372 | /* Dummy readl to force pci flush */ | ||
373 | readl(®s->outbound_intr_mask); | ||
374 | } | ||
375 | |||
376 | /** | ||
377 | * megasas_read_fw_status_reg_skinny - returns the current FW status value | ||
378 | * @regs: MFI register set | ||
379 | */ | ||
380 | static u32 | ||
381 | megasas_read_fw_status_reg_skinny(struct megasas_register_set __iomem *regs) | ||
382 | { | ||
383 | return readl(&(regs)->outbound_scratch_pad); | ||
384 | } | ||
385 | |||
386 | /** | ||
387 | * megasas_clear_interrupt_skinny - Check & clear interrupt | ||
388 | * @regs: MFI register set | ||
389 | */ | ||
390 | static int | ||
391 | megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs) | ||
392 | { | ||
393 | u32 status; | ||
394 | /* | ||
395 | * Check if it is our interrupt | ||
396 | */ | ||
397 | status = readl(®s->outbound_intr_status); | ||
398 | |||
399 | if (!(status & MFI_SKINNY_ENABLE_INTERRUPT_MASK)) { | ||
400 | return 1; | ||
401 | } | ||
402 | |||
403 | /* | ||
404 | * Clear the interrupt by writing back the same value | ||
405 | */ | ||
406 | writel(status, ®s->outbound_intr_status); | ||
407 | |||
408 | /* | ||
409 | * dummy read to flush PCI | ||
410 | */ | ||
411 | readl(®s->outbound_intr_status); | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | /** | ||
417 | * megasas_fire_cmd_skinny - Sends command to the FW | ||
418 | * @frame_phys_addr : Physical address of cmd | ||
419 | * @frame_count : Number of frames for the command | ||
420 | * @regs : MFI register set | ||
421 | */ | ||
422 | static inline void | ||
423 | megasas_fire_cmd_skinny(struct megasas_instance *instance, | ||
424 | dma_addr_t frame_phys_addr, | ||
425 | u32 frame_count, | ||
426 | struct megasas_register_set __iomem *regs) | ||
427 | { | ||
428 | unsigned long flags; | ||
429 | spin_lock_irqsave(&instance->fire_lock, flags); | ||
430 | writel(0, &(regs)->inbound_high_queue_port); | ||
431 | writel((frame_phys_addr | (frame_count<<1))|1, | ||
432 | &(regs)->inbound_low_queue_port); | ||
433 | spin_unlock_irqrestore(&instance->fire_lock, flags); | ||
434 | } | ||
435 | |||
436 | static struct megasas_instance_template megasas_instance_template_skinny = { | ||
437 | |||
438 | .fire_cmd = megasas_fire_cmd_skinny, | ||
439 | .enable_intr = megasas_enable_intr_skinny, | ||
440 | .disable_intr = megasas_disable_intr_skinny, | ||
441 | .clear_intr = megasas_clear_intr_skinny, | ||
442 | .read_fw_status_reg = megasas_read_fw_status_reg_skinny, | ||
443 | }; | ||
444 | |||
445 | |||
446 | /** | ||
331 | * The following functions are defined for gen2 (deviceid : 0x78 0x79) | 447 | * The following functions are defined for gen2 (deviceid : 0x78 0x79) |
332 | * controllers | 448 | * controllers |
333 | */ | 449 | */ |
@@ -404,7 +520,9 @@ megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs) | |||
404 | * @regs : MFI register set | 520 | * @regs : MFI register set |
405 | */ | 521 | */ |
406 | static inline void | 522 | static inline void |
407 | megasas_fire_cmd_gen2(dma_addr_t frame_phys_addr, u32 frame_count, | 523 | megasas_fire_cmd_gen2(struct megasas_instance *instance, |
524 | dma_addr_t frame_phys_addr, | ||
525 | u32 frame_count, | ||
408 | struct megasas_register_set __iomem *regs) | 526 | struct megasas_register_set __iomem *regs) |
409 | { | 527 | { |
410 | writel((frame_phys_addr | (frame_count<<1))|1, | 528 | writel((frame_phys_addr | (frame_count<<1))|1, |
@@ -446,7 +564,8 @@ megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) | |||
446 | /* | 564 | /* |
447 | * Issue the frame using inbound queue port | 565 | * Issue the frame using inbound queue port |
448 | */ | 566 | */ |
449 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); | 567 | instance->instancet->fire_cmd(instance, |
568 | cmd->frame_phys_addr, 0, instance->reg_set); | ||
450 | 569 | ||
451 | /* | 570 | /* |
452 | * Wait for cmd_status to change | 571 | * Wait for cmd_status to change |
@@ -477,7 +596,8 @@ megasas_issue_blocked_cmd(struct megasas_instance *instance, | |||
477 | { | 596 | { |
478 | cmd->cmd_status = ENODATA; | 597 | cmd->cmd_status = ENODATA; |
479 | 598 | ||
480 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); | 599 | instance->instancet->fire_cmd(instance, |
600 | cmd->frame_phys_addr, 0, instance->reg_set); | ||
481 | 601 | ||
482 | wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA), | 602 | wait_event_timeout(instance->int_cmd_wait_q, (cmd->cmd_status != ENODATA), |
483 | MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ); | 603 | MEGASAS_INTERNAL_CMD_WAIT_TIME*HZ); |
@@ -522,7 +642,8 @@ megasas_issue_blocked_abort_cmd(struct megasas_instance *instance, | |||
522 | cmd->sync_cmd = 1; | 642 | cmd->sync_cmd = 1; |
523 | cmd->cmd_status = 0xFF; | 643 | cmd->cmd_status = 0xFF; |
524 | 644 | ||
525 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); | 645 | instance->instancet->fire_cmd(instance, |
646 | cmd->frame_phys_addr, 0, instance->reg_set); | ||
526 | 647 | ||
527 | /* | 648 | /* |
528 | * Wait for this cmd to complete | 649 | * Wait for this cmd to complete |
@@ -592,6 +713,35 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
592 | return sge_count; | 713 | return sge_count; |
593 | } | 714 | } |
594 | 715 | ||
716 | /** | ||
717 | * megasas_make_sgl_skinny - Prepares IEEE SGL | ||
718 | * @instance: Adapter soft state | ||
719 | * @scp: SCSI command from the mid-layer | ||
720 | * @mfi_sgl: SGL to be filled in | ||
721 | * | ||
722 | * If successful, this function returns the number of SG elements. Otherwise, | ||
723 | * it returnes -1. | ||
724 | */ | ||
725 | static int | ||
726 | megasas_make_sgl_skinny(struct megasas_instance *instance, | ||
727 | struct scsi_cmnd *scp, union megasas_sgl *mfi_sgl) | ||
728 | { | ||
729 | int i; | ||
730 | int sge_count; | ||
731 | struct scatterlist *os_sgl; | ||
732 | |||
733 | sge_count = scsi_dma_map(scp); | ||
734 | |||
735 | if (sge_count) { | ||
736 | scsi_for_each_sg(scp, os_sgl, sge_count, i) { | ||
737 | mfi_sgl->sge_skinny[i].length = sg_dma_len(os_sgl); | ||
738 | mfi_sgl->sge_skinny[i].phys_addr = | ||
739 | sg_dma_address(os_sgl); | ||
740 | } | ||
741 | } | ||
742 | return sge_count; | ||
743 | } | ||
744 | |||
595 | /** | 745 | /** |
596 | * megasas_get_frame_count - Computes the number of frames | 746 | * megasas_get_frame_count - Computes the number of frames |
597 | * @frame_type : type of frame- io or pthru frame | 747 | * @frame_type : type of frame- io or pthru frame |
@@ -600,7 +750,8 @@ megasas_make_sgl64(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
600 | * Returns the number of frames required for numnber of sge's (sge_count) | 750 | * Returns the number of frames required for numnber of sge's (sge_count) |
601 | */ | 751 | */ |
602 | 752 | ||
603 | static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) | 753 | static u32 megasas_get_frame_count(struct megasas_instance *instance, |
754 | u8 sge_count, u8 frame_type) | ||
604 | { | 755 | { |
605 | int num_cnt; | 756 | int num_cnt; |
606 | int sge_bytes; | 757 | int sge_bytes; |
@@ -610,6 +761,10 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) | |||
610 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : | 761 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : |
611 | sizeof(struct megasas_sge32); | 762 | sizeof(struct megasas_sge32); |
612 | 763 | ||
764 | if (instance->flag_ieee) { | ||
765 | sge_sz = sizeof(struct megasas_sge_skinny); | ||
766 | } | ||
767 | |||
613 | /* | 768 | /* |
614 | * Main frame can contain 2 SGEs for 64-bit SGLs and | 769 | * Main frame can contain 2 SGEs for 64-bit SGLs and |
615 | * 3 SGEs for 32-bit SGLs for ldio & | 770 | * 3 SGEs for 32-bit SGLs for ldio & |
@@ -617,12 +772,16 @@ static u32 megasas_get_frame_count(u8 sge_count, u8 frame_type) | |||
617 | * 2 SGEs for 32-bit SGLs for pthru frame | 772 | * 2 SGEs for 32-bit SGLs for pthru frame |
618 | */ | 773 | */ |
619 | if (unlikely(frame_type == PTHRU_FRAME)) { | 774 | if (unlikely(frame_type == PTHRU_FRAME)) { |
620 | if (IS_DMA64) | 775 | if (instance->flag_ieee == 1) { |
776 | num_cnt = sge_count - 1; | ||
777 | } else if (IS_DMA64) | ||
621 | num_cnt = sge_count - 1; | 778 | num_cnt = sge_count - 1; |
622 | else | 779 | else |
623 | num_cnt = sge_count - 2; | 780 | num_cnt = sge_count - 2; |
624 | } else { | 781 | } else { |
625 | if (IS_DMA64) | 782 | if (instance->flag_ieee == 1) { |
783 | num_cnt = sge_count - 1; | ||
784 | } else if (IS_DMA64) | ||
626 | num_cnt = sge_count - 2; | 785 | num_cnt = sge_count - 2; |
627 | else | 786 | else |
628 | num_cnt = sge_count - 3; | 787 | num_cnt = sge_count - 3; |
@@ -671,6 +830,10 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
671 | else if (scp->sc_data_direction == PCI_DMA_NONE) | 830 | else if (scp->sc_data_direction == PCI_DMA_NONE) |
672 | flags = MFI_FRAME_DIR_NONE; | 831 | flags = MFI_FRAME_DIR_NONE; |
673 | 832 | ||
833 | if (instance->flag_ieee == 1) { | ||
834 | flags |= MFI_FRAME_IEEE; | ||
835 | } | ||
836 | |||
674 | /* | 837 | /* |
675 | * Prepare the DCDB frame | 838 | * Prepare the DCDB frame |
676 | */ | 839 | */ |
@@ -681,15 +844,31 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
681 | pthru->lun = scp->device->lun; | 844 | pthru->lun = scp->device->lun; |
682 | pthru->cdb_len = scp->cmd_len; | 845 | pthru->cdb_len = scp->cmd_len; |
683 | pthru->timeout = 0; | 846 | pthru->timeout = 0; |
847 | pthru->pad_0 = 0; | ||
684 | pthru->flags = flags; | 848 | pthru->flags = flags; |
685 | pthru->data_xfer_len = scsi_bufflen(scp); | 849 | pthru->data_xfer_len = scsi_bufflen(scp); |
686 | 850 | ||
687 | memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); | 851 | memcpy(pthru->cdb, scp->cmnd, scp->cmd_len); |
688 | 852 | ||
689 | /* | 853 | /* |
854 | * If the command is for the tape device, set the | ||
855 | * pthru timeout to the os layer timeout value. | ||
856 | */ | ||
857 | if (scp->device->type == TYPE_TAPE) { | ||
858 | if ((scp->request->timeout / HZ) > 0xFFFF) | ||
859 | pthru->timeout = 0xFFFF; | ||
860 | else | ||
861 | pthru->timeout = scp->request->timeout / HZ; | ||
862 | } | ||
863 | |||
864 | /* | ||
690 | * Construct SGL | 865 | * Construct SGL |
691 | */ | 866 | */ |
692 | if (IS_DMA64) { | 867 | if (instance->flag_ieee == 1) { |
868 | pthru->flags |= MFI_FRAME_SGL64; | ||
869 | pthru->sge_count = megasas_make_sgl_skinny(instance, scp, | ||
870 | &pthru->sgl); | ||
871 | } else if (IS_DMA64) { | ||
693 | pthru->flags |= MFI_FRAME_SGL64; | 872 | pthru->flags |= MFI_FRAME_SGL64; |
694 | pthru->sge_count = megasas_make_sgl64(instance, scp, | 873 | pthru->sge_count = megasas_make_sgl64(instance, scp, |
695 | &pthru->sgl); | 874 | &pthru->sgl); |
@@ -697,6 +876,12 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
697 | pthru->sge_count = megasas_make_sgl32(instance, scp, | 876 | pthru->sge_count = megasas_make_sgl32(instance, scp, |
698 | &pthru->sgl); | 877 | &pthru->sgl); |
699 | 878 | ||
879 | if (pthru->sge_count > instance->max_num_sge) { | ||
880 | printk(KERN_ERR "megasas: DCDB two many SGE NUM=%x\n", | ||
881 | pthru->sge_count); | ||
882 | return 0; | ||
883 | } | ||
884 | |||
700 | /* | 885 | /* |
701 | * Sense info specific | 886 | * Sense info specific |
702 | */ | 887 | */ |
@@ -708,7 +893,7 @@ megasas_build_dcdb(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
708 | * Compute the total number of frames this command consumes. FW uses | 893 | * Compute the total number of frames this command consumes. FW uses |
709 | * this number to pull sufficient number of frames from host memory. | 894 | * this number to pull sufficient number of frames from host memory. |
710 | */ | 895 | */ |
711 | cmd->frame_count = megasas_get_frame_count(pthru->sge_count, | 896 | cmd->frame_count = megasas_get_frame_count(instance, pthru->sge_count, |
712 | PTHRU_FRAME); | 897 | PTHRU_FRAME); |
713 | 898 | ||
714 | return cmd->frame_count; | 899 | return cmd->frame_count; |
@@ -739,6 +924,10 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
739 | else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) | 924 | else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) |
740 | flags = MFI_FRAME_DIR_READ; | 925 | flags = MFI_FRAME_DIR_READ; |
741 | 926 | ||
927 | if (instance->flag_ieee == 1) { | ||
928 | flags |= MFI_FRAME_IEEE; | ||
929 | } | ||
930 | |||
742 | /* | 931 | /* |
743 | * Prepare the Logical IO frame: 2nd bit is zero for all read cmds | 932 | * Prepare the Logical IO frame: 2nd bit is zero for all read cmds |
744 | */ | 933 | */ |
@@ -809,12 +998,22 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
809 | /* | 998 | /* |
810 | * Construct SGL | 999 | * Construct SGL |
811 | */ | 1000 | */ |
812 | if (IS_DMA64) { | 1001 | if (instance->flag_ieee) { |
1002 | ldio->flags |= MFI_FRAME_SGL64; | ||
1003 | ldio->sge_count = megasas_make_sgl_skinny(instance, scp, | ||
1004 | &ldio->sgl); | ||
1005 | } else if (IS_DMA64) { | ||
813 | ldio->flags |= MFI_FRAME_SGL64; | 1006 | ldio->flags |= MFI_FRAME_SGL64; |
814 | ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); | 1007 | ldio->sge_count = megasas_make_sgl64(instance, scp, &ldio->sgl); |
815 | } else | 1008 | } else |
816 | ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl); | 1009 | ldio->sge_count = megasas_make_sgl32(instance, scp, &ldio->sgl); |
817 | 1010 | ||
1011 | if (ldio->sge_count > instance->max_num_sge) { | ||
1012 | printk(KERN_ERR "megasas: build_ld_io: sge_count = %x\n", | ||
1013 | ldio->sge_count); | ||
1014 | return 0; | ||
1015 | } | ||
1016 | |||
818 | /* | 1017 | /* |
819 | * Sense info specific | 1018 | * Sense info specific |
820 | */ | 1019 | */ |
@@ -826,7 +1025,8 @@ megasas_build_ldio(struct megasas_instance *instance, struct scsi_cmnd *scp, | |||
826 | * Compute the total number of frames this command consumes. FW uses | 1025 | * Compute the total number of frames this command consumes. FW uses |
827 | * this number to pull sufficient number of frames from host memory. | 1026 | * this number to pull sufficient number of frames from host memory. |
828 | */ | 1027 | */ |
829 | cmd->frame_count = megasas_get_frame_count(ldio->sge_count, IO_FRAME); | 1028 | cmd->frame_count = megasas_get_frame_count(instance, |
1029 | ldio->sge_count, IO_FRAME); | ||
830 | 1030 | ||
831 | return cmd->frame_count; | 1031 | return cmd->frame_count; |
832 | } | 1032 | } |
@@ -983,7 +1183,8 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) | |||
983 | */ | 1183 | */ |
984 | atomic_inc(&instance->fw_outstanding); | 1184 | atomic_inc(&instance->fw_outstanding); |
985 | 1185 | ||
986 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,cmd->frame_count-1,instance->reg_set); | 1186 | instance->instancet->fire_cmd(instance, cmd->frame_phys_addr, |
1187 | cmd->frame_count-1, instance->reg_set); | ||
987 | /* | 1188 | /* |
988 | * Check if we have pend cmds to be completed | 1189 | * Check if we have pend cmds to be completed |
989 | */ | 1190 | */ |
@@ -1000,24 +1201,76 @@ megasas_queue_command(struct scsi_cmnd *scmd, void (*done) (struct scsi_cmnd *)) | |||
1000 | return 0; | 1201 | return 0; |
1001 | } | 1202 | } |
1002 | 1203 | ||
1204 | static struct megasas_instance *megasas_lookup_instance(u16 host_no) | ||
1205 | { | ||
1206 | int i; | ||
1207 | |||
1208 | for (i = 0; i < megasas_mgmt_info.max_index; i++) { | ||
1209 | |||
1210 | if ((megasas_mgmt_info.instance[i]) && | ||
1211 | (megasas_mgmt_info.instance[i]->host->host_no == host_no)) | ||
1212 | return megasas_mgmt_info.instance[i]; | ||
1213 | } | ||
1214 | |||
1215 | return NULL; | ||
1216 | } | ||
1217 | |||
1003 | static int megasas_slave_configure(struct scsi_device *sdev) | 1218 | static int megasas_slave_configure(struct scsi_device *sdev) |
1004 | { | 1219 | { |
1220 | u16 pd_index = 0; | ||
1221 | struct megasas_instance *instance ; | ||
1222 | |||
1223 | instance = megasas_lookup_instance(sdev->host->host_no); | ||
1224 | |||
1005 | /* | 1225 | /* |
1006 | * Don't export physical disk devices to the disk driver. | 1226 | * Don't export physical disk devices to the disk driver. |
1007 | * | 1227 | * |
1008 | * FIXME: Currently we don't export them to the midlayer at all. | 1228 | * FIXME: Currently we don't export them to the midlayer at all. |
1009 | * That will be fixed once LSI engineers have audited the | 1229 | * That will be fixed once LSI engineers have audited the |
1010 | * firmware for possible issues. | 1230 | * firmware for possible issues. |
1011 | */ | 1231 | */ |
1012 | if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && sdev->type == TYPE_DISK) | 1232 | if (sdev->channel < MEGASAS_MAX_PD_CHANNELS && |
1233 | sdev->type == TYPE_DISK) { | ||
1234 | pd_index = (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + | ||
1235 | sdev->id; | ||
1236 | if (instance->pd_list[pd_index].driveState == | ||
1237 | MR_PD_STATE_SYSTEM) { | ||
1238 | blk_queue_rq_timeout(sdev->request_queue, | ||
1239 | MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); | ||
1240 | return 0; | ||
1241 | } | ||
1013 | return -ENXIO; | 1242 | return -ENXIO; |
1243 | } | ||
1014 | 1244 | ||
1015 | /* | 1245 | /* |
1016 | * The RAID firmware may require extended timeouts. | 1246 | * The RAID firmware may require extended timeouts. |
1017 | */ | 1247 | */ |
1018 | if (sdev->channel >= MEGASAS_MAX_PD_CHANNELS) | 1248 | blk_queue_rq_timeout(sdev->request_queue, |
1019 | blk_queue_rq_timeout(sdev->request_queue, | 1249 | MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); |
1020 | MEGASAS_DEFAULT_CMD_TIMEOUT * HZ); | 1250 | return 0; |
1251 | } | ||
1252 | |||
1253 | static int megasas_slave_alloc(struct scsi_device *sdev) | ||
1254 | { | ||
1255 | u16 pd_index = 0; | ||
1256 | struct megasas_instance *instance ; | ||
1257 | instance = megasas_lookup_instance(sdev->host->host_no); | ||
1258 | if ((sdev->channel < MEGASAS_MAX_PD_CHANNELS) && | ||
1259 | (sdev->type == TYPE_DISK)) { | ||
1260 | /* | ||
1261 | * Open the OS scan to the SYSTEM PD | ||
1262 | */ | ||
1263 | pd_index = | ||
1264 | (sdev->channel * MEGASAS_MAX_DEV_PER_CHANNEL) + | ||
1265 | sdev->id; | ||
1266 | if ((instance->pd_list[pd_index].driveState == | ||
1267 | MR_PD_STATE_SYSTEM) && | ||
1268 | (instance->pd_list[pd_index].driveType == | ||
1269 | TYPE_DISK)) { | ||
1270 | return 0; | ||
1271 | } | ||
1272 | return -ENXIO; | ||
1273 | } | ||
1021 | return 0; | 1274 | return 0; |
1022 | } | 1275 | } |
1023 | 1276 | ||
@@ -1072,7 +1325,14 @@ static void megasas_complete_cmd_dpc(unsigned long instance_addr) | |||
1072 | 1325 | ||
1073 | spin_lock_irqsave(instance->host->host_lock, flags); | 1326 | spin_lock_irqsave(instance->host->host_lock, flags); |
1074 | instance->flag &= ~MEGASAS_FW_BUSY; | 1327 | instance->flag &= ~MEGASAS_FW_BUSY; |
1075 | instance->host->can_queue = | 1328 | if ((instance->pdev->device == |
1329 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | ||
1330 | (instance->pdev->device == | ||
1331 | PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
1332 | instance->host->can_queue = | ||
1333 | instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; | ||
1334 | } else | ||
1335 | instance->host->can_queue = | ||
1076 | instance->max_fw_cmds - MEGASAS_INT_CMDS; | 1336 | instance->max_fw_cmds - MEGASAS_INT_CMDS; |
1077 | 1337 | ||
1078 | spin_unlock_irqrestore(instance->host->host_lock, flags); | 1338 | spin_unlock_irqrestore(instance->host->host_lock, flags); |
@@ -1117,8 +1377,16 @@ static int megasas_wait_for_outstanding(struct megasas_instance *instance) | |||
1117 | * Send signal to FW to stop processing any pending cmds. | 1377 | * Send signal to FW to stop processing any pending cmds. |
1118 | * The controller will be taken offline by the OS now. | 1378 | * The controller will be taken offline by the OS now. |
1119 | */ | 1379 | */ |
1120 | writel(MFI_STOP_ADP, | 1380 | if ((instance->pdev->device == |
1381 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | ||
1382 | (instance->pdev->device == | ||
1383 | PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
1384 | writel(MFI_STOP_ADP, | ||
1385 | &instance->reg_set->reserved_0[0]); | ||
1386 | } else { | ||
1387 | writel(MFI_STOP_ADP, | ||
1121 | &instance->reg_set->inbound_doorbell); | 1388 | &instance->reg_set->inbound_doorbell); |
1389 | } | ||
1122 | megasas_dump_pending_frames(instance); | 1390 | megasas_dump_pending_frames(instance); |
1123 | instance->hw_crit_error = 1; | 1391 | instance->hw_crit_error = 1; |
1124 | return FAILED; | 1392 | return FAILED; |
@@ -1266,6 +1534,8 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev, | |||
1266 | return 0; | 1534 | return 0; |
1267 | } | 1535 | } |
1268 | 1536 | ||
1537 | static void megasas_aen_polling(struct work_struct *work); | ||
1538 | |||
1269 | /** | 1539 | /** |
1270 | * megasas_service_aen - Processes an event notification | 1540 | * megasas_service_aen - Processes an event notification |
1271 | * @instance: Adapter soft state | 1541 | * @instance: Adapter soft state |
@@ -1281,16 +1551,36 @@ megasas_bios_param(struct scsi_device *sdev, struct block_device *bdev, | |||
1281 | static void | 1551 | static void |
1282 | megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) | 1552 | megasas_service_aen(struct megasas_instance *instance, struct megasas_cmd *cmd) |
1283 | { | 1553 | { |
1554 | unsigned long flags; | ||
1284 | /* | 1555 | /* |
1285 | * Don't signal app if it is just an aborted previously registered aen | 1556 | * Don't signal app if it is just an aborted previously registered aen |
1286 | */ | 1557 | */ |
1287 | if (!cmd->abort_aen) | 1558 | if ((!cmd->abort_aen) && (instance->unload == 0)) { |
1559 | spin_lock_irqsave(&poll_aen_lock, flags); | ||
1560 | megasas_poll_wait_aen = 1; | ||
1561 | spin_unlock_irqrestore(&poll_aen_lock, flags); | ||
1562 | wake_up(&megasas_poll_wait); | ||
1288 | kill_fasync(&megasas_async_queue, SIGIO, POLL_IN); | 1563 | kill_fasync(&megasas_async_queue, SIGIO, POLL_IN); |
1564 | } | ||
1289 | else | 1565 | else |
1290 | cmd->abort_aen = 0; | 1566 | cmd->abort_aen = 0; |
1291 | 1567 | ||
1292 | instance->aen_cmd = NULL; | 1568 | instance->aen_cmd = NULL; |
1293 | megasas_return_cmd(instance, cmd); | 1569 | megasas_return_cmd(instance, cmd); |
1570 | |||
1571 | if (instance->unload == 0) { | ||
1572 | struct megasas_aen_event *ev; | ||
1573 | ev = kzalloc(sizeof(*ev), GFP_ATOMIC); | ||
1574 | if (!ev) { | ||
1575 | printk(KERN_ERR "megasas_service_aen: out of memory\n"); | ||
1576 | } else { | ||
1577 | ev->instance = instance; | ||
1578 | instance->ev = ev; | ||
1579 | INIT_WORK(&ev->hotplug_work, megasas_aen_polling); | ||
1580 | schedule_delayed_work( | ||
1581 | (struct delayed_work *)&ev->hotplug_work, 0); | ||
1582 | } | ||
1583 | } | ||
1294 | } | 1584 | } |
1295 | 1585 | ||
1296 | /* | 1586 | /* |
@@ -1302,6 +1592,7 @@ static struct scsi_host_template megasas_template = { | |||
1302 | .name = "LSI SAS based MegaRAID driver", | 1592 | .name = "LSI SAS based MegaRAID driver", |
1303 | .proc_name = "megaraid_sas", | 1593 | .proc_name = "megaraid_sas", |
1304 | .slave_configure = megasas_slave_configure, | 1594 | .slave_configure = megasas_slave_configure, |
1595 | .slave_alloc = megasas_slave_alloc, | ||
1305 | .queuecommand = megasas_queue_command, | 1596 | .queuecommand = megasas_queue_command, |
1306 | .eh_device_reset_handler = megasas_reset_device, | 1597 | .eh_device_reset_handler = megasas_reset_device, |
1307 | .eh_bus_reset_handler = megasas_reset_bus_host, | 1598 | .eh_bus_reset_handler = megasas_reset_bus_host, |
@@ -1370,6 +1661,7 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | |||
1370 | { | 1661 | { |
1371 | int exception = 0; | 1662 | int exception = 0; |
1372 | struct megasas_header *hdr = &cmd->frame->hdr; | 1663 | struct megasas_header *hdr = &cmd->frame->hdr; |
1664 | unsigned long flags; | ||
1373 | 1665 | ||
1374 | if (cmd->scmd) | 1666 | if (cmd->scmd) |
1375 | cmd->scmd->SCp.ptr = NULL; | 1667 | cmd->scmd->SCp.ptr = NULL; |
@@ -1459,6 +1751,12 @@ megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, | |||
1459 | case MFI_CMD_SMP: | 1751 | case MFI_CMD_SMP: |
1460 | case MFI_CMD_STP: | 1752 | case MFI_CMD_STP: |
1461 | case MFI_CMD_DCMD: | 1753 | case MFI_CMD_DCMD: |
1754 | if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO || | ||
1755 | cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) { | ||
1756 | spin_lock_irqsave(&poll_aen_lock, flags); | ||
1757 | megasas_poll_wait_aen = 0; | ||
1758 | spin_unlock_irqrestore(&poll_aen_lock, flags); | ||
1759 | } | ||
1462 | 1760 | ||
1463 | /* | 1761 | /* |
1464 | * See if got an event notification | 1762 | * See if got an event notification |
@@ -1536,6 +1834,7 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1536 | u8 max_wait; | 1834 | u8 max_wait; |
1537 | u32 fw_state; | 1835 | u32 fw_state; |
1538 | u32 cur_state; | 1836 | u32 cur_state; |
1837 | u32 abs_state, curr_abs_state; | ||
1539 | 1838 | ||
1540 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; | 1839 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & MFI_STATE_MASK; |
1541 | 1840 | ||
@@ -1545,6 +1844,9 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1545 | 1844 | ||
1546 | while (fw_state != MFI_STATE_READY) { | 1845 | while (fw_state != MFI_STATE_READY) { |
1547 | 1846 | ||
1847 | abs_state = | ||
1848 | instance->instancet->read_fw_status_reg(instance->reg_set); | ||
1849 | |||
1548 | switch (fw_state) { | 1850 | switch (fw_state) { |
1549 | 1851 | ||
1550 | case MFI_STATE_FAULT: | 1852 | case MFI_STATE_FAULT: |
@@ -1556,18 +1858,36 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1556 | /* | 1858 | /* |
1557 | * Set the CLR bit in inbound doorbell | 1859 | * Set the CLR bit in inbound doorbell |
1558 | */ | 1860 | */ |
1559 | writel(MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, | 1861 | if ((instance->pdev->device == |
1560 | &instance->reg_set->inbound_doorbell); | 1862 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
1863 | (instance->pdev->device == | ||
1864 | PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
1865 | |||
1866 | writel( | ||
1867 | MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, | ||
1868 | &instance->reg_set->reserved_0[0]); | ||
1869 | } else { | ||
1870 | writel( | ||
1871 | MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, | ||
1872 | &instance->reg_set->inbound_doorbell); | ||
1873 | } | ||
1561 | 1874 | ||
1562 | max_wait = 2; | 1875 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1563 | cur_state = MFI_STATE_WAIT_HANDSHAKE; | 1876 | cur_state = MFI_STATE_WAIT_HANDSHAKE; |
1564 | break; | 1877 | break; |
1565 | 1878 | ||
1566 | case MFI_STATE_BOOT_MESSAGE_PENDING: | 1879 | case MFI_STATE_BOOT_MESSAGE_PENDING: |
1567 | writel(MFI_INIT_HOTPLUG, | 1880 | if ((instance->pdev->device == |
1568 | &instance->reg_set->inbound_doorbell); | 1881 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
1882 | (instance->pdev->device == | ||
1883 | PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
1884 | writel(MFI_INIT_HOTPLUG, | ||
1885 | &instance->reg_set->reserved_0[0]); | ||
1886 | } else | ||
1887 | writel(MFI_INIT_HOTPLUG, | ||
1888 | &instance->reg_set->inbound_doorbell); | ||
1569 | 1889 | ||
1570 | max_wait = 10; | 1890 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1571 | cur_state = MFI_STATE_BOOT_MESSAGE_PENDING; | 1891 | cur_state = MFI_STATE_BOOT_MESSAGE_PENDING; |
1572 | break; | 1892 | break; |
1573 | 1893 | ||
@@ -1576,9 +1896,17 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1576 | * Bring it to READY state; assuming max wait 10 secs | 1896 | * Bring it to READY state; assuming max wait 10 secs |
1577 | */ | 1897 | */ |
1578 | instance->instancet->disable_intr(instance->reg_set); | 1898 | instance->instancet->disable_intr(instance->reg_set); |
1579 | writel(MFI_RESET_FLAGS, &instance->reg_set->inbound_doorbell); | 1899 | if ((instance->pdev->device == |
1900 | PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | ||
1901 | (instance->pdev->device == | ||
1902 | PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
1903 | writel(MFI_RESET_FLAGS, | ||
1904 | &instance->reg_set->reserved_0[0]); | ||
1905 | } else | ||
1906 | writel(MFI_RESET_FLAGS, | ||
1907 | &instance->reg_set->inbound_doorbell); | ||
1580 | 1908 | ||
1581 | max_wait = 60; | 1909 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1582 | cur_state = MFI_STATE_OPERATIONAL; | 1910 | cur_state = MFI_STATE_OPERATIONAL; |
1583 | break; | 1911 | break; |
1584 | 1912 | ||
@@ -1586,32 +1914,32 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1586 | /* | 1914 | /* |
1587 | * This state should not last for more than 2 seconds | 1915 | * This state should not last for more than 2 seconds |
1588 | */ | 1916 | */ |
1589 | max_wait = 2; | 1917 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1590 | cur_state = MFI_STATE_UNDEFINED; | 1918 | cur_state = MFI_STATE_UNDEFINED; |
1591 | break; | 1919 | break; |
1592 | 1920 | ||
1593 | case MFI_STATE_BB_INIT: | 1921 | case MFI_STATE_BB_INIT: |
1594 | max_wait = 2; | 1922 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1595 | cur_state = MFI_STATE_BB_INIT; | 1923 | cur_state = MFI_STATE_BB_INIT; |
1596 | break; | 1924 | break; |
1597 | 1925 | ||
1598 | case MFI_STATE_FW_INIT: | 1926 | case MFI_STATE_FW_INIT: |
1599 | max_wait = 20; | 1927 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1600 | cur_state = MFI_STATE_FW_INIT; | 1928 | cur_state = MFI_STATE_FW_INIT; |
1601 | break; | 1929 | break; |
1602 | 1930 | ||
1603 | case MFI_STATE_FW_INIT_2: | 1931 | case MFI_STATE_FW_INIT_2: |
1604 | max_wait = 20; | 1932 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1605 | cur_state = MFI_STATE_FW_INIT_2; | 1933 | cur_state = MFI_STATE_FW_INIT_2; |
1606 | break; | 1934 | break; |
1607 | 1935 | ||
1608 | case MFI_STATE_DEVICE_SCAN: | 1936 | case MFI_STATE_DEVICE_SCAN: |
1609 | max_wait = 20; | 1937 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1610 | cur_state = MFI_STATE_DEVICE_SCAN; | 1938 | cur_state = MFI_STATE_DEVICE_SCAN; |
1611 | break; | 1939 | break; |
1612 | 1940 | ||
1613 | case MFI_STATE_FLUSH_CACHE: | 1941 | case MFI_STATE_FLUSH_CACHE: |
1614 | max_wait = 20; | 1942 | max_wait = MEGASAS_RESET_WAIT_TIME; |
1615 | cur_state = MFI_STATE_FLUSH_CACHE; | 1943 | cur_state = MFI_STATE_FLUSH_CACHE; |
1616 | break; | 1944 | break; |
1617 | 1945 | ||
@@ -1627,8 +1955,10 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1627 | for (i = 0; i < (max_wait * 1000); i++) { | 1955 | for (i = 0; i < (max_wait * 1000); i++) { |
1628 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & | 1956 | fw_state = instance->instancet->read_fw_status_reg(instance->reg_set) & |
1629 | MFI_STATE_MASK ; | 1957 | MFI_STATE_MASK ; |
1958 | curr_abs_state = | ||
1959 | instance->instancet->read_fw_status_reg(instance->reg_set); | ||
1630 | 1960 | ||
1631 | if (fw_state == cur_state) { | 1961 | if (abs_state == curr_abs_state) { |
1632 | msleep(1); | 1962 | msleep(1); |
1633 | } else | 1963 | } else |
1634 | break; | 1964 | break; |
@@ -1637,7 +1967,7 @@ megasas_transition_to_ready(struct megasas_instance* instance) | |||
1637 | /* | 1967 | /* |
1638 | * Return error if fw_state hasn't changed after max_wait | 1968 | * Return error if fw_state hasn't changed after max_wait |
1639 | */ | 1969 | */ |
1640 | if (fw_state == cur_state) { | 1970 | if (curr_abs_state == abs_state) { |
1641 | printk(KERN_DEBUG "FW state [%d] hasn't changed " | 1971 | printk(KERN_DEBUG "FW state [%d] hasn't changed " |
1642 | "in %d secs\n", fw_state, max_wait); | 1972 | "in %d secs\n", fw_state, max_wait); |
1643 | return -ENODEV; | 1973 | return -ENODEV; |
@@ -1715,6 +2045,10 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) | |||
1715 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : | 2045 | sge_sz = (IS_DMA64) ? sizeof(struct megasas_sge64) : |
1716 | sizeof(struct megasas_sge32); | 2046 | sizeof(struct megasas_sge32); |
1717 | 2047 | ||
2048 | if (instance->flag_ieee) { | ||
2049 | sge_sz = sizeof(struct megasas_sge_skinny); | ||
2050 | } | ||
2051 | |||
1718 | /* | 2052 | /* |
1719 | * Calculated the number of 64byte frames required for SGL | 2053 | * Calculated the number of 64byte frames required for SGL |
1720 | */ | 2054 | */ |
@@ -1777,6 +2111,7 @@ static int megasas_create_frame_pool(struct megasas_instance *instance) | |||
1777 | } | 2111 | } |
1778 | 2112 | ||
1779 | cmd->frame->io.context = cmd->index; | 2113 | cmd->frame->io.context = cmd->index; |
2114 | cmd->frame->io.pad_0 = 0; | ||
1780 | } | 2115 | } |
1781 | 2116 | ||
1782 | return 0; | 2117 | return 0; |
@@ -1882,6 +2217,178 @@ static int megasas_alloc_cmds(struct megasas_instance *instance) | |||
1882 | return 0; | 2217 | return 0; |
1883 | } | 2218 | } |
1884 | 2219 | ||
2220 | /* | ||
2221 | * megasas_get_pd_list_info - Returns FW's pd_list structure | ||
2222 | * @instance: Adapter soft state | ||
2223 | * @pd_list: pd_list structure | ||
2224 | * | ||
2225 | * Issues an internal command (DCMD) to get the FW's controller PD | ||
2226 | * list structure. This information is mainly used to find out SYSTEM | ||
2227 | * supported by the FW. | ||
2228 | */ | ||
2229 | static int | ||
2230 | megasas_get_pd_list(struct megasas_instance *instance) | ||
2231 | { | ||
2232 | int ret = 0, pd_index = 0; | ||
2233 | struct megasas_cmd *cmd; | ||
2234 | struct megasas_dcmd_frame *dcmd; | ||
2235 | struct MR_PD_LIST *ci; | ||
2236 | struct MR_PD_ADDRESS *pd_addr; | ||
2237 | dma_addr_t ci_h = 0; | ||
2238 | |||
2239 | cmd = megasas_get_cmd(instance); | ||
2240 | |||
2241 | if (!cmd) { | ||
2242 | printk(KERN_DEBUG "megasas (get_pd_list): Failed to get cmd\n"); | ||
2243 | return -ENOMEM; | ||
2244 | } | ||
2245 | |||
2246 | dcmd = &cmd->frame->dcmd; | ||
2247 | |||
2248 | ci = pci_alloc_consistent(instance->pdev, | ||
2249 | MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), &ci_h); | ||
2250 | |||
2251 | if (!ci) { | ||
2252 | printk(KERN_DEBUG "Failed to alloc mem for pd_list\n"); | ||
2253 | megasas_return_cmd(instance, cmd); | ||
2254 | return -ENOMEM; | ||
2255 | } | ||
2256 | |||
2257 | memset(ci, 0, sizeof(*ci)); | ||
2258 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | ||
2259 | |||
2260 | dcmd->mbox.b[0] = MR_PD_QUERY_TYPE_EXPOSED_TO_HOST; | ||
2261 | dcmd->mbox.b[1] = 0; | ||
2262 | dcmd->cmd = MFI_CMD_DCMD; | ||
2263 | dcmd->cmd_status = 0xFF; | ||
2264 | dcmd->sge_count = 1; | ||
2265 | dcmd->flags = MFI_FRAME_DIR_READ; | ||
2266 | dcmd->timeout = 0; | ||
2267 | dcmd->pad_0 = 0; | ||
2268 | dcmd->data_xfer_len = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); | ||
2269 | dcmd->opcode = MR_DCMD_PD_LIST_QUERY; | ||
2270 | dcmd->sgl.sge32[0].phys_addr = ci_h; | ||
2271 | dcmd->sgl.sge32[0].length = MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST); | ||
2272 | |||
2273 | if (!megasas_issue_polled(instance, cmd)) { | ||
2274 | ret = 0; | ||
2275 | } else { | ||
2276 | ret = -1; | ||
2277 | } | ||
2278 | |||
2279 | /* | ||
2280 | * the following function will get the instance PD LIST. | ||
2281 | */ | ||
2282 | |||
2283 | pd_addr = ci->addr; | ||
2284 | |||
2285 | if ( ret == 0 && | ||
2286 | (ci->count < | ||
2287 | (MEGASAS_MAX_PD_CHANNELS * MEGASAS_MAX_DEV_PER_CHANNEL))) { | ||
2288 | |||
2289 | memset(instance->pd_list, 0, | ||
2290 | MEGASAS_MAX_PD * sizeof(struct megasas_pd_list)); | ||
2291 | |||
2292 | for (pd_index = 0; pd_index < ci->count; pd_index++) { | ||
2293 | |||
2294 | instance->pd_list[pd_addr->deviceId].tid = | ||
2295 | pd_addr->deviceId; | ||
2296 | instance->pd_list[pd_addr->deviceId].driveType = | ||
2297 | pd_addr->scsiDevType; | ||
2298 | instance->pd_list[pd_addr->deviceId].driveState = | ||
2299 | MR_PD_STATE_SYSTEM; | ||
2300 | pd_addr++; | ||
2301 | } | ||
2302 | } | ||
2303 | |||
2304 | pci_free_consistent(instance->pdev, | ||
2305 | MEGASAS_MAX_PD * sizeof(struct MR_PD_LIST), | ||
2306 | ci, ci_h); | ||
2307 | megasas_return_cmd(instance, cmd); | ||
2308 | |||
2309 | return ret; | ||
2310 | } | ||
2311 | |||
2312 | /* | ||
2313 | * megasas_get_ld_list_info - Returns FW's ld_list structure | ||
2314 | * @instance: Adapter soft state | ||
2315 | * @ld_list: ld_list structure | ||
2316 | * | ||
2317 | * Issues an internal command (DCMD) to get the FW's controller PD | ||
2318 | * list structure. This information is mainly used to find out SYSTEM | ||
2319 | * supported by the FW. | ||
2320 | */ | ||
2321 | static int | ||
2322 | megasas_get_ld_list(struct megasas_instance *instance) | ||
2323 | { | ||
2324 | int ret = 0, ld_index = 0, ids = 0; | ||
2325 | struct megasas_cmd *cmd; | ||
2326 | struct megasas_dcmd_frame *dcmd; | ||
2327 | struct MR_LD_LIST *ci; | ||
2328 | dma_addr_t ci_h = 0; | ||
2329 | |||
2330 | cmd = megasas_get_cmd(instance); | ||
2331 | |||
2332 | if (!cmd) { | ||
2333 | printk(KERN_DEBUG "megasas_get_ld_list: Failed to get cmd\n"); | ||
2334 | return -ENOMEM; | ||
2335 | } | ||
2336 | |||
2337 | dcmd = &cmd->frame->dcmd; | ||
2338 | |||
2339 | ci = pci_alloc_consistent(instance->pdev, | ||
2340 | sizeof(struct MR_LD_LIST), | ||
2341 | &ci_h); | ||
2342 | |||
2343 | if (!ci) { | ||
2344 | printk(KERN_DEBUG "Failed to alloc mem in get_ld_list\n"); | ||
2345 | megasas_return_cmd(instance, cmd); | ||
2346 | return -ENOMEM; | ||
2347 | } | ||
2348 | |||
2349 | memset(ci, 0, sizeof(*ci)); | ||
2350 | memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); | ||
2351 | |||
2352 | dcmd->cmd = MFI_CMD_DCMD; | ||
2353 | dcmd->cmd_status = 0xFF; | ||
2354 | dcmd->sge_count = 1; | ||
2355 | dcmd->flags = MFI_FRAME_DIR_READ; | ||
2356 | dcmd->timeout = 0; | ||
2357 | dcmd->data_xfer_len = sizeof(struct MR_LD_LIST); | ||
2358 | dcmd->opcode = MR_DCMD_LD_GET_LIST; | ||
2359 | dcmd->sgl.sge32[0].phys_addr = ci_h; | ||
2360 | dcmd->sgl.sge32[0].length = sizeof(struct MR_LD_LIST); | ||
2361 | dcmd->pad_0 = 0; | ||
2362 | |||
2363 | if (!megasas_issue_polled(instance, cmd)) { | ||
2364 | ret = 0; | ||
2365 | } else { | ||
2366 | ret = -1; | ||
2367 | } | ||
2368 | |||
2369 | /* the following function will get the instance PD LIST */ | ||
2370 | |||
2371 | if ((ret == 0) && (ci->ldCount < MAX_LOGICAL_DRIVES)) { | ||
2372 | memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); | ||
2373 | |||
2374 | for (ld_index = 0; ld_index < ci->ldCount; ld_index++) { | ||
2375 | if (ci->ldList[ld_index].state != 0) { | ||
2376 | ids = ci->ldList[ld_index].ref.targetId; | ||
2377 | instance->ld_ids[ids] = | ||
2378 | ci->ldList[ld_index].ref.targetId; | ||
2379 | } | ||
2380 | } | ||
2381 | } | ||
2382 | |||
2383 | pci_free_consistent(instance->pdev, | ||
2384 | sizeof(struct MR_LD_LIST), | ||
2385 | ci, | ||
2386 | ci_h); | ||
2387 | |||
2388 | megasas_return_cmd(instance, cmd); | ||
2389 | return ret; | ||
2390 | } | ||
2391 | |||
1885 | /** | 2392 | /** |
1886 | * megasas_get_controller_info - Returns FW's controller structure | 2393 | * megasas_get_controller_info - Returns FW's controller structure |
1887 | * @instance: Adapter soft state | 2394 | * @instance: Adapter soft state |
@@ -1927,6 +2434,7 @@ megasas_get_ctrl_info(struct megasas_instance *instance, | |||
1927 | dcmd->sge_count = 1; | 2434 | dcmd->sge_count = 1; |
1928 | dcmd->flags = MFI_FRAME_DIR_READ; | 2435 | dcmd->flags = MFI_FRAME_DIR_READ; |
1929 | dcmd->timeout = 0; | 2436 | dcmd->timeout = 0; |
2437 | dcmd->pad_0 = 0; | ||
1930 | dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info); | 2438 | dcmd->data_xfer_len = sizeof(struct megasas_ctrl_info); |
1931 | dcmd->opcode = MR_DCMD_CTRL_GET_INFO; | 2439 | dcmd->opcode = MR_DCMD_CTRL_GET_INFO; |
1932 | dcmd->sgl.sge32[0].phys_addr = ci_h; | 2440 | dcmd->sgl.sge32[0].phys_addr = ci_h; |
@@ -2081,13 +2589,17 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
2081 | * Map the message registers | 2589 | * Map the message registers |
2082 | */ | 2590 | */ |
2083 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) || | 2591 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) || |
2592 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || | ||
2593 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | ||
2084 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) { | 2594 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) { |
2085 | instance->base_addr = pci_resource_start(instance->pdev, 1); | 2595 | instance->base_addr = pci_resource_start(instance->pdev, 1); |
2086 | } else { | 2596 | } else { |
2087 | instance->base_addr = pci_resource_start(instance->pdev, 0); | 2597 | instance->base_addr = pci_resource_start(instance->pdev, 0); |
2088 | } | 2598 | } |
2089 | 2599 | ||
2090 | if (pci_request_regions(instance->pdev, "megasas: LSI")) { | 2600 | if (pci_request_selected_regions(instance->pdev, |
2601 | pci_select_bars(instance->pdev, IORESOURCE_MEM), | ||
2602 | "megasas: LSI")) { | ||
2091 | printk(KERN_DEBUG "megasas: IO memory region busy!\n"); | 2603 | printk(KERN_DEBUG "megasas: IO memory region busy!\n"); |
2092 | return -EBUSY; | 2604 | return -EBUSY; |
2093 | } | 2605 | } |
@@ -2111,6 +2623,10 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
2111 | case PCI_DEVICE_ID_LSI_SAS0079GEN2: | 2623 | case PCI_DEVICE_ID_LSI_SAS0079GEN2: |
2112 | instance->instancet = &megasas_instance_template_gen2; | 2624 | instance->instancet = &megasas_instance_template_gen2; |
2113 | break; | 2625 | break; |
2626 | case PCI_DEVICE_ID_LSI_SAS0073SKINNY: | ||
2627 | case PCI_DEVICE_ID_LSI_SAS0071SKINNY: | ||
2628 | instance->instancet = &megasas_instance_template_skinny; | ||
2629 | break; | ||
2114 | case PCI_DEVICE_ID_LSI_SAS1064R: | 2630 | case PCI_DEVICE_ID_LSI_SAS1064R: |
2115 | case PCI_DEVICE_ID_DELL_PERC5: | 2631 | case PCI_DEVICE_ID_DELL_PERC5: |
2116 | default: | 2632 | default: |
@@ -2166,6 +2682,13 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
2166 | if (megasas_issue_init_mfi(instance)) | 2682 | if (megasas_issue_init_mfi(instance)) |
2167 | goto fail_fw_init; | 2683 | goto fail_fw_init; |
2168 | 2684 | ||
2685 | memset(instance->pd_list, 0 , | ||
2686 | (MEGASAS_MAX_PD * sizeof(struct megasas_pd_list))); | ||
2687 | megasas_get_pd_list(instance); | ||
2688 | |||
2689 | memset(instance->ld_ids, 0xff, MEGASAS_MAX_LD_IDS); | ||
2690 | megasas_get_ld_list(instance); | ||
2691 | |||
2169 | ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); | 2692 | ctrl_info = kmalloc(sizeof(struct megasas_ctrl_info), GFP_KERNEL); |
2170 | 2693 | ||
2171 | /* | 2694 | /* |
@@ -2220,7 +2743,8 @@ static int megasas_init_mfi(struct megasas_instance *instance) | |||
2220 | iounmap(instance->reg_set); | 2743 | iounmap(instance->reg_set); |
2221 | 2744 | ||
2222 | fail_ioremap: | 2745 | fail_ioremap: |
2223 | pci_release_regions(instance->pdev); | 2746 | pci_release_selected_regions(instance->pdev, |
2747 | pci_select_bars(instance->pdev, IORESOURCE_MEM)); | ||
2224 | 2748 | ||
2225 | return -EINVAL; | 2749 | return -EINVAL; |
2226 | } | 2750 | } |
@@ -2240,7 +2764,8 @@ static void megasas_release_mfi(struct megasas_instance *instance) | |||
2240 | 2764 | ||
2241 | iounmap(instance->reg_set); | 2765 | iounmap(instance->reg_set); |
2242 | 2766 | ||
2243 | pci_release_regions(instance->pdev); | 2767 | pci_release_selected_regions(instance->pdev, |
2768 | pci_select_bars(instance->pdev, IORESOURCE_MEM)); | ||
2244 | } | 2769 | } |
2245 | 2770 | ||
2246 | /** | 2771 | /** |
@@ -2288,6 +2813,7 @@ megasas_get_seq_num(struct megasas_instance *instance, | |||
2288 | dcmd->sge_count = 1; | 2813 | dcmd->sge_count = 1; |
2289 | dcmd->flags = MFI_FRAME_DIR_READ; | 2814 | dcmd->flags = MFI_FRAME_DIR_READ; |
2290 | dcmd->timeout = 0; | 2815 | dcmd->timeout = 0; |
2816 | dcmd->pad_0 = 0; | ||
2291 | dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info); | 2817 | dcmd->data_xfer_len = sizeof(struct megasas_evt_log_info); |
2292 | dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO; | 2818 | dcmd->opcode = MR_DCMD_CTRL_EVENT_GET_INFO; |
2293 | dcmd->sgl.sge32[0].phys_addr = el_info_h; | 2819 | dcmd->sgl.sge32[0].phys_addr = el_info_h; |
@@ -2402,6 +2928,7 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, | |||
2402 | dcmd->sge_count = 1; | 2928 | dcmd->sge_count = 1; |
2403 | dcmd->flags = MFI_FRAME_DIR_READ; | 2929 | dcmd->flags = MFI_FRAME_DIR_READ; |
2404 | dcmd->timeout = 0; | 2930 | dcmd->timeout = 0; |
2931 | dcmd->pad_0 = 0; | ||
2405 | dcmd->data_xfer_len = sizeof(struct megasas_evt_detail); | 2932 | dcmd->data_xfer_len = sizeof(struct megasas_evt_detail); |
2406 | dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT; | 2933 | dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT; |
2407 | dcmd->mbox.w[0] = seq_num; | 2934 | dcmd->mbox.w[0] = seq_num; |
@@ -2409,6 +2936,11 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, | |||
2409 | dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; | 2936 | dcmd->sgl.sge32[0].phys_addr = (u32) instance->evt_detail_h; |
2410 | dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); | 2937 | dcmd->sgl.sge32[0].length = sizeof(struct megasas_evt_detail); |
2411 | 2938 | ||
2939 | if (instance->aen_cmd != NULL) { | ||
2940 | megasas_return_cmd(instance, cmd); | ||
2941 | return 0; | ||
2942 | } | ||
2943 | |||
2412 | /* | 2944 | /* |
2413 | * Store reference to the cmd used to register for AEN. When an | 2945 | * Store reference to the cmd used to register for AEN. When an |
2414 | * application wants us to register for AEN, we have to abort this | 2946 | * application wants us to register for AEN, we have to abort this |
@@ -2419,7 +2951,8 @@ megasas_register_aen(struct megasas_instance *instance, u32 seq_num, | |||
2419 | /* | 2951 | /* |
2420 | * Issue the aen registration frame | 2952 | * Issue the aen registration frame |
2421 | */ | 2953 | */ |
2422 | instance->instancet->fire_cmd(cmd->frame_phys_addr ,0,instance->reg_set); | 2954 | instance->instancet->fire_cmd(instance, |
2955 | cmd->frame_phys_addr, 0, instance->reg_set); | ||
2423 | 2956 | ||
2424 | return 0; | 2957 | return 0; |
2425 | } | 2958 | } |
@@ -2465,7 +2998,13 @@ static int megasas_io_attach(struct megasas_instance *instance) | |||
2465 | */ | 2998 | */ |
2466 | host->irq = instance->pdev->irq; | 2999 | host->irq = instance->pdev->irq; |
2467 | host->unique_id = instance->unique_id; | 3000 | host->unique_id = instance->unique_id; |
2468 | host->can_queue = instance->max_fw_cmds - MEGASAS_INT_CMDS; | 3001 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || |
3002 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
3003 | host->can_queue = | ||
3004 | instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; | ||
3005 | } else | ||
3006 | host->can_queue = | ||
3007 | instance->max_fw_cmds - MEGASAS_INT_CMDS; | ||
2469 | host->this_id = instance->init_id; | 3008 | host->this_id = instance->init_id; |
2470 | host->sg_tablesize = instance->max_num_sge; | 3009 | host->sg_tablesize = instance->max_num_sge; |
2471 | host->max_sectors = instance->max_sectors_per_req; | 3010 | host->max_sectors = instance->max_sectors_per_req; |
@@ -2537,7 +3076,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2537 | /* | 3076 | /* |
2538 | * PCI prepping: enable device set bus mastering and dma mask | 3077 | * PCI prepping: enable device set bus mastering and dma mask |
2539 | */ | 3078 | */ |
2540 | rval = pci_enable_device(pdev); | 3079 | rval = pci_enable_device_mem(pdev); |
2541 | 3080 | ||
2542 | if (rval) { | 3081 | if (rval) { |
2543 | return rval; | 3082 | return rval; |
@@ -2572,6 +3111,9 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2572 | 3111 | ||
2573 | *instance->producer = 0; | 3112 | *instance->producer = 0; |
2574 | *instance->consumer = 0; | 3113 | *instance->consumer = 0; |
3114 | megasas_poll_wait_aen = 0; | ||
3115 | instance->flag_ieee = 0; | ||
3116 | instance->ev = NULL; | ||
2575 | 3117 | ||
2576 | instance->evt_detail = pci_alloc_consistent(pdev, | 3118 | instance->evt_detail = pci_alloc_consistent(pdev, |
2577 | sizeof(struct | 3119 | sizeof(struct |
@@ -2595,10 +3137,11 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2595 | init_waitqueue_head(&instance->abort_cmd_wait_q); | 3137 | init_waitqueue_head(&instance->abort_cmd_wait_q); |
2596 | 3138 | ||
2597 | spin_lock_init(&instance->cmd_pool_lock); | 3139 | spin_lock_init(&instance->cmd_pool_lock); |
3140 | spin_lock_init(&instance->fire_lock); | ||
2598 | spin_lock_init(&instance->completion_lock); | 3141 | spin_lock_init(&instance->completion_lock); |
3142 | spin_lock_init(&poll_aen_lock); | ||
2599 | 3143 | ||
2600 | mutex_init(&instance->aen_mutex); | 3144 | mutex_init(&instance->aen_mutex); |
2601 | sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); | ||
2602 | 3145 | ||
2603 | /* | 3146 | /* |
2604 | * Initialize PCI related and misc parameters | 3147 | * Initialize PCI related and misc parameters |
@@ -2608,8 +3151,16 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2608 | instance->unique_id = pdev->bus->number << 8 | pdev->devfn; | 3151 | instance->unique_id = pdev->bus->number << 8 | pdev->devfn; |
2609 | instance->init_id = MEGASAS_DEFAULT_INIT_ID; | 3152 | instance->init_id = MEGASAS_DEFAULT_INIT_ID; |
2610 | 3153 | ||
3154 | if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || | ||
3155 | (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { | ||
3156 | instance->flag_ieee = 1; | ||
3157 | sema_init(&instance->ioctl_sem, MEGASAS_SKINNY_INT_CMDS); | ||
3158 | } else | ||
3159 | sema_init(&instance->ioctl_sem, MEGASAS_INT_CMDS); | ||
3160 | |||
2611 | megasas_dbg_lvl = 0; | 3161 | megasas_dbg_lvl = 0; |
2612 | instance->flag = 0; | 3162 | instance->flag = 0; |
3163 | instance->unload = 1; | ||
2613 | instance->last_time = 0; | 3164 | instance->last_time = 0; |
2614 | 3165 | ||
2615 | /* | 3166 | /* |
@@ -2655,6 +3206,7 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
2655 | if (megasas_io_attach(instance)) | 3206 | if (megasas_io_attach(instance)) |
2656 | goto fail_io_attach; | 3207 | goto fail_io_attach; |
2657 | 3208 | ||
3209 | instance->unload = 0; | ||
2658 | return 0; | 3210 | return 0; |
2659 | 3211 | ||
2660 | fail_start_aen: | 3212 | fail_start_aen: |
@@ -2715,6 +3267,7 @@ static void megasas_flush_cache(struct megasas_instance *instance) | |||
2715 | dcmd->sge_count = 0; | 3267 | dcmd->sge_count = 0; |
2716 | dcmd->flags = MFI_FRAME_DIR_NONE; | 3268 | dcmd->flags = MFI_FRAME_DIR_NONE; |
2717 | dcmd->timeout = 0; | 3269 | dcmd->timeout = 0; |
3270 | dcmd->pad_0 = 0; | ||
2718 | dcmd->data_xfer_len = 0; | 3271 | dcmd->data_xfer_len = 0; |
2719 | dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH; | 3272 | dcmd->opcode = MR_DCMD_CTRL_CACHE_FLUSH; |
2720 | dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; | 3273 | dcmd->mbox.b[0] = MR_FLUSH_CTRL_CACHE | MR_FLUSH_DISK_CACHE; |
@@ -2754,6 +3307,7 @@ static void megasas_shutdown_controller(struct megasas_instance *instance, | |||
2754 | dcmd->sge_count = 0; | 3307 | dcmd->sge_count = 0; |
2755 | dcmd->flags = MFI_FRAME_DIR_NONE; | 3308 | dcmd->flags = MFI_FRAME_DIR_NONE; |
2756 | dcmd->timeout = 0; | 3309 | dcmd->timeout = 0; |
3310 | dcmd->pad_0 = 0; | ||
2757 | dcmd->data_xfer_len = 0; | 3311 | dcmd->data_xfer_len = 0; |
2758 | dcmd->opcode = opcode; | 3312 | dcmd->opcode = opcode; |
2759 | 3313 | ||
@@ -2778,12 +3332,23 @@ megasas_suspend(struct pci_dev *pdev, pm_message_t state) | |||
2778 | 3332 | ||
2779 | instance = pci_get_drvdata(pdev); | 3333 | instance = pci_get_drvdata(pdev); |
2780 | host = instance->host; | 3334 | host = instance->host; |
3335 | instance->unload = 1; | ||
2781 | 3336 | ||
2782 | if (poll_mode_io) | 3337 | if (poll_mode_io) |
2783 | del_timer_sync(&instance->io_completion_timer); | 3338 | del_timer_sync(&instance->io_completion_timer); |
2784 | 3339 | ||
2785 | megasas_flush_cache(instance); | 3340 | megasas_flush_cache(instance); |
2786 | megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); | 3341 | megasas_shutdown_controller(instance, MR_DCMD_HIBERNATE_SHUTDOWN); |
3342 | |||
3343 | /* cancel the delayed work if this work still in queue */ | ||
3344 | if (instance->ev != NULL) { | ||
3345 | struct megasas_aen_event *ev = instance->ev; | ||
3346 | cancel_delayed_work( | ||
3347 | (struct delayed_work *)&ev->hotplug_work); | ||
3348 | flush_scheduled_work(); | ||
3349 | instance->ev = NULL; | ||
3350 | } | ||
3351 | |||
2787 | tasklet_kill(&instance->isr_tasklet); | 3352 | tasklet_kill(&instance->isr_tasklet); |
2788 | 3353 | ||
2789 | pci_set_drvdata(instance->pdev, instance); | 3354 | pci_set_drvdata(instance->pdev, instance); |
@@ -2818,7 +3383,7 @@ megasas_resume(struct pci_dev *pdev) | |||
2818 | /* | 3383 | /* |
2819 | * PCI prepping: enable device set bus mastering and dma mask | 3384 | * PCI prepping: enable device set bus mastering and dma mask |
2820 | */ | 3385 | */ |
2821 | rval = pci_enable_device(pdev); | 3386 | rval = pci_enable_device_mem(pdev); |
2822 | 3387 | ||
2823 | if (rval) { | 3388 | if (rval) { |
2824 | printk(KERN_ERR "megasas: Enable device failed\n"); | 3389 | printk(KERN_ERR "megasas: Enable device failed\n"); |
@@ -2873,6 +3438,8 @@ megasas_resume(struct pci_dev *pdev) | |||
2873 | megasas_start_timer(instance, &instance->io_completion_timer, | 3438 | megasas_start_timer(instance, &instance->io_completion_timer, |
2874 | megasas_io_completion_timer, | 3439 | megasas_io_completion_timer, |
2875 | MEGASAS_COMPLETION_TIMER_INTERVAL); | 3440 | MEGASAS_COMPLETION_TIMER_INTERVAL); |
3441 | instance->unload = 0; | ||
3442 | |||
2876 | return 0; | 3443 | return 0; |
2877 | 3444 | ||
2878 | fail_irq: | 3445 | fail_irq: |
@@ -2913,6 +3480,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) | |||
2913 | struct megasas_instance *instance; | 3480 | struct megasas_instance *instance; |
2914 | 3481 | ||
2915 | instance = pci_get_drvdata(pdev); | 3482 | instance = pci_get_drvdata(pdev); |
3483 | instance->unload = 1; | ||
2916 | host = instance->host; | 3484 | host = instance->host; |
2917 | 3485 | ||
2918 | if (poll_mode_io) | 3486 | if (poll_mode_io) |
@@ -2921,6 +3489,16 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) | |||
2921 | scsi_remove_host(instance->host); | 3489 | scsi_remove_host(instance->host); |
2922 | megasas_flush_cache(instance); | 3490 | megasas_flush_cache(instance); |
2923 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); | 3491 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
3492 | |||
3493 | /* cancel the delayed work if this work still in queue*/ | ||
3494 | if (instance->ev != NULL) { | ||
3495 | struct megasas_aen_event *ev = instance->ev; | ||
3496 | cancel_delayed_work( | ||
3497 | (struct delayed_work *)&ev->hotplug_work); | ||
3498 | flush_scheduled_work(); | ||
3499 | instance->ev = NULL; | ||
3500 | } | ||
3501 | |||
2924 | tasklet_kill(&instance->isr_tasklet); | 3502 | tasklet_kill(&instance->isr_tasklet); |
2925 | 3503 | ||
2926 | /* | 3504 | /* |
@@ -2969,6 +3547,7 @@ static void __devexit megasas_detach_one(struct pci_dev *pdev) | |||
2969 | static void megasas_shutdown(struct pci_dev *pdev) | 3547 | static void megasas_shutdown(struct pci_dev *pdev) |
2970 | { | 3548 | { |
2971 | struct megasas_instance *instance = pci_get_drvdata(pdev); | 3549 | struct megasas_instance *instance = pci_get_drvdata(pdev); |
3550 | instance->unload = 1; | ||
2972 | megasas_flush_cache(instance); | 3551 | megasas_flush_cache(instance); |
2973 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); | 3552 | megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); |
2974 | } | 3553 | } |
@@ -3016,6 +3595,23 @@ static int megasas_mgmt_fasync(int fd, struct file *filep, int mode) | |||
3016 | } | 3595 | } |
3017 | 3596 | ||
3018 | /** | 3597 | /** |
3598 | * megasas_mgmt_poll - char node "poll" entry point | ||
3599 | * */ | ||
3600 | static unsigned int megasas_mgmt_poll(struct file *file, poll_table *wait) | ||
3601 | { | ||
3602 | unsigned int mask; | ||
3603 | unsigned long flags; | ||
3604 | poll_wait(file, &megasas_poll_wait, wait); | ||
3605 | spin_lock_irqsave(&poll_aen_lock, flags); | ||
3606 | if (megasas_poll_wait_aen) | ||
3607 | mask = (POLLIN | POLLRDNORM); | ||
3608 | else | ||
3609 | mask = 0; | ||
3610 | spin_unlock_irqrestore(&poll_aen_lock, flags); | ||
3611 | return mask; | ||
3612 | } | ||
3613 | |||
3614 | /** | ||
3019 | * megasas_mgmt_fw_ioctl - Issues management ioctls to FW | 3615 | * megasas_mgmt_fw_ioctl - Issues management ioctls to FW |
3020 | * @instance: Adapter soft state | 3616 | * @instance: Adapter soft state |
3021 | * @argp: User's ioctl packet | 3617 | * @argp: User's ioctl packet |
@@ -3032,7 +3628,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
3032 | int error = 0, i; | 3628 | int error = 0, i; |
3033 | void *sense = NULL; | 3629 | void *sense = NULL; |
3034 | dma_addr_t sense_handle; | 3630 | dma_addr_t sense_handle; |
3035 | u32 *sense_ptr; | 3631 | unsigned long *sense_ptr; |
3036 | 3632 | ||
3037 | memset(kbuff_arr, 0, sizeof(kbuff_arr)); | 3633 | memset(kbuff_arr, 0, sizeof(kbuff_arr)); |
3038 | 3634 | ||
@@ -3056,6 +3652,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
3056 | */ | 3652 | */ |
3057 | memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); | 3653 | memcpy(cmd->frame, ioc->frame.raw, 2 * MEGAMFI_FRAME_SIZE); |
3058 | cmd->frame->hdr.context = cmd->index; | 3654 | cmd->frame->hdr.context = cmd->index; |
3655 | cmd->frame->hdr.pad_0 = 0; | ||
3059 | 3656 | ||
3060 | /* | 3657 | /* |
3061 | * The management interface between applications and the fw uses | 3658 | * The management interface between applications and the fw uses |
@@ -3109,7 +3706,7 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
3109 | } | 3706 | } |
3110 | 3707 | ||
3111 | sense_ptr = | 3708 | sense_ptr = |
3112 | (u32 *) ((unsigned long)cmd->frame + ioc->sense_off); | 3709 | (unsigned long *) ((unsigned long)cmd->frame + ioc->sense_off); |
3113 | *sense_ptr = sense_handle; | 3710 | *sense_ptr = sense_handle; |
3114 | } | 3711 | } |
3115 | 3712 | ||
@@ -3140,8 +3737,8 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
3140 | * sense_ptr points to the location that has the user | 3737 | * sense_ptr points to the location that has the user |
3141 | * sense buffer address | 3738 | * sense buffer address |
3142 | */ | 3739 | */ |
3143 | sense_ptr = (u32 *) ((unsigned long)ioc->frame.raw + | 3740 | sense_ptr = (unsigned long *) ((unsigned long)ioc->frame.raw + |
3144 | ioc->sense_off); | 3741 | ioc->sense_off); |
3145 | 3742 | ||
3146 | if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), | 3743 | if (copy_to_user((void __user *)((unsigned long)(*sense_ptr)), |
3147 | sense, ioc->sense_len)) { | 3744 | sense, ioc->sense_len)) { |
@@ -3177,20 +3774,6 @@ megasas_mgmt_fw_ioctl(struct megasas_instance *instance, | |||
3177 | return error; | 3774 | return error; |
3178 | } | 3775 | } |
3179 | 3776 | ||
3180 | static struct megasas_instance *megasas_lookup_instance(u16 host_no) | ||
3181 | { | ||
3182 | int i; | ||
3183 | |||
3184 | for (i = 0; i < megasas_mgmt_info.max_index; i++) { | ||
3185 | |||
3186 | if ((megasas_mgmt_info.instance[i]) && | ||
3187 | (megasas_mgmt_info.instance[i]->host->host_no == host_no)) | ||
3188 | return megasas_mgmt_info.instance[i]; | ||
3189 | } | ||
3190 | |||
3191 | return NULL; | ||
3192 | } | ||
3193 | |||
3194 | static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) | 3777 | static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) |
3195 | { | 3778 | { |
3196 | struct megasas_iocpacket __user *user_ioc = | 3779 | struct megasas_iocpacket __user *user_ioc = |
@@ -3214,6 +3797,17 @@ static int megasas_mgmt_ioctl_fw(struct file *file, unsigned long arg) | |||
3214 | goto out_kfree_ioc; | 3797 | goto out_kfree_ioc; |
3215 | } | 3798 | } |
3216 | 3799 | ||
3800 | if (instance->hw_crit_error == 1) { | ||
3801 | printk(KERN_DEBUG "Controller in Crit ERROR\n"); | ||
3802 | error = -ENODEV; | ||
3803 | goto out_kfree_ioc; | ||
3804 | } | ||
3805 | |||
3806 | if (instance->unload == 1) { | ||
3807 | error = -ENODEV; | ||
3808 | goto out_kfree_ioc; | ||
3809 | } | ||
3810 | |||
3217 | /* | 3811 | /* |
3218 | * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds | 3812 | * We will allow only MEGASAS_INT_CMDS number of parallel ioctl cmds |
3219 | */ | 3813 | */ |
@@ -3249,6 +3843,14 @@ static int megasas_mgmt_ioctl_aen(struct file *file, unsigned long arg) | |||
3249 | if (!instance) | 3843 | if (!instance) |
3250 | return -ENODEV; | 3844 | return -ENODEV; |
3251 | 3845 | ||
3846 | if (instance->hw_crit_error == 1) { | ||
3847 | error = -ENODEV; | ||
3848 | } | ||
3849 | |||
3850 | if (instance->unload == 1) { | ||
3851 | return -ENODEV; | ||
3852 | } | ||
3853 | |||
3252 | mutex_lock(&instance->aen_mutex); | 3854 | mutex_lock(&instance->aen_mutex); |
3253 | error = megasas_register_aen(instance, aen.seq_num, | 3855 | error = megasas_register_aen(instance, aen.seq_num, |
3254 | aen.class_locale_word); | 3856 | aen.class_locale_word); |
@@ -3282,6 +3884,7 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) | |||
3282 | compat_alloc_user_space(sizeof(struct megasas_iocpacket)); | 3884 | compat_alloc_user_space(sizeof(struct megasas_iocpacket)); |
3283 | int i; | 3885 | int i; |
3284 | int error = 0; | 3886 | int error = 0; |
3887 | compat_uptr_t ptr; | ||
3285 | 3888 | ||
3286 | if (clear_user(ioc, sizeof(*ioc))) | 3889 | if (clear_user(ioc, sizeof(*ioc))) |
3287 | return -EFAULT; | 3890 | return -EFAULT; |
@@ -3294,9 +3897,22 @@ static int megasas_mgmt_compat_ioctl_fw(struct file *file, unsigned long arg) | |||
3294 | copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32))) | 3897 | copy_in_user(&ioc->sge_count, &cioc->sge_count, sizeof(u32))) |
3295 | return -EFAULT; | 3898 | return -EFAULT; |
3296 | 3899 | ||
3297 | for (i = 0; i < MAX_IOCTL_SGE; i++) { | 3900 | /* |
3298 | compat_uptr_t ptr; | 3901 | * The sense_ptr is used in megasas_mgmt_fw_ioctl only when |
3902 | * sense_len is not null, so prepare the 64bit value under | ||
3903 | * the same condition. | ||
3904 | */ | ||
3905 | if (ioc->sense_len) { | ||
3906 | void __user **sense_ioc_ptr = | ||
3907 | (void __user **)(ioc->frame.raw + ioc->sense_off); | ||
3908 | compat_uptr_t *sense_cioc_ptr = | ||
3909 | (compat_uptr_t *)(cioc->frame.raw + cioc->sense_off); | ||
3910 | if (get_user(ptr, sense_cioc_ptr) || | ||
3911 | put_user(compat_ptr(ptr), sense_ioc_ptr)) | ||
3912 | return -EFAULT; | ||
3913 | } | ||
3299 | 3914 | ||
3915 | for (i = 0; i < MAX_IOCTL_SGE; i++) { | ||
3300 | if (get_user(ptr, &cioc->sgl[i].iov_base) || | 3916 | if (get_user(ptr, &cioc->sgl[i].iov_base) || |
3301 | put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) || | 3917 | put_user(compat_ptr(ptr), &ioc->sgl[i].iov_base) || |
3302 | copy_in_user(&ioc->sgl[i].iov_len, | 3918 | copy_in_user(&ioc->sgl[i].iov_len, |
@@ -3337,6 +3953,7 @@ static const struct file_operations megasas_mgmt_fops = { | |||
3337 | .open = megasas_mgmt_open, | 3953 | .open = megasas_mgmt_open, |
3338 | .fasync = megasas_mgmt_fasync, | 3954 | .fasync = megasas_mgmt_fasync, |
3339 | .unlocked_ioctl = megasas_mgmt_ioctl, | 3955 | .unlocked_ioctl = megasas_mgmt_ioctl, |
3956 | .poll = megasas_mgmt_poll, | ||
3340 | #ifdef CONFIG_COMPAT | 3957 | #ifdef CONFIG_COMPAT |
3341 | .compat_ioctl = megasas_mgmt_compat_ioctl, | 3958 | .compat_ioctl = megasas_mgmt_compat_ioctl, |
3342 | #endif | 3959 | #endif |
@@ -3378,6 +3995,15 @@ static DRIVER_ATTR(release_date, S_IRUGO, megasas_sysfs_show_release_date, | |||
3378 | NULL); | 3995 | NULL); |
3379 | 3996 | ||
3380 | static ssize_t | 3997 | static ssize_t |
3998 | megasas_sysfs_show_support_poll_for_event(struct device_driver *dd, char *buf) | ||
3999 | { | ||
4000 | return sprintf(buf, "%u\n", support_poll_for_event); | ||
4001 | } | ||
4002 | |||
4003 | static DRIVER_ATTR(support_poll_for_event, S_IRUGO, | ||
4004 | megasas_sysfs_show_support_poll_for_event, NULL); | ||
4005 | |||
4006 | static ssize_t | ||
3381 | megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) | 4007 | megasas_sysfs_show_dbg_lvl(struct device_driver *dd, char *buf) |
3382 | { | 4008 | { |
3383 | return sprintf(buf, "%u\n", megasas_dbg_lvl); | 4009 | return sprintf(buf, "%u\n", megasas_dbg_lvl); |
@@ -3451,7 +4077,235 @@ out: | |||
3451 | return retval; | 4077 | return retval; |
3452 | } | 4078 | } |
3453 | 4079 | ||
3454 | static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUGO, | 4080 | static void |
4081 | megasas_aen_polling(struct work_struct *work) | ||
4082 | { | ||
4083 | struct megasas_aen_event *ev = | ||
4084 | container_of(work, struct megasas_aen_event, hotplug_work); | ||
4085 | struct megasas_instance *instance = ev->instance; | ||
4086 | union megasas_evt_class_locale class_locale; | ||
4087 | struct Scsi_Host *host; | ||
4088 | struct scsi_device *sdev1; | ||
4089 | u16 pd_index = 0; | ||
4090 | u16 ld_index = 0; | ||
4091 | int i, j, doscan = 0; | ||
4092 | u32 seq_num; | ||
4093 | int error; | ||
4094 | |||
4095 | if (!instance) { | ||
4096 | printk(KERN_ERR "invalid instance!\n"); | ||
4097 | kfree(ev); | ||
4098 | return; | ||
4099 | } | ||
4100 | instance->ev = NULL; | ||
4101 | host = instance->host; | ||
4102 | if (instance->evt_detail) { | ||
4103 | |||
4104 | switch (instance->evt_detail->code) { | ||
4105 | case MR_EVT_PD_INSERTED: | ||
4106 | if (megasas_get_pd_list(instance) == 0) { | ||
4107 | for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { | ||
4108 | for (j = 0; | ||
4109 | j < MEGASAS_MAX_DEV_PER_CHANNEL; | ||
4110 | j++) { | ||
4111 | |||
4112 | pd_index = | ||
4113 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; | ||
4114 | |||
4115 | sdev1 = | ||
4116 | scsi_device_lookup(host, i, j, 0); | ||
4117 | |||
4118 | if (instance->pd_list[pd_index].driveState | ||
4119 | == MR_PD_STATE_SYSTEM) { | ||
4120 | if (!sdev1) { | ||
4121 | scsi_add_device(host, i, j, 0); | ||
4122 | } | ||
4123 | |||
4124 | if (sdev1) | ||
4125 | scsi_device_put(sdev1); | ||
4126 | } | ||
4127 | } | ||
4128 | } | ||
4129 | } | ||
4130 | doscan = 0; | ||
4131 | break; | ||
4132 | |||
4133 | case MR_EVT_PD_REMOVED: | ||
4134 | if (megasas_get_pd_list(instance) == 0) { | ||
4135 | megasas_get_pd_list(instance); | ||
4136 | for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { | ||
4137 | for (j = 0; | ||
4138 | j < MEGASAS_MAX_DEV_PER_CHANNEL; | ||
4139 | j++) { | ||
4140 | |||
4141 | pd_index = | ||
4142 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; | ||
4143 | |||
4144 | sdev1 = | ||
4145 | scsi_device_lookup(host, i, j, 0); | ||
4146 | |||
4147 | if (instance->pd_list[pd_index].driveState | ||
4148 | == MR_PD_STATE_SYSTEM) { | ||
4149 | if (sdev1) { | ||
4150 | scsi_device_put(sdev1); | ||
4151 | } | ||
4152 | } else { | ||
4153 | if (sdev1) { | ||
4154 | scsi_remove_device(sdev1); | ||
4155 | scsi_device_put(sdev1); | ||
4156 | } | ||
4157 | } | ||
4158 | } | ||
4159 | } | ||
4160 | } | ||
4161 | doscan = 0; | ||
4162 | break; | ||
4163 | |||
4164 | case MR_EVT_LD_OFFLINE: | ||
4165 | case MR_EVT_LD_DELETED: | ||
4166 | megasas_get_ld_list(instance); | ||
4167 | for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { | ||
4168 | for (j = 0; | ||
4169 | j < MEGASAS_MAX_DEV_PER_CHANNEL; | ||
4170 | j++) { | ||
4171 | |||
4172 | ld_index = | ||
4173 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; | ||
4174 | |||
4175 | sdev1 = scsi_device_lookup(host, | ||
4176 | i + MEGASAS_MAX_LD_CHANNELS, | ||
4177 | j, | ||
4178 | 0); | ||
4179 | |||
4180 | if (instance->ld_ids[ld_index] != 0xff) { | ||
4181 | if (sdev1) { | ||
4182 | scsi_device_put(sdev1); | ||
4183 | } | ||
4184 | } else { | ||
4185 | if (sdev1) { | ||
4186 | scsi_remove_device(sdev1); | ||
4187 | scsi_device_put(sdev1); | ||
4188 | } | ||
4189 | } | ||
4190 | } | ||
4191 | } | ||
4192 | doscan = 0; | ||
4193 | break; | ||
4194 | case MR_EVT_LD_CREATED: | ||
4195 | megasas_get_ld_list(instance); | ||
4196 | for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { | ||
4197 | for (j = 0; | ||
4198 | j < MEGASAS_MAX_DEV_PER_CHANNEL; | ||
4199 | j++) { | ||
4200 | ld_index = | ||
4201 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; | ||
4202 | |||
4203 | sdev1 = scsi_device_lookup(host, | ||
4204 | i+MEGASAS_MAX_LD_CHANNELS, | ||
4205 | j, 0); | ||
4206 | |||
4207 | if (instance->ld_ids[ld_index] != | ||
4208 | 0xff) { | ||
4209 | if (!sdev1) { | ||
4210 | scsi_add_device(host, | ||
4211 | i + 2, | ||
4212 | j, 0); | ||
4213 | } | ||
4214 | } | ||
4215 | if (sdev1) { | ||
4216 | scsi_device_put(sdev1); | ||
4217 | } | ||
4218 | } | ||
4219 | } | ||
4220 | doscan = 0; | ||
4221 | break; | ||
4222 | case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: | ||
4223 | case MR_EVT_FOREIGN_CFG_IMPORTED: | ||
4224 | doscan = 1; | ||
4225 | break; | ||
4226 | default: | ||
4227 | doscan = 0; | ||
4228 | break; | ||
4229 | } | ||
4230 | } else { | ||
4231 | printk(KERN_ERR "invalid evt_detail!\n"); | ||
4232 | kfree(ev); | ||
4233 | return; | ||
4234 | } | ||
4235 | |||
4236 | if (doscan) { | ||
4237 | printk(KERN_INFO "scanning ...\n"); | ||
4238 | megasas_get_pd_list(instance); | ||
4239 | for (i = 0; i < MEGASAS_MAX_PD_CHANNELS; i++) { | ||
4240 | for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { | ||
4241 | pd_index = i*MEGASAS_MAX_DEV_PER_CHANNEL + j; | ||
4242 | sdev1 = scsi_device_lookup(host, i, j, 0); | ||
4243 | if (instance->pd_list[pd_index].driveState == | ||
4244 | MR_PD_STATE_SYSTEM) { | ||
4245 | if (!sdev1) { | ||
4246 | scsi_add_device(host, i, j, 0); | ||
4247 | } | ||
4248 | if (sdev1) | ||
4249 | scsi_device_put(sdev1); | ||
4250 | } else { | ||
4251 | if (sdev1) { | ||
4252 | scsi_remove_device(sdev1); | ||
4253 | scsi_device_put(sdev1); | ||
4254 | } | ||
4255 | } | ||
4256 | } | ||
4257 | } | ||
4258 | |||
4259 | megasas_get_ld_list(instance); | ||
4260 | for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) { | ||
4261 | for (j = 0; j < MEGASAS_MAX_DEV_PER_CHANNEL; j++) { | ||
4262 | ld_index = | ||
4263 | (i * MEGASAS_MAX_DEV_PER_CHANNEL) + j; | ||
4264 | |||
4265 | sdev1 = scsi_device_lookup(host, | ||
4266 | i+MEGASAS_MAX_LD_CHANNELS, j, 0); | ||
4267 | if (instance->ld_ids[ld_index] != 0xff) { | ||
4268 | if (!sdev1) { | ||
4269 | scsi_add_device(host, | ||
4270 | i+2, | ||
4271 | j, 0); | ||
4272 | } else { | ||
4273 | scsi_device_put(sdev1); | ||
4274 | } | ||
4275 | } else { | ||
4276 | if (sdev1) { | ||
4277 | scsi_remove_device(sdev1); | ||
4278 | scsi_device_put(sdev1); | ||
4279 | } | ||
4280 | } | ||
4281 | } | ||
4282 | } | ||
4283 | } | ||
4284 | |||
4285 | if ( instance->aen_cmd != NULL ) { | ||
4286 | kfree(ev); | ||
4287 | return ; | ||
4288 | } | ||
4289 | |||
4290 | seq_num = instance->evt_detail->seq_num + 1; | ||
4291 | |||
4292 | /* Register AEN with FW for latest sequence number plus 1 */ | ||
4293 | class_locale.members.reserved = 0; | ||
4294 | class_locale.members.locale = MR_EVT_LOCALE_ALL; | ||
4295 | class_locale.members.class = MR_EVT_CLASS_DEBUG; | ||
4296 | mutex_lock(&instance->aen_mutex); | ||
4297 | error = megasas_register_aen(instance, seq_num, | ||
4298 | class_locale.word); | ||
4299 | mutex_unlock(&instance->aen_mutex); | ||
4300 | |||
4301 | if (error) | ||
4302 | printk(KERN_ERR "register aen failed error %x\n", error); | ||
4303 | |||
4304 | kfree(ev); | ||
4305 | } | ||
4306 | |||
4307 | |||
4308 | static DRIVER_ATTR(poll_mode_io, S_IRUGO|S_IWUSR, | ||
3455 | megasas_sysfs_show_poll_mode_io, | 4309 | megasas_sysfs_show_poll_mode_io, |
3456 | megasas_sysfs_set_poll_mode_io); | 4310 | megasas_sysfs_set_poll_mode_io); |
3457 | 4311 | ||
@@ -3468,6 +4322,8 @@ static int __init megasas_init(void) | |||
3468 | printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, | 4322 | printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION, |
3469 | MEGASAS_EXT_VERSION); | 4323 | MEGASAS_EXT_VERSION); |
3470 | 4324 | ||
4325 | support_poll_for_event = 2; | ||
4326 | |||
3471 | memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info)); | 4327 | memset(&megasas_mgmt_info, 0, sizeof(megasas_mgmt_info)); |
3472 | 4328 | ||
3473 | /* | 4329 | /* |
@@ -3500,6 +4356,12 @@ static int __init megasas_init(void) | |||
3500 | &driver_attr_release_date); | 4356 | &driver_attr_release_date); |
3501 | if (rval) | 4357 | if (rval) |
3502 | goto err_dcf_rel_date; | 4358 | goto err_dcf_rel_date; |
4359 | |||
4360 | rval = driver_create_file(&megasas_pci_driver.driver, | ||
4361 | &driver_attr_support_poll_for_event); | ||
4362 | if (rval) | ||
4363 | goto err_dcf_support_poll_for_event; | ||
4364 | |||
3503 | rval = driver_create_file(&megasas_pci_driver.driver, | 4365 | rval = driver_create_file(&megasas_pci_driver.driver, |
3504 | &driver_attr_dbg_lvl); | 4366 | &driver_attr_dbg_lvl); |
3505 | if (rval) | 4367 | if (rval) |
@@ -3516,7 +4378,12 @@ err_dcf_poll_mode_io: | |||
3516 | &driver_attr_dbg_lvl); | 4378 | &driver_attr_dbg_lvl); |
3517 | err_dcf_dbg_lvl: | 4379 | err_dcf_dbg_lvl: |
3518 | driver_remove_file(&megasas_pci_driver.driver, | 4380 | driver_remove_file(&megasas_pci_driver.driver, |
4381 | &driver_attr_support_poll_for_event); | ||
4382 | |||
4383 | err_dcf_support_poll_for_event: | ||
4384 | driver_remove_file(&megasas_pci_driver.driver, | ||
3519 | &driver_attr_release_date); | 4385 | &driver_attr_release_date); |
4386 | |||
3520 | err_dcf_rel_date: | 4387 | err_dcf_rel_date: |
3521 | driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); | 4388 | driver_remove_file(&megasas_pci_driver.driver, &driver_attr_version); |
3522 | err_dcf_attr_ver: | 4389 | err_dcf_attr_ver: |
diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 0d033248fdf1..9d8b6bf605aa 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h | |||
@@ -18,9 +18,9 @@ | |||
18 | /* | 18 | /* |
19 | * MegaRAID SAS Driver meta data | 19 | * MegaRAID SAS Driver meta data |
20 | */ | 20 | */ |
21 | #define MEGASAS_VERSION "00.00.04.01" | 21 | #define MEGASAS_VERSION "00.00.04.17.1-rc1" |
22 | #define MEGASAS_RELDATE "July 24, 2008" | 22 | #define MEGASAS_RELDATE "Oct. 29, 2009" |
23 | #define MEGASAS_EXT_VERSION "Thu July 24 11:41:51 PST 2008" | 23 | #define MEGASAS_EXT_VERSION "Thu. Oct. 29, 11:41:51 PST 2009" |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Device IDs | 26 | * Device IDs |
@@ -30,6 +30,8 @@ | |||
30 | #define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413 | 30 | #define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413 |
31 | #define PCI_DEVICE_ID_LSI_SAS1078GEN2 0x0078 | 31 | #define PCI_DEVICE_ID_LSI_SAS1078GEN2 0x0078 |
32 | #define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079 | 32 | #define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079 |
33 | #define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073 | ||
34 | #define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071 | ||
33 | 35 | ||
34 | /* | 36 | /* |
35 | * ===================================== | 37 | * ===================================== |
@@ -94,6 +96,7 @@ | |||
94 | #define MFI_FRAME_DIR_WRITE 0x0008 | 96 | #define MFI_FRAME_DIR_WRITE 0x0008 |
95 | #define MFI_FRAME_DIR_READ 0x0010 | 97 | #define MFI_FRAME_DIR_READ 0x0010 |
96 | #define MFI_FRAME_DIR_BOTH 0x0018 | 98 | #define MFI_FRAME_DIR_BOTH 0x0018 |
99 | #define MFI_FRAME_IEEE 0x0020 | ||
97 | 100 | ||
98 | /* | 101 | /* |
99 | * Definition for cmd_status | 102 | * Definition for cmd_status |
@@ -114,6 +117,7 @@ | |||
114 | #define MFI_CMD_STP 0x08 | 117 | #define MFI_CMD_STP 0x08 |
115 | 118 | ||
116 | #define MR_DCMD_CTRL_GET_INFO 0x01010000 | 119 | #define MR_DCMD_CTRL_GET_INFO 0x01010000 |
120 | #define MR_DCMD_LD_GET_LIST 0x03010000 | ||
117 | 121 | ||
118 | #define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000 | 122 | #define MR_DCMD_CTRL_CACHE_FLUSH 0x01101000 |
119 | #define MR_FLUSH_CTRL_CACHE 0x01 | 123 | #define MR_FLUSH_CTRL_CACHE 0x01 |
@@ -131,6 +135,7 @@ | |||
131 | #define MR_DCMD_CLUSTER 0x08000000 | 135 | #define MR_DCMD_CLUSTER 0x08000000 |
132 | #define MR_DCMD_CLUSTER_RESET_ALL 0x08010100 | 136 | #define MR_DCMD_CLUSTER_RESET_ALL 0x08010100 |
133 | #define MR_DCMD_CLUSTER_RESET_LD 0x08010200 | 137 | #define MR_DCMD_CLUSTER_RESET_LD 0x08010200 |
138 | #define MR_DCMD_PD_LIST_QUERY 0x02010100 | ||
134 | 139 | ||
135 | /* | 140 | /* |
136 | * MFI command completion codes | 141 | * MFI command completion codes |
@@ -251,9 +256,126 @@ enum MR_EVT_ARGS { | |||
251 | MR_EVT_ARGS_STR, | 256 | MR_EVT_ARGS_STR, |
252 | MR_EVT_ARGS_TIME, | 257 | MR_EVT_ARGS_TIME, |
253 | MR_EVT_ARGS_ECC, | 258 | MR_EVT_ARGS_ECC, |
259 | MR_EVT_ARGS_LD_PROP, | ||
260 | MR_EVT_ARGS_PD_SPARE, | ||
261 | MR_EVT_ARGS_PD_INDEX, | ||
262 | MR_EVT_ARGS_DIAG_PASS, | ||
263 | MR_EVT_ARGS_DIAG_FAIL, | ||
264 | MR_EVT_ARGS_PD_LBA_LBA, | ||
265 | MR_EVT_ARGS_PORT_PHY, | ||
266 | MR_EVT_ARGS_PD_MISSING, | ||
267 | MR_EVT_ARGS_PD_ADDRESS, | ||
268 | MR_EVT_ARGS_BITMAP, | ||
269 | MR_EVT_ARGS_CONNECTOR, | ||
270 | MR_EVT_ARGS_PD_PD, | ||
271 | MR_EVT_ARGS_PD_FRU, | ||
272 | MR_EVT_ARGS_PD_PATHINFO, | ||
273 | MR_EVT_ARGS_PD_POWER_STATE, | ||
274 | MR_EVT_ARGS_GENERIC, | ||
275 | }; | ||
254 | 276 | ||
277 | /* | ||
278 | * define constants for device list query options | ||
279 | */ | ||
280 | enum MR_PD_QUERY_TYPE { | ||
281 | MR_PD_QUERY_TYPE_ALL = 0, | ||
282 | MR_PD_QUERY_TYPE_STATE = 1, | ||
283 | MR_PD_QUERY_TYPE_POWER_STATE = 2, | ||
284 | MR_PD_QUERY_TYPE_MEDIA_TYPE = 3, | ||
285 | MR_PD_QUERY_TYPE_SPEED = 4, | ||
286 | MR_PD_QUERY_TYPE_EXPOSED_TO_HOST = 5, | ||
255 | }; | 287 | }; |
256 | 288 | ||
289 | #define MR_EVT_CFG_CLEARED 0x0004 | ||
290 | #define MR_EVT_LD_STATE_CHANGE 0x0051 | ||
291 | #define MR_EVT_PD_INSERTED 0x005b | ||
292 | #define MR_EVT_PD_REMOVED 0x0070 | ||
293 | #define MR_EVT_LD_CREATED 0x008a | ||
294 | #define MR_EVT_LD_DELETED 0x008b | ||
295 | #define MR_EVT_FOREIGN_CFG_IMPORTED 0x00db | ||
296 | #define MR_EVT_LD_OFFLINE 0x00fc | ||
297 | #define MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED 0x0152 | ||
298 | #define MAX_LOGICAL_DRIVES 64 | ||
299 | |||
300 | enum MR_PD_STATE { | ||
301 | MR_PD_STATE_UNCONFIGURED_GOOD = 0x00, | ||
302 | MR_PD_STATE_UNCONFIGURED_BAD = 0x01, | ||
303 | MR_PD_STATE_HOT_SPARE = 0x02, | ||
304 | MR_PD_STATE_OFFLINE = 0x10, | ||
305 | MR_PD_STATE_FAILED = 0x11, | ||
306 | MR_PD_STATE_REBUILD = 0x14, | ||
307 | MR_PD_STATE_ONLINE = 0x18, | ||
308 | MR_PD_STATE_COPYBACK = 0x20, | ||
309 | MR_PD_STATE_SYSTEM = 0x40, | ||
310 | }; | ||
311 | |||
312 | |||
313 | /* | ||
314 | * defines the physical drive address structure | ||
315 | */ | ||
316 | struct MR_PD_ADDRESS { | ||
317 | u16 deviceId; | ||
318 | u16 enclDeviceId; | ||
319 | |||
320 | union { | ||
321 | struct { | ||
322 | u8 enclIndex; | ||
323 | u8 slotNumber; | ||
324 | } mrPdAddress; | ||
325 | struct { | ||
326 | u8 enclPosition; | ||
327 | u8 enclConnectorIndex; | ||
328 | } mrEnclAddress; | ||
329 | }; | ||
330 | u8 scsiDevType; | ||
331 | union { | ||
332 | u8 connectedPortBitmap; | ||
333 | u8 connectedPortNumbers; | ||
334 | }; | ||
335 | u64 sasAddr[2]; | ||
336 | } __packed; | ||
337 | |||
338 | /* | ||
339 | * defines the physical drive list structure | ||
340 | */ | ||
341 | struct MR_PD_LIST { | ||
342 | u32 size; | ||
343 | u32 count; | ||
344 | struct MR_PD_ADDRESS addr[1]; | ||
345 | } __packed; | ||
346 | |||
347 | struct megasas_pd_list { | ||
348 | u16 tid; | ||
349 | u8 driveType; | ||
350 | u8 driveState; | ||
351 | } __packed; | ||
352 | |||
353 | /* | ||
354 | * defines the logical drive reference structure | ||
355 | */ | ||
356 | union MR_LD_REF { | ||
357 | struct { | ||
358 | u8 targetId; | ||
359 | u8 reserved; | ||
360 | u16 seqNum; | ||
361 | }; | ||
362 | u32 ref; | ||
363 | } __packed; | ||
364 | |||
365 | /* | ||
366 | * defines the logical drive list structure | ||
367 | */ | ||
368 | struct MR_LD_LIST { | ||
369 | u32 ldCount; | ||
370 | u32 reserved; | ||
371 | struct { | ||
372 | union MR_LD_REF ref; | ||
373 | u8 state; | ||
374 | u8 reserved[3]; | ||
375 | u64 size; | ||
376 | } ldList[MAX_LOGICAL_DRIVES]; | ||
377 | } __packed; | ||
378 | |||
257 | /* | 379 | /* |
258 | * SAS controller properties | 380 | * SAS controller properties |
259 | */ | 381 | */ |
@@ -282,7 +404,7 @@ struct megasas_ctrl_prop { | |||
282 | u8 expose_encl_devices; | 404 | u8 expose_encl_devices; |
283 | u8 reserved[38]; | 405 | u8 reserved[38]; |
284 | 406 | ||
285 | } __attribute__ ((packed)); | 407 | } __packed; |
286 | 408 | ||
287 | /* | 409 | /* |
288 | * SAS controller information | 410 | * SAS controller information |
@@ -525,7 +647,7 @@ struct megasas_ctrl_info { | |||
525 | 647 | ||
526 | u8 pad[0x800 - 0x6a0]; | 648 | u8 pad[0x800 - 0x6a0]; |
527 | 649 | ||
528 | } __attribute__ ((packed)); | 650 | } __packed; |
529 | 651 | ||
530 | /* | 652 | /* |
531 | * =============================== | 653 | * =============================== |
@@ -540,6 +662,10 @@ struct megasas_ctrl_info { | |||
540 | #define MEGASAS_DEFAULT_INIT_ID -1 | 662 | #define MEGASAS_DEFAULT_INIT_ID -1 |
541 | #define MEGASAS_MAX_LUN 8 | 663 | #define MEGASAS_MAX_LUN 8 |
542 | #define MEGASAS_MAX_LD 64 | 664 | #define MEGASAS_MAX_LD 64 |
665 | #define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \ | ||
666 | MEGASAS_MAX_DEV_PER_CHANNEL) | ||
667 | #define MEGASAS_MAX_LD_IDS (MEGASAS_MAX_LD_CHANNELS * \ | ||
668 | MEGASAS_MAX_DEV_PER_CHANNEL) | ||
543 | 669 | ||
544 | #define MEGASAS_DBG_LVL 1 | 670 | #define MEGASAS_DBG_LVL 1 |
545 | 671 | ||
@@ -570,6 +696,7 @@ struct megasas_ctrl_info { | |||
570 | * is shown below | 696 | * is shown below |
571 | */ | 697 | */ |
572 | #define MEGASAS_INT_CMDS 32 | 698 | #define MEGASAS_INT_CMDS 32 |
699 | #define MEGASAS_SKINNY_INT_CMDS 5 | ||
573 | 700 | ||
574 | /* | 701 | /* |
575 | * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit | 702 | * FW can accept both 32 and 64 bit SGLs. We want to allocate 32/64 bit |
@@ -584,6 +711,8 @@ struct megasas_ctrl_info { | |||
584 | #define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 | 711 | #define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 |
585 | #define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001 | 712 | #define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001 |
586 | #define MFI_GEN2_ENABLE_INTERRUPT_MASK (0x00000001 | 0x00000004) | 713 | #define MFI_GEN2_ENABLE_INTERRUPT_MASK (0x00000001 | 0x00000004) |
714 | #define MFI_REPLY_SKINNY_MESSAGE_INTERRUPT 0x40000000 | ||
715 | #define MFI_SKINNY_ENABLE_INTERRUPT_MASK (0x00000001) | ||
587 | 716 | ||
588 | /* | 717 | /* |
589 | * register set for both 1068 and 1078 controllers | 718 | * register set for both 1068 and 1078 controllers |
@@ -644,10 +773,17 @@ struct megasas_sge64 { | |||
644 | 773 | ||
645 | } __attribute__ ((packed)); | 774 | } __attribute__ ((packed)); |
646 | 775 | ||
776 | struct megasas_sge_skinny { | ||
777 | u64 phys_addr; | ||
778 | u32 length; | ||
779 | u32 flag; | ||
780 | } __packed; | ||
781 | |||
647 | union megasas_sgl { | 782 | union megasas_sgl { |
648 | 783 | ||
649 | struct megasas_sge32 sge32[1]; | 784 | struct megasas_sge32 sge32[1]; |
650 | struct megasas_sge64 sge64[1]; | 785 | struct megasas_sge64 sge64[1]; |
786 | struct megasas_sge_skinny sge_skinny[1]; | ||
651 | 787 | ||
652 | } __attribute__ ((packed)); | 788 | } __attribute__ ((packed)); |
653 | 789 | ||
@@ -1061,16 +1197,10 @@ struct megasas_evt_detail { | |||
1061 | 1197 | ||
1062 | } __attribute__ ((packed)); | 1198 | } __attribute__ ((packed)); |
1063 | 1199 | ||
1064 | struct megasas_instance_template { | 1200 | struct megasas_aen_event { |
1065 | void (*fire_cmd)(dma_addr_t ,u32 ,struct megasas_register_set __iomem *); | 1201 | struct work_struct hotplug_work; |
1066 | 1202 | struct megasas_instance *instance; | |
1067 | void (*enable_intr)(struct megasas_register_set __iomem *) ; | 1203 | }; |
1068 | void (*disable_intr)(struct megasas_register_set __iomem *); | ||
1069 | |||
1070 | int (*clear_intr)(struct megasas_register_set __iomem *); | ||
1071 | |||
1072 | u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *); | ||
1073 | }; | ||
1074 | 1204 | ||
1075 | struct megasas_instance { | 1205 | struct megasas_instance { |
1076 | 1206 | ||
@@ -1085,17 +1215,22 @@ struct megasas_instance { | |||
1085 | unsigned long base_addr; | 1215 | unsigned long base_addr; |
1086 | struct megasas_register_set __iomem *reg_set; | 1216 | struct megasas_register_set __iomem *reg_set; |
1087 | 1217 | ||
1218 | struct megasas_pd_list pd_list[MEGASAS_MAX_PD]; | ||
1219 | u8 ld_ids[MEGASAS_MAX_LD_IDS]; | ||
1088 | s8 init_id; | 1220 | s8 init_id; |
1089 | 1221 | ||
1090 | u16 max_num_sge; | 1222 | u16 max_num_sge; |
1091 | u16 max_fw_cmds; | 1223 | u16 max_fw_cmds; |
1092 | u32 max_sectors_per_req; | 1224 | u32 max_sectors_per_req; |
1225 | struct megasas_aen_event *ev; | ||
1093 | 1226 | ||
1094 | struct megasas_cmd **cmd_list; | 1227 | struct megasas_cmd **cmd_list; |
1095 | struct list_head cmd_pool; | 1228 | struct list_head cmd_pool; |
1096 | spinlock_t cmd_pool_lock; | 1229 | spinlock_t cmd_pool_lock; |
1097 | /* used to synch producer, consumer ptrs in dpc */ | 1230 | /* used to synch producer, consumer ptrs in dpc */ |
1098 | spinlock_t completion_lock; | 1231 | spinlock_t completion_lock; |
1232 | /* used to sync fire the cmd to fw */ | ||
1233 | spinlock_t fire_lock; | ||
1099 | struct dma_pool *frame_dma_pool; | 1234 | struct dma_pool *frame_dma_pool; |
1100 | struct dma_pool *sense_dma_pool; | 1235 | struct dma_pool *sense_dma_pool; |
1101 | 1236 | ||
@@ -1120,11 +1255,25 @@ struct megasas_instance { | |||
1120 | struct tasklet_struct isr_tasklet; | 1255 | struct tasklet_struct isr_tasklet; |
1121 | 1256 | ||
1122 | u8 flag; | 1257 | u8 flag; |
1258 | u8 unload; | ||
1259 | u8 flag_ieee; | ||
1123 | unsigned long last_time; | 1260 | unsigned long last_time; |
1124 | 1261 | ||
1125 | struct timer_list io_completion_timer; | 1262 | struct timer_list io_completion_timer; |
1126 | }; | 1263 | }; |
1127 | 1264 | ||
1265 | struct megasas_instance_template { | ||
1266 | void (*fire_cmd)(struct megasas_instance *, dma_addr_t, \ | ||
1267 | u32, struct megasas_register_set __iomem *); | ||
1268 | |||
1269 | void (*enable_intr)(struct megasas_register_set __iomem *) ; | ||
1270 | void (*disable_intr)(struct megasas_register_set __iomem *); | ||
1271 | |||
1272 | int (*clear_intr)(struct megasas_register_set __iomem *); | ||
1273 | |||
1274 | u32 (*read_fw_status_reg)(struct megasas_register_set __iomem *); | ||
1275 | }; | ||
1276 | |||
1128 | #define MEGASAS_IS_LOGICAL(scp) \ | 1277 | #define MEGASAS_IS_LOGICAL(scp) \ |
1129 | (scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1 | 1278 | (scp->device->channel < MEGASAS_MAX_PD_CHANNELS) ? 0 : 1 |
1130 | 1279 | ||