Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[SCSI] megaraid_sas: Add 9565/9285 specific code

This patch adds MegaRAID 9265/9285 (Device id 0x5b) specific code

Signed-off-by: Adam Radford <aradford@gmail.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>

authored by

adam radford and committed by
James Bottomley
9c915a8c cd50ba8e

+3751 -111
+2 -1
drivers/scsi/megaraid/Makefile
··· 1 1 obj-$(CONFIG_MEGARAID_MM) += megaraid_mm.o 2 2 obj-$(CONFIG_MEGARAID_MAILBOX) += megaraid_mbox.o 3 3 obj-$(CONFIG_MEGARAID_SAS) += megaraid_sas.o 4 - megaraid_sas-objs := megaraid_sas_base.o 4 + megaraid_sas-objs := megaraid_sas_base.o megaraid_sas_fusion.o \ 5 + megaraid_sas_fp.o
+30 -8
drivers/scsi/megaraid/megaraid_sas.h
··· 33 33 /* 34 34 * MegaRAID SAS Driver meta data 35 35 */ 36 - #define MEGASAS_VERSION "00.00.04.31-rc1" 37 - #define MEGASAS_RELDATE "May 3, 2010" 38 - #define MEGASAS_EXT_VERSION "Mon. May 3, 11:41:51 PST 2010" 36 + #define MEGASAS_VERSION "00.00.05.29-rc1" 37 + #define MEGASAS_RELDATE "Dec. 7, 2010" 38 + #define MEGASAS_EXT_VERSION "Tue. Dec. 7 17:00:00 PDT 2010" 39 39 40 40 /* 41 41 * Device IDs ··· 47 47 #define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079 48 48 #define PCI_DEVICE_ID_LSI_SAS0073SKINNY 0x0073 49 49 #define PCI_DEVICE_ID_LSI_SAS0071SKINNY 0x0071 50 + #define PCI_DEVICE_ID_LSI_FUSION 0x005b 50 51 51 52 /* 52 53 * ===================================== ··· 437 436 * Add properties that can be controlled by 438 437 * a bit in the following structure. 439 438 */ 440 - 441 439 struct { 442 440 u32 copyBackDisabled : 1; 443 441 u32 SMARTerEnabled : 1; ··· 716 716 #define MEGASAS_DEFAULT_INIT_ID -1 717 717 #define MEGASAS_MAX_LUN 8 718 718 #define MEGASAS_MAX_LD 64 719 + #define MEGASAS_DEFAULT_CMD_PER_LUN 128 719 720 #define MEGASAS_MAX_PD (MEGASAS_MAX_PD_CHANNELS * \ 720 721 MEGASAS_MAX_DEV_PER_CHANNEL) 721 722 #define MEGASAS_MAX_LD_IDS (MEGASAS_MAX_LD_CHANNELS * \ ··· 785 784 */ 786 785 787 786 struct megasas_register_set { 788 - u32 reserved_0[4]; /*0000h*/ 787 + u32 doorbell; /*0000h*/ 788 + u32 fusion_seq_offset; /*0004h*/ 789 + u32 fusion_host_diag; /*0008h*/ 790 + u32 reserved_01; /*000Ch*/ 789 791 790 792 u32 inbound_msg_0; /*0010h*/ 791 793 u32 inbound_msg_1; /*0014h*/ ··· 808 804 u32 inbound_queue_port; /*0040h*/ 809 805 u32 outbound_queue_port; /*0044h*/ 810 806 811 - u32 reserved_2[22]; /*0048h*/ 807 + u32 reserved_2[9]; /*0048h*/ 808 + u32 reply_post_host_index; /*006Ch*/ 809 + u32 reserved_2_2[12]; /*0070h*/ 812 810 813 811 u32 outbound_doorbell_clear; /*00A0h*/ 814 812 815 813 u32 reserved_3[3]; /*00A4h*/ 816 814 817 815 u32 outbound_scratch_pad ; /*00B0h*/ 816 + u32 outbound_scratch_pad_2; /*00B4h*/ 818 817 819 - u32 reserved_4[3]; /*00B4h*/ 818 + u32 reserved_4[2]; /*00B8h*/ 820 819 821 820 u32 inbound_low_queue_port ; /*00C0h*/ 822 821 ··· 1294 1287 1295 1288 u16 max_num_sge; 1296 1289 u16 max_fw_cmds; 1290 + /* For Fusion its num IOCTL cmds, for others MFI based its 1291 + max_fw_cmds */ 1292 + u16 max_mfi_cmds; 1297 1293 u32 max_sectors_per_req; 1298 1294 struct megasas_aen_event *ev; 1299 1295 ··· 1346 1336 struct timer_list io_completion_timer; 1347 1337 struct list_head internal_reset_pending_q; 1348 1338 1339 + /* Ptr to hba specfic information */ 1340 + void *ctrl_context; 1349 1341 u8 msi_flag; 1350 1342 struct msix_entry msixentry; 1343 + u64 map_id; 1344 + struct megasas_cmd *map_update_cmd; 1351 1345 unsigned long bar; 1346 + long reset_flags; 1347 + struct mutex reset_mutex; 1352 1348 }; 1353 1349 1354 1350 enum { ··· 1413 1397 struct list_head list; 1414 1398 struct scsi_cmnd *scmd; 1415 1399 struct megasas_instance *instance; 1416 - u32 frame_count; 1400 + union { 1401 + struct { 1402 + u16 smid; 1403 + u16 resvd; 1404 + } context; 1405 + u32 frame_count; 1406 + }; 1417 1407 }; 1418 1408 1419 1409 #define MAX_MGMT_ADAPTERS 1024
+260 -102
drivers/scsi/megaraid/megaraid_sas_base.c
··· 53 53 #include <scsi/scsi_cmnd.h> 54 54 #include <scsi/scsi_device.h> 55 55 #include <scsi/scsi_host.h> 56 + #include "megaraid_sas_fusion.h" 56 57 #include "megaraid_sas.h" 57 58 58 59 /* ··· 82 81 MODULE_AUTHOR("megaraidlinux@lsi.com"); 83 82 MODULE_DESCRIPTION("LSI MegaRAID SAS Driver"); 84 83 85 - static int megasas_transition_to_ready(struct megasas_instance *instance); 84 + int megasas_transition_to_ready(struct megasas_instance *instance); 86 85 static int megasas_get_pd_list(struct megasas_instance *instance); 87 86 static int megasas_issue_init_mfi(struct megasas_instance *instance); 88 87 static int megasas_register_aen(struct megasas_instance *instance, ··· 110 109 /* xscale IOP, vega */ 111 110 {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, 112 111 /* xscale IOP */ 112 + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_FUSION)}, 113 + /* Fusion */ 113 114 {} 114 115 }; 115 116 ··· 125 122 static int megasas_poll_wait_aen; 126 123 static DECLARE_WAIT_QUEUE_HEAD(megasas_poll_wait); 127 124 static u32 support_poll_for_event; 128 - static u32 megasas_dbg_lvl; 125 + u32 megasas_dbg_lvl; 129 126 static u32 support_device_change; 130 127 131 128 /* define lock for aen poll */ 132 129 spinlock_t poll_aen_lock; 133 130 134 - static void 131 + void 135 132 megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, 136 133 u8 alt_status); 134 + 137 135 static irqreturn_t megasas_isr(int irq, void *devp); 138 136 static u32 139 137 megasas_init_adapter_mfi(struct megasas_instance *instance); ··· 142 138 megasas_build_and_issue_cmd(struct megasas_instance *instance, 143 139 struct scsi_cmnd *scmd); 144 140 static void megasas_complete_cmd_dpc(unsigned long instance_addr); 141 + void 142 + megasas_release_fusion(struct megasas_instance *instance); 143 + int 144 + megasas_ioc_init_fusion(struct megasas_instance *instance); 145 + void 146 + megasas_free_cmds_fusion(struct megasas_instance *instance); 147 + u8 148 + megasas_get_map_info(struct megasas_instance *instance); 149 + int 150 + megasas_sync_map_info(struct megasas_instance *instance); 151 + int 152 + wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd); 153 + void megasas_reset_reply_desc(struct megasas_instance *instance); 154 + u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map, 155 + struct LD_LOAD_BALANCE_INFO *lbInfo); 156 + int megasas_reset_fusion(struct Scsi_Host *shost); 157 + void megasas_fusion_ocr_wq(struct work_struct *work); 145 158 146 159 void 147 160 megasas_issue_dcmd(struct megasas_instance *instance, struct megasas_cmd *cmd) ··· 173 152 * 174 153 * Returns a free command from the pool 175 154 */ 176 - static struct megasas_cmd *megasas_get_cmd(struct megasas_instance 155 + struct megasas_cmd *megasas_get_cmd(struct megasas_instance 177 156 *instance) 178 157 { 179 158 unsigned long flags; ··· 198 177 * @instance: Adapter soft state 199 178 * @cmd: Command packet to be returned to free command pool 200 179 */ 201 - static inline void 180 + inline void 202 181 megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) 203 182 { 204 183 unsigned long flags; ··· 206 185 spin_lock_irqsave(&instance->cmd_pool_lock, flags); 207 186 208 187 cmd->scmd = NULL; 188 + cmd->frame_count = 0; 209 189 list_add_tail(&cmd->list, &instance->cmd_pool); 210 190 211 191 spin_unlock_irqrestore(&instance->cmd_pool_lock, flags); ··· 818 796 * specific to gen2 (deviceid : 0x78, 0x79) controllers 819 797 */ 820 798 799 + /* 800 + * Template added for TB (Fusion) 801 + */ 802 + extern struct megasas_instance_template megasas_instance_template_fusion; 803 + 821 804 /** 822 805 * megasas_issue_polled - Issues a polling command 823 806 * @instance: Adapter soft state ··· 830 803 * 831 804 * For polling, MFI requires the cmd_status to be set to 0xFF before posting. 832 805 */ 833 - static int 806 + int 834 807 megasas_issue_polled(struct megasas_instance *instance, struct megasas_cmd *cmd) 835 808 { 836 - int i; 837 - u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000; 838 809 839 810 struct megasas_header *frame_hdr = &cmd->frame->hdr; 840 811 ··· 842 817 /* 843 818 * Issue the frame using inbound queue port 844 819 */ 845 - instance->instancet->fire_cmd(instance, 846 - cmd->frame_phys_addr, 0, instance->reg_set); 820 + instance->instancet->issue_dcmd(instance, cmd); 847 821 848 822 /* 849 823 * Wait for cmd_status to change 850 824 */ 851 - for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i++) { 852 - rmb(); 853 - msleep(1); 854 - } 855 - 856 - if (frame_hdr->cmd_status == 0xff) 857 - return -ETIME; 858 - 859 - return 0; 825 + return wait_and_poll(instance, cmd); 860 826 } 861 827 862 828 /** ··· 865 849 { 866 850 cmd->cmd_status = ENODATA; 867 851 868 - instance->instancet->fire_cmd(instance, 869 - cmd->frame_phys_addr, 0, instance->reg_set); 852 + instance->instancet->issue_dcmd(instance, cmd); 870 853 871 854 wait_event(instance->int_cmd_wait_q, cmd->cmd_status != ENODATA); 872 855 ··· 909 894 cmd->sync_cmd = 1; 910 895 cmd->cmd_status = 0xFF; 911 896 912 - instance->instancet->fire_cmd(instance, 913 - cmd->frame_phys_addr, 0, instance->reg_set); 897 + instance->instancet->issue_dcmd(instance, cmd); 914 898 915 899 /* 916 900 * Wait for this cmd to complete ··· 1305 1291 * Called by megasas_queue_command to find out if the command to be queued 1306 1292 * is a logical drive command 1307 1293 */ 1308 - static inline int megasas_is_ldio(struct scsi_cmnd *cmd) 1294 + inline int megasas_is_ldio(struct scsi_cmnd *cmd) 1309 1295 { 1310 1296 if (!MEGASAS_IS_LOGICAL(cmd)) 1311 1297 return 0; ··· 1565 1551 return 0; 1566 1552 } 1567 1553 1568 - static void megaraid_sas_kill_hba(struct megasas_instance *instance) 1554 + void megaraid_sas_kill_hba(struct megasas_instance *instance) 1569 1555 { 1570 1556 if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0073SKINNY) || 1571 - (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { 1572 - writel(MFI_STOP_ADP, 1573 - &instance->reg_set->reserved_0[0]); 1557 + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0071SKINNY) || 1558 + (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)) { 1559 + writel(MFI_STOP_ADP, &instance->reg_set->doorbell); 1574 1560 } else { 1575 - writel(MFI_STOP_ADP, 1576 - &instance->reg_set->inbound_doorbell); 1561 + writel(MFI_STOP_ADP, &instance->reg_set->inbound_doorbell); 1562 + } 1563 + } 1564 + 1565 + /** 1566 + * megasas_check_and_restore_queue_depth - Check if queue depth needs to be 1567 + * restored to max value 1568 + * @instance: Adapter soft state 1569 + * 1570 + */ 1571 + void 1572 + megasas_check_and_restore_queue_depth(struct megasas_instance *instance) 1573 + { 1574 + unsigned long flags; 1575 + if (instance->flag & MEGASAS_FW_BUSY 1576 + && time_after(jiffies, instance->last_time + 5 * HZ) 1577 + && atomic_read(&instance->fw_outstanding) < 17) { 1578 + 1579 + spin_lock_irqsave(instance->host->host_lock, flags); 1580 + instance->flag &= ~MEGASAS_FW_BUSY; 1581 + if ((instance->pdev->device == 1582 + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || 1583 + (instance->pdev->device == 1584 + PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { 1585 + instance->host->can_queue = 1586 + instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; 1587 + } else 1588 + instance->host->can_queue = 1589 + instance->max_fw_cmds - MEGASAS_INT_CMDS; 1590 + 1591 + spin_unlock_irqrestore(instance->host->host_lock, flags); 1577 1592 } 1578 1593 } 1579 1594 ··· 1656 1613 /* 1657 1614 * Check if we can restore can_queue 1658 1615 */ 1659 - if (instance->flag & MEGASAS_FW_BUSY 1660 - && time_after(jiffies, instance->last_time + 5 * HZ) 1661 - && atomic_read(&instance->fw_outstanding) < 17) { 1662 - 1663 - spin_lock_irqsave(instance->host->host_lock, flags); 1664 - instance->flag &= ~MEGASAS_FW_BUSY; 1665 - if ((instance->pdev->device == 1666 - PCI_DEVICE_ID_LSI_SAS0073SKINNY) || 1667 - (instance->pdev->device == 1668 - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { 1669 - instance->host->can_queue = 1670 - instance->max_fw_cmds - MEGASAS_SKINNY_INT_CMDS; 1671 - } else 1672 - instance->host->can_queue = 1673 - instance->max_fw_cmds - MEGASAS_INT_CMDS; 1674 - 1675 - spin_unlock_irqrestore(instance->host->host_lock, flags); 1676 - } 1616 + megasas_check_and_restore_queue_depth(instance); 1677 1617 } 1678 1618 1679 1619 static void ··· 1834 1808 (instance->pdev->device == 1835 1809 PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { 1836 1810 writel(MFI_STOP_ADP, 1837 - &instance->reg_set->reserved_0[0]); 1811 + &instance->reg_set->doorbell); 1838 1812 } else { 1839 1813 writel(MFI_STOP_ADP, 1840 1814 &instance->reg_set->inbound_doorbell); ··· 1938 1912 static int megasas_reset_bus_host(struct scsi_cmnd *scmd) 1939 1913 { 1940 1914 int ret; 1915 + struct megasas_instance *instance; 1916 + instance = (struct megasas_instance *)scmd->device->host->hostdata; 1941 1917 1942 1918 /* 1943 1919 * First wait for all commands to complete 1944 1920 */ 1945 - ret = megasas_generic_reset(scmd); 1921 + if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) 1922 + ret = megasas_reset_fusion(scmd->device->host); 1923 + else 1924 + ret = megasas_generic_reset(scmd); 1946 1925 1947 1926 return ret; 1948 1927 } ··· 2117 2086 * an alternate status (as in the case of aborted 2118 2087 * commands) 2119 2088 */ 2120 - static void 2089 + void 2121 2090 megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd, 2122 2091 u8 alt_status) 2123 2092 { 2124 2093 int exception = 0; 2125 2094 struct megasas_header *hdr = &cmd->frame->hdr; 2126 2095 unsigned long flags; 2096 + struct fusion_context *fusion = instance->ctrl_context; 2127 2097 2128 2098 /* flag for the retry reset */ 2129 2099 cmd->retry_for_fw_reset = 0; ··· 2217 2185 case MFI_CMD_SMP: 2218 2186 case MFI_CMD_STP: 2219 2187 case MFI_CMD_DCMD: 2188 + /* Check for LD map update */ 2189 + if ((cmd->frame->dcmd.opcode == MR_DCMD_LD_MAP_GET_INFO) && 2190 + (cmd->frame->dcmd.mbox.b[1] == 1)) { 2191 + spin_lock_irqsave(instance->host->host_lock, flags); 2192 + if (cmd->frame->hdr.cmd_status != 0) { 2193 + if (cmd->frame->hdr.cmd_status != 2194 + MFI_STAT_NOT_FOUND) 2195 + printk(KERN_WARNING "megasas: map sync" 2196 + "failed, status = 0x%x.\n", 2197 + cmd->frame->hdr.cmd_status); 2198 + else { 2199 + megasas_return_cmd(instance, cmd); 2200 + spin_unlock_irqrestore( 2201 + instance->host->host_lock, 2202 + flags); 2203 + break; 2204 + } 2205 + } else 2206 + instance->map_id++; 2207 + megasas_return_cmd(instance, cmd); 2208 + if (MR_ValidateMapInfo( 2209 + fusion->ld_map[(instance->map_id & 1)], 2210 + fusion->load_balance_info)) 2211 + fusion->fast_path_io = 1; 2212 + else 2213 + fusion->fast_path_io = 0; 2214 + megasas_sync_map_info(instance); 2215 + spin_unlock_irqrestore(instance->host->host_lock, 2216 + flags); 2217 + break; 2218 + } 2220 2219 if (cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET_INFO || 2221 2220 cmd->frame->dcmd.opcode == MR_DCMD_CTRL_EVENT_GET) { 2222 2221 spin_lock_irqsave(&poll_aen_lock, flags); ··· 2586 2523 * states, driver must take steps to bring it to ready state. Otherwise, it 2587 2524 * has to wait for the ready state. 2588 2525 */ 2589 - static int 2526 + int 2590 2527 megasas_transition_to_ready(struct megasas_instance* instance) 2591 2528 { 2592 2529 int i; ··· 2620 2557 if ((instance->pdev->device == 2621 2558 PCI_DEVICE_ID_LSI_SAS0073SKINNY) || 2622 2559 (instance->pdev->device == 2623 - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { 2624 - 2560 + PCI_DEVICE_ID_LSI_SAS0071SKINNY) || 2561 + (instance->pdev->device == 2562 + PCI_DEVICE_ID_LSI_FUSION)) { 2625 2563 writel( 2626 2564 MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, 2627 - &instance->reg_set->reserved_0[0]); 2565 + &instance->reg_set->doorbell); 2628 2566 } else { 2629 2567 writel( 2630 2568 MFI_INIT_CLEAR_HANDSHAKE|MFI_INIT_HOTPLUG, ··· 2638 2574 2639 2575 case MFI_STATE_BOOT_MESSAGE_PENDING: 2640 2576 if ((instance->pdev->device == 2641 - PCI_DEVICE_ID_LSI_SAS0073SKINNY) || 2642 - (instance->pdev->device == 2643 - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { 2577 + PCI_DEVICE_ID_LSI_SAS0073SKINNY) || 2578 + (instance->pdev->device == 2579 + PCI_DEVICE_ID_LSI_SAS0071SKINNY) || 2580 + (instance->pdev->device == 2581 + PCI_DEVICE_ID_LSI_FUSION)) { 2644 2582 writel(MFI_INIT_HOTPLUG, 2645 - &instance->reg_set->reserved_0[0]); 2583 + &instance->reg_set->doorbell); 2646 2584 } else 2647 2585 writel(MFI_INIT_HOTPLUG, 2648 2586 &instance->reg_set->inbound_doorbell); ··· 2661 2595 if ((instance->pdev->device == 2662 2596 PCI_DEVICE_ID_LSI_SAS0073SKINNY) || 2663 2597 (instance->pdev->device == 2664 - PCI_DEVICE_ID_LSI_SAS0071SKINNY)) { 2598 + PCI_DEVICE_ID_LSI_SAS0071SKINNY) || 2599 + (instance->pdev->device 2600 + == PCI_DEVICE_ID_LSI_FUSION)) { 2665 2601 writel(MFI_RESET_FLAGS, 2666 - &instance->reg_set->reserved_0[0]); 2602 + &instance->reg_set->doorbell); 2603 + if (instance->pdev->device == 2604 + PCI_DEVICE_ID_LSI_FUSION) { 2605 + for (i = 0; i < (10 * 1000); i += 20) { 2606 + if (readl( 2607 + &instance-> 2608 + reg_set-> 2609 + doorbell) & 1) 2610 + msleep(20); 2611 + else 2612 + break; 2613 + } 2614 + } 2667 2615 } else 2668 2616 writel(MFI_RESET_FLAGS, 2669 2617 &instance->reg_set->inbound_doorbell); ··· 2761 2681 static void megasas_teardown_frame_pool(struct megasas_instance *instance) 2762 2682 { 2763 2683 int i; 2764 - u32 max_cmd = instance->max_fw_cmds; 2684 + u32 max_cmd = instance->max_mfi_cmds; 2765 2685 struct megasas_cmd *cmd; 2766 2686 2767 2687 if (!instance->frame_dma_pool) ··· 2812 2732 u32 frame_count; 2813 2733 struct megasas_cmd *cmd; 2814 2734 2815 - max_cmd = instance->max_fw_cmds; 2735 + max_cmd = instance->max_mfi_cmds; 2816 2736 2817 2737 /* 2818 2738 * Size of our frame is 64 bytes for MFI frame, followed by max SG ··· 2899 2819 * megasas_free_cmds - Free all the cmds in the free cmd pool 2900 2820 * @instance: Adapter soft state 2901 2821 */ 2902 - static void megasas_free_cmds(struct megasas_instance *instance) 2822 + void megasas_free_cmds(struct megasas_instance *instance) 2903 2823 { 2904 2824 int i; 2905 2825 /* First free the MFI frame pool */ 2906 2826 megasas_teardown_frame_pool(instance); 2907 2827 2908 2828 /* Free all the commands in the cmd_list */ 2909 - for (i = 0; i < instance->max_fw_cmds; i++) 2829 + for (i = 0; i < instance->max_mfi_cmds; i++) 2830 + 2910 2831 kfree(instance->cmd_list[i]); 2911 2832 2912 2833 /* Free the cmd_list buffer itself */ ··· 2935 2854 * This array is used only to look up the megasas_cmd given the context. The 2936 2855 * free commands themselves are maintained in a linked list called cmd_pool. 2937 2856 */ 2938 - static int megasas_alloc_cmds(struct megasas_instance *instance) 2857 + int megasas_alloc_cmds(struct megasas_instance *instance) 2939 2858 { 2940 2859 int i; 2941 2860 int j; 2942 2861 u32 max_cmd; 2943 2862 struct megasas_cmd *cmd; 2944 2863 2945 - max_cmd = instance->max_fw_cmds; 2864 + max_cmd = instance->max_mfi_cmds; 2946 2865 2947 2866 /* 2948 2867 * instance->cmd_list is an array of struct megasas_cmd pointers. ··· 2956 2875 return -ENOMEM; 2957 2876 } 2958 2877 2878 + memset(instance->cmd_list, 0, sizeof(struct megasas_cmd *) *max_cmd); 2959 2879 2960 2880 for (i = 0; i < max_cmd; i++) { 2961 2881 instance->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd), ··· 3370 3288 * does not exceed max cmds that the FW can support 3371 3289 */ 3372 3290 instance->max_fw_cmds = instance->max_fw_cmds-1; 3291 + instance->max_mfi_cmds = instance->max_fw_cmds; 3373 3292 instance->max_num_sge = (instance->instancet->read_fw_status_reg(reg_set) & 0xFF0000) >> 3374 3293 0x10; 3375 3294 /* ··· 3464 3381 reg_set = instance->reg_set; 3465 3382 3466 3383 switch (instance->pdev->device) { 3384 + case PCI_DEVICE_ID_LSI_FUSION: 3385 + instance->instancet = &megasas_instance_template_fusion; 3386 + break; 3467 3387 case PCI_DEVICE_ID_LSI_SAS1078R: 3468 3388 case PCI_DEVICE_ID_LSI_SAS1078DE: 3469 3389 instance->instancet = &megasas_instance_template_ppc; ··· 3568 3482 */ 3569 3483 static void megasas_release_mfi(struct megasas_instance *instance) 3570 3484 { 3571 - u32 reply_q_sz = sizeof(u32) * (instance->max_fw_cmds + 1); 3485 + u32 reply_q_sz = sizeof(u32) *(instance->max_mfi_cmds + 1); 3572 3486 3573 - pci_free_consistent(instance->pdev, reply_q_sz, 3487 + if (instance->reply_queue) 3488 + pci_free_consistent(instance->pdev, reply_q_sz, 3574 3489 instance->reply_queue, instance->reply_queue_h); 3575 3490 3576 3491 megasas_free_cmds(instance); ··· 3765 3678 /* 3766 3679 * Issue the aen registration frame 3767 3680 */ 3768 - instance->instancet->fire_cmd(instance, 3769 - cmd->frame_phys_addr, 0, instance->reg_set); 3681 + instance->instancet->issue_dcmd(instance, cmd); 3770 3682 3771 3683 return 0; 3772 3684 } ··· 3842 3756 } 3843 3757 3844 3758 host->max_sectors = instance->max_sectors_per_req; 3845 - host->cmd_per_lun = 128; 3759 + host->cmd_per_lun = MEGASAS_DEFAULT_CMD_PER_LUN; 3846 3760 host->max_channel = MEGASAS_MAX_CHANNELS - 1; 3847 3761 host->max_id = MEGASAS_MAX_DEV_PER_CHANNEL; 3848 3762 host->max_lun = MEGASAS_MAX_LUN; 3849 3763 host->max_cmd_len = 16; 3764 + 3765 + /* Fusion only supports host reset */ 3766 + if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) { 3767 + host->hostt->eh_device_reset_handler = NULL; 3768 + host->hostt->eh_bus_reset_handler = NULL; 3769 + } 3850 3770 3851 3771 /* 3852 3772 * Notify the mid-layer about the new controller ··· 3938 3846 instance = (struct megasas_instance *)host->hostdata; 3939 3847 memset(instance, 0, sizeof(*instance)); 3940 3848 atomic_set( &instance->fw_reset_no_pci_access, 0 ); 3849 + instance->pdev = pdev; 3941 3850 3942 - instance->producer = pci_alloc_consistent(pdev, sizeof(u32), 3943 - &instance->producer_h); 3944 - instance->consumer = pci_alloc_consistent(pdev, sizeof(u32), 3945 - &instance->consumer_h); 3851 + switch (instance->pdev->device) { 3852 + case PCI_DEVICE_ID_LSI_FUSION: 3853 + { 3854 + struct fusion_context *fusion; 3946 3855 3947 - if (!instance->producer || !instance->consumer) { 3948 - printk(KERN_DEBUG "megasas: Failed to allocate memory for " 3949 - "producer, consumer\n"); 3950 - goto fail_alloc_dma_buf; 3856 + instance->ctrl_context = 3857 + kzalloc(sizeof(struct fusion_context), GFP_KERNEL); 3858 + if (!instance->ctrl_context) { 3859 + printk(KERN_DEBUG "megasas: Failed to allocate " 3860 + "memory for Fusion context info\n"); 3861 + goto fail_alloc_dma_buf; 3862 + } 3863 + fusion = instance->ctrl_context; 3864 + INIT_LIST_HEAD(&fusion->cmd_pool); 3865 + spin_lock_init(&fusion->cmd_pool_lock); 3866 + } 3867 + break; 3868 + default: /* For all other supported controllers */ 3869 + 3870 + instance->producer = 3871 + pci_alloc_consistent(pdev, sizeof(u32), 3872 + &instance->producer_h); 3873 + instance->consumer = 3874 + pci_alloc_consistent(pdev, sizeof(u32), 3875 + &instance->consumer_h); 3876 + 3877 + if (!instance->producer || !instance->consumer) { 3878 + printk(KERN_DEBUG "megasas: Failed to allocate" 3879 + "memory for producer, consumer\n"); 3880 + goto fail_alloc_dma_buf; 3881 + } 3882 + 3883 + *instance->producer = 0; 3884 + *instance->consumer = 0; 3885 + break; 3951 3886 } 3952 3887 3953 - *instance->producer = 0; 3954 - *instance->consumer = 0; 3955 3888 megasas_poll_wait_aen = 0; 3956 3889 instance->flag_ieee = 0; 3957 3890 instance->ev = NULL; ··· 4012 3895 spin_lock_init(&poll_aen_lock); 4013 3896 4014 3897 mutex_init(&instance->aen_mutex); 3898 + mutex_init(&instance->reset_mutex); 4015 3899 4016 3900 /* 4017 3901 * Initialize PCI related and misc parameters 4018 3902 */ 4019 - instance->pdev = pdev; 4020 3903 instance->host = host; 4021 3904 instance->unique_id = pdev->bus->number << 8 | pdev->devfn; 4022 3905 instance->init_id = MEGASAS_DEFAULT_INIT_ID; ··· 4034 3917 instance->last_time = 0; 4035 3918 instance->disableOnlineCtrlReset = 1; 4036 3919 4037 - INIT_WORK(&instance->work_init, process_fw_state_change_wq); 3920 + if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION) 3921 + INIT_WORK(&instance->work_init, megasas_fusion_ocr_wq); 3922 + else 3923 + INIT_WORK(&instance->work_init, process_fw_state_change_wq); 4038 3924 4039 3925 /* 4040 3926 * Initialize MFI Firmware ··· 4120 4000 pci_free_consistent(pdev, sizeof(u32), instance->producer, 4121 4001 instance->producer_h); 4122 4002 megasas_release_mfi(instance); 4003 + } else { 4004 + megasas_release_fusion(instance); 4123 4005 } 4124 4006 if (instance->consumer) 4125 4007 pci_free_consistent(pdev, sizeof(u32), instance->consumer, ··· 4194 4072 4195 4073 if (instance->aen_cmd) 4196 4074 megasas_issue_blocked_abort_cmd(instance, instance->aen_cmd); 4197 - 4075 + if (instance->map_update_cmd) 4076 + megasas_issue_blocked_abort_cmd(instance, 4077 + instance->map_update_cmd); 4198 4078 dcmd = &cmd->frame->dcmd; 4199 4079 4200 4080 memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); ··· 4301 4177 * Initialize MFI Firmware 4302 4178 */ 4303 4179 4304 - *instance->producer = 0; 4305 - *instance->consumer = 0; 4306 - 4307 4180 atomic_set(&instance->fw_outstanding, 0); 4308 4181 4309 4182 /* ··· 4309 4188 if (megasas_transition_to_ready(instance)) 4310 4189 goto fail_ready_state; 4311 4190 4312 - if (megasas_issue_init_mfi(instance)) 4313 - goto fail_init_mfi; 4191 + switch (instance->pdev->device) { 4192 + case PCI_DEVICE_ID_LSI_FUSION: 4193 + { 4194 + megasas_reset_reply_desc(instance); 4195 + if (megasas_ioc_init_fusion(instance)) { 4196 + megasas_free_cmds(instance); 4197 + megasas_free_cmds_fusion(instance); 4198 + goto fail_init_mfi; 4199 + } 4200 + if (!megasas_get_map_info(instance)) 4201 + megasas_sync_map_info(instance); 4202 + } 4203 + break; 4204 + default: 4205 + *instance->producer = 0; 4206 + *instance->consumer = 0; 4207 + if (megasas_issue_init_mfi(instance)) 4208 + goto fail_init_mfi; 4209 + break; 4210 + } 4314 4211 4315 - tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc, 4316 - (unsigned long)instance); 4212 + tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet, 4213 + (unsigned long)instance); 4317 4214 4318 4215 /* Now re-enable MSI-X */ 4319 4216 if (instance->msi_flag) ··· 4400 4261 int i; 4401 4262 struct Scsi_Host *host; 4402 4263 struct megasas_instance *instance; 4264 + struct fusion_context *fusion; 4403 4265 4404 4266 instance = pci_get_drvdata(pdev); 4405 4267 instance->unload = 1; 4406 4268 host = instance->host; 4269 + fusion = instance->ctrl_context; 4407 4270 4408 4271 if (poll_mode_io) 4409 4272 del_timer_sync(&instance->io_completion_timer); ··· 4447 4306 if (instance->msi_flag) 4448 4307 pci_disable_msix(instance->pdev); 4449 4308 4450 - megasas_release_mfi(instance); 4451 - 4452 - pci_free_consistent(pdev, sizeof(struct megasas_evt_detail), 4453 - instance->evt_detail, instance->evt_detail_h); 4454 - 4455 - pci_free_consistent(pdev, sizeof(u32), instance->producer, 4456 - instance->producer_h); 4457 - 4458 - pci_free_consistent(pdev, sizeof(u32), instance->consumer, 4459 - instance->consumer_h); 4309 + switch (instance->pdev->device) { 4310 + case PCI_DEVICE_ID_LSI_FUSION: 4311 + megasas_release_fusion(instance); 4312 + for (i = 0; i < 2 ; i++) 4313 + if (fusion->ld_map[i]) 4314 + dma_free_coherent(&instance->pdev->dev, 4315 + fusion->map_sz, 4316 + fusion->ld_map[i], 4317 + fusion-> 4318 + ld_map_phys[i]); 4319 + kfree(instance->ctrl_context); 4320 + break; 4321 + default: 4322 + megasas_release_mfi(instance); 4323 + pci_free_consistent(pdev, 4324 + sizeof(struct megasas_evt_detail), 4325 + instance->evt_detail, 4326 + instance->evt_detail_h); 4327 + pci_free_consistent(pdev, sizeof(u32), 4328 + instance->producer, 4329 + instance->producer_h); 4330 + pci_free_consistent(pdev, sizeof(u32), 4331 + instance->consumer, 4332 + instance->consumer_h); 4333 + break; 4334 + } 4460 4335 4461 4336 scsi_host_put(host); 4462 4337 ··· 5236 5079 break; 5237 5080 case MR_EVT_CTRL_HOST_BUS_SCAN_REQUESTED: 5238 5081 case MR_EVT_FOREIGN_CFG_IMPORTED: 5082 + case MR_EVT_LD_STATE_CHANGE: 5239 5083 doscan = 1; 5240 5084 break; 5241 5085 default:
+516
drivers/scsi/megaraid/megaraid_sas_fp.c
··· 1 + /* 2 + * Linux MegaRAID driver for SAS based RAID controllers 3 + * 4 + * Copyright (c) 2009-2011 LSI Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 2 9 + * of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 + * 20 + * FILE: megaraid_sas_fp.c 21 + * 22 + * Authors: LSI Corporation 23 + * Sumant Patro 24 + * Varad Talamacki 25 + * Manoj Jose 26 + * 27 + * Send feedback to: <megaraidlinux@lsi.com> 28 + * 29 + * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035 30 + * ATTN: Linuxraid 31 + */ 32 + 33 + #include <linux/kernel.h> 34 + #include <linux/types.h> 35 + #include <linux/pci.h> 36 + #include <linux/list.h> 37 + #include <linux/moduleparam.h> 38 + #include <linux/module.h> 39 + #include <linux/spinlock.h> 40 + #include <linux/interrupt.h> 41 + #include <linux/delay.h> 42 + #include <linux/smp_lock.h> 43 + #include <linux/uio.h> 44 + #include <linux/uaccess.h> 45 + #include <linux/fs.h> 46 + #include <linux/compat.h> 47 + #include <linux/blkdev.h> 48 + #include <linux/poll.h> 49 + 50 + #include <scsi/scsi.h> 51 + #include <scsi/scsi_cmnd.h> 52 + #include <scsi/scsi_device.h> 53 + #include <scsi/scsi_host.h> 54 + 55 + #include "megaraid_sas_fusion.h" 56 + #include <asm/div64.h> 57 + 58 + #define ABS_DIFF(a, b) (((a) > (b)) ? ((a) - (b)) : ((b) - (a))) 59 + #define MR_LD_STATE_OPTIMAL 3 60 + #define FALSE 0 61 + #define TRUE 1 62 + 63 + /* Prototypes */ 64 + void 65 + mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map, 66 + struct LD_LOAD_BALANCE_INFO *lbInfo); 67 + 68 + u32 mega_mod64(u64 dividend, u32 divisor) 69 + { 70 + u64 d; 71 + u32 remainder; 72 + 73 + if (!divisor) 74 + printk(KERN_ERR "megasas : DIVISOR is zero, in div fn\n"); 75 + d = dividend; 76 + remainder = do_div(d, divisor); 77 + return remainder; 78 + } 79 + 80 + /** 81 + * @param dividend : Dividend 82 + * @param divisor : Divisor 83 + * 84 + * @return quotient 85 + **/ 86 + u64 mega_div64_32(uint64_t dividend, uint32_t divisor) 87 + { 88 + u32 remainder; 89 + u64 d; 90 + 91 + if (!divisor) 92 + printk(KERN_ERR "megasas : DIVISOR is zero in mod fn\n"); 93 + 94 + d = dividend; 95 + remainder = do_div(d, divisor); 96 + 97 + return d; 98 + } 99 + 100 + struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map) 101 + { 102 + return &map->raidMap.ldSpanMap[ld].ldRaid; 103 + } 104 + 105 + static struct MR_SPAN_BLOCK_INFO *MR_LdSpanInfoGet(u32 ld, 106 + struct MR_FW_RAID_MAP_ALL 107 + *map) 108 + { 109 + return &map->raidMap.ldSpanMap[ld].spanBlock[0]; 110 + } 111 + 112 + static u8 MR_LdDataArmGet(u32 ld, u32 armIdx, struct MR_FW_RAID_MAP_ALL *map) 113 + { 114 + return map->raidMap.ldSpanMap[ld].dataArmMap[armIdx]; 115 + } 116 + 117 + static u16 MR_ArPdGet(u32 ar, u32 arm, struct MR_FW_RAID_MAP_ALL *map) 118 + { 119 + return map->raidMap.arMapInfo[ar].pd[arm]; 120 + } 121 + 122 + static u16 MR_LdSpanArrayGet(u32 ld, u32 span, struct MR_FW_RAID_MAP_ALL *map) 123 + { 124 + return map->raidMap.ldSpanMap[ld].spanBlock[span].span.arrayRef; 125 + } 126 + 127 + static u16 MR_PdDevHandleGet(u32 pd, struct MR_FW_RAID_MAP_ALL *map) 128 + { 129 + return map->raidMap.devHndlInfo[pd].curDevHdl; 130 + } 131 + 132 + u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map) 133 + { 134 + return map->raidMap.ldSpanMap[ld].ldRaid.targetId; 135 + } 136 + 137 + u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map) 138 + { 139 + return map->raidMap.ldTgtIdToLd[ldTgtId]; 140 + } 141 + 142 + static struct MR_LD_SPAN *MR_LdSpanPtrGet(u32 ld, u32 span, 143 + struct MR_FW_RAID_MAP_ALL *map) 144 + { 145 + return &map->raidMap.ldSpanMap[ld].spanBlock[span].span; 146 + } 147 + 148 + /* 149 + * This function will validate Map info data provided by FW 150 + */ 151 + u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map, 152 + struct LD_LOAD_BALANCE_INFO *lbInfo) 153 + { 154 + struct MR_FW_RAID_MAP *pFwRaidMap = &map->raidMap; 155 + 156 + if (pFwRaidMap->totalSize != 157 + (sizeof(struct MR_FW_RAID_MAP) -sizeof(struct MR_LD_SPAN_MAP) + 158 + (sizeof(struct MR_LD_SPAN_MAP) *pFwRaidMap->ldCount))) { 159 + printk(KERN_ERR "megasas: map info structure size 0x%x is not matching with ld count\n", 160 + (unsigned int)((sizeof(struct MR_FW_RAID_MAP) - 161 + sizeof(struct MR_LD_SPAN_MAP)) + 162 + (sizeof(struct MR_LD_SPAN_MAP) * 163 + pFwRaidMap->ldCount))); 164 + printk(KERN_ERR "megasas: span map %x, pFwRaidMap->totalSize " 165 + ": %x\n", (unsigned int)sizeof(struct MR_LD_SPAN_MAP), 166 + pFwRaidMap->totalSize); 167 + return 0; 168 + } 169 + 170 + mr_update_load_balance_params(map, lbInfo); 171 + 172 + return 1; 173 + } 174 + 175 + u32 MR_GetSpanBlock(u32 ld, u64 row, u64 *span_blk, 176 + struct MR_FW_RAID_MAP_ALL *map, int *div_error) 177 + { 178 + struct MR_SPAN_BLOCK_INFO *pSpanBlock = MR_LdSpanInfoGet(ld, map); 179 + struct MR_QUAD_ELEMENT *quad; 180 + struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 181 + u32 span, j; 182 + 183 + for (span = 0; span < raid->spanDepth; span++, pSpanBlock++) { 184 + 185 + for (j = 0; j < pSpanBlock->block_span_info.noElements; j++) { 186 + quad = &pSpanBlock->block_span_info.quad[j]; 187 + 188 + if (quad->diff == 0) { 189 + *div_error = 1; 190 + return span; 191 + } 192 + if (quad->logStart <= row && row <= quad->logEnd && 193 + (mega_mod64(row-quad->logStart, quad->diff)) == 0) { 194 + if (span_blk != NULL) { 195 + u64 blk, debugBlk; 196 + blk = 197 + mega_div64_32( 198 + (row-quad->logStart), 199 + quad->diff); 200 + debugBlk = blk; 201 + 202 + blk = (blk + quad->offsetInSpan) << 203 + raid->stripeShift; 204 + *span_blk = blk; 205 + } 206 + return span; 207 + } 208 + } 209 + } 210 + return span; 211 + } 212 + 213 + /* 214 + ****************************************************************************** 215 + * 216 + * This routine calculates the arm, span and block for the specified stripe and 217 + * reference in stripe. 218 + * 219 + * Inputs : 220 + * 221 + * ld - Logical drive number 222 + * stripRow - Stripe number 223 + * stripRef - Reference in stripe 224 + * 225 + * Outputs : 226 + * 227 + * span - Span number 228 + * block - Absolute Block number in the physical disk 229 + */ 230 + u8 MR_GetPhyParams(u32 ld, u64 stripRow, u16 stripRef, u64 *pdBlock, 231 + u16 *pDevHandle, struct RAID_CONTEXT *pRAID_Context, 232 + struct MR_FW_RAID_MAP_ALL *map) 233 + { 234 + struct MR_LD_RAID *raid = MR_LdRaidGet(ld, map); 235 + u32 pd, arRef; 236 + u8 physArm, span; 237 + u64 row; 238 + u8 retval = TRUE; 239 + int error_code = 0; 240 + 241 + row = mega_div64_32(stripRow, raid->rowDataSize); 242 + 243 + if (raid->level == 6) { 244 + /* logical arm within row */ 245 + u32 logArm = mega_mod64(stripRow, raid->rowDataSize); 246 + u32 rowMod, armQ, arm; 247 + 248 + if (raid->rowSize == 0) 249 + return FALSE; 250 + /* get logical row mod */ 251 + rowMod = mega_mod64(row, raid->rowSize); 252 + armQ = raid->rowSize-1-rowMod; /* index of Q drive */ 253 + arm = armQ+1+logArm; /* data always logically follows Q */ 254 + if (arm >= raid->rowSize) /* handle wrap condition */ 255 + arm -= raid->rowSize; 256 + physArm = (u8)arm; 257 + } else { 258 + if (raid->modFactor == 0) 259 + return FALSE; 260 + physArm = MR_LdDataArmGet(ld, mega_mod64(stripRow, 261 + raid->modFactor), 262 + map); 263 + } 264 + 265 + if (raid->spanDepth == 1) { 266 + span = 0; 267 + *pdBlock = row << raid->stripeShift; 268 + } else { 269 + span = (u8)MR_GetSpanBlock(ld, row, pdBlock, map, &error_code); 270 + if (error_code == 1) 271 + return FALSE; 272 + } 273 + 274 + /* Get the array on which this span is present */ 275 + arRef = MR_LdSpanArrayGet(ld, span, map); 276 + pd = MR_ArPdGet(arRef, physArm, map); /* Get the pd */ 277 + 278 + if (pd != MR_PD_INVALID) 279 + /* Get dev handle from Pd. */ 280 + *pDevHandle = MR_PdDevHandleGet(pd, map); 281 + else { 282 + *pDevHandle = MR_PD_INVALID; /* set dev handle as invalid. */ 283 + if (raid->level >= 5) 284 + pRAID_Context->regLockFlags = REGION_TYPE_EXCLUSIVE; 285 + else if (raid->level == 1) { 286 + /* Get alternate Pd. */ 287 + pd = MR_ArPdGet(arRef, physArm + 1, map); 288 + if (pd != MR_PD_INVALID) 289 + /* Get dev handle from Pd */ 290 + *pDevHandle = MR_PdDevHandleGet(pd, map); 291 + } 292 + retval = FALSE; 293 + } 294 + 295 + *pdBlock += stripRef + MR_LdSpanPtrGet(ld, span, map)->startBlk; 296 + pRAID_Context->spanArm = (span << RAID_CTX_SPANARM_SPAN_SHIFT) | 297 + physArm; 298 + return retval; 299 + } 300 + 301 + /* 302 + ****************************************************************************** 303 + * 304 + * MR_BuildRaidContext function 305 + * 306 + * This function will initiate command processing. The start/end row and strip 307 + * information is calculated then the lock is acquired. 308 + * This function will return 0 if region lock was acquired OR return num strips 309 + */ 310 + u8 311 + MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info, 312 + struct RAID_CONTEXT *pRAID_Context, 313 + struct MR_FW_RAID_MAP_ALL *map) 314 + { 315 + struct MR_LD_RAID *raid; 316 + u32 ld, stripSize, stripe_mask; 317 + u64 endLba, endStrip, endRow, start_row, start_strip; 318 + u64 regStart; 319 + u32 regSize; 320 + u8 num_strips, numRows; 321 + u16 ref_in_start_stripe, ref_in_end_stripe; 322 + u64 ldStartBlock; 323 + u32 numBlocks, ldTgtId; 324 + u8 isRead; 325 + u8 retval = 0; 326 + 327 + ldStartBlock = io_info->ldStartBlock; 328 + numBlocks = io_info->numBlocks; 329 + ldTgtId = io_info->ldTgtId; 330 + isRead = io_info->isRead; 331 + 332 + ld = MR_TargetIdToLdGet(ldTgtId, map); 333 + raid = MR_LdRaidGet(ld, map); 334 + 335 + stripSize = 1 << raid->stripeShift; 336 + stripe_mask = stripSize-1; 337 + /* 338 + * calculate starting row and stripe, and number of strips and rows 339 + */ 340 + start_strip = ldStartBlock >> raid->stripeShift; 341 + ref_in_start_stripe = (u16)(ldStartBlock & stripe_mask); 342 + endLba = ldStartBlock + numBlocks - 1; 343 + ref_in_end_stripe = (u16)(endLba & stripe_mask); 344 + endStrip = endLba >> raid->stripeShift; 345 + num_strips = (u8)(endStrip - start_strip + 1); /* End strip */ 346 + if (raid->rowDataSize == 0) 347 + return FALSE; 348 + start_row = mega_div64_32(start_strip, raid->rowDataSize); 349 + endRow = mega_div64_32(endStrip, raid->rowDataSize); 350 + numRows = (u8)(endRow - start_row + 1); 351 + 352 + /* 353 + * calculate region info. 354 + */ 355 + 356 + /* assume region is at the start of the first row */ 357 + regStart = start_row << raid->stripeShift; 358 + /* assume this IO needs the full row - we'll adjust if not true */ 359 + regSize = stripSize; 360 + 361 + /* If IO spans more than 1 strip, fp is not possible 362 + FP is not possible for writes on non-0 raid levels 363 + FP is not possible if LD is not capable */ 364 + if (num_strips > 1 || (!isRead && raid->level != 0) || 365 + !raid->capability.fpCapable) { 366 + io_info->fpOkForIo = FALSE; 367 + } else { 368 + io_info->fpOkForIo = TRUE; 369 + } 370 + 371 + if (numRows == 1) { 372 + /* single-strip IOs can always lock only the data needed */ 373 + if (num_strips == 1) { 374 + regStart += ref_in_start_stripe; 375 + regSize = numBlocks; 376 + } 377 + /* multi-strip IOs always need to full stripe locked */ 378 + } else { 379 + if (start_strip == (start_row + 1) * raid->rowDataSize - 1) { 380 + /* If the start strip is the last in the start row */ 381 + regStart += ref_in_start_stripe; 382 + regSize = stripSize - ref_in_start_stripe; 383 + /* initialize count to sectors from startref to end 384 + of strip */ 385 + } 386 + 387 + if (numRows > 2) 388 + /* Add complete rows in the middle of the transfer */ 389 + regSize += (numRows-2) << raid->stripeShift; 390 + 391 + /* if IO ends within first strip of last row */ 392 + if (endStrip == endRow*raid->rowDataSize) 393 + regSize += ref_in_end_stripe+1; 394 + else 395 + regSize += stripSize; 396 + } 397 + 398 + pRAID_Context->timeoutValue = map->raidMap.fpPdIoTimeoutSec; 399 + pRAID_Context->regLockFlags = (isRead) ? REGION_TYPE_SHARED_READ : 400 + raid->regTypeReqOnWrite; 401 + pRAID_Context->VirtualDiskTgtId = raid->targetId; 402 + pRAID_Context->regLockRowLBA = regStart; 403 + pRAID_Context->regLockLength = regSize; 404 + pRAID_Context->configSeqNum = raid->seqNum; 405 + 406 + /*Get Phy Params only if FP capable, or else leave it to MR firmware 407 + to do the calculation.*/ 408 + if (io_info->fpOkForIo) { 409 + retval = MR_GetPhyParams(ld, start_strip, ref_in_start_stripe, 410 + &io_info->pdBlock, 411 + &io_info->devHandle, pRAID_Context, 412 + map); 413 + /* If IO on an invalid Pd, then FP i snot possible */ 414 + if (io_info->devHandle == MR_PD_INVALID) 415 + io_info->fpOkForIo = FALSE; 416 + return retval; 417 + } else if (isRead) { 418 + uint stripIdx; 419 + for (stripIdx = 0; stripIdx < num_strips; stripIdx++) { 420 + if (!MR_GetPhyParams(ld, start_strip + stripIdx, 421 + ref_in_start_stripe, 422 + &io_info->pdBlock, 423 + &io_info->devHandle, 424 + pRAID_Context, map)) 425 + return TRUE; 426 + } 427 + } 428 + return TRUE; 429 + } 430 + 431 + void 432 + mr_update_load_balance_params(struct MR_FW_RAID_MAP_ALL *map, 433 + struct LD_LOAD_BALANCE_INFO *lbInfo) 434 + { 435 + int ldCount; 436 + u16 ld; 437 + struct MR_LD_RAID *raid; 438 + 439 + for (ldCount = 0; ldCount < MAX_LOGICAL_DRIVES; ldCount++) { 440 + ld = MR_TargetIdToLdGet(ldCount, map); 441 + if (ld >= MAX_LOGICAL_DRIVES) { 442 + lbInfo[ldCount].loadBalanceFlag = 0; 443 + continue; 444 + } 445 + 446 + raid = MR_LdRaidGet(ld, map); 447 + 448 + /* Two drive Optimal RAID 1 */ 449 + if ((raid->level == 1) && (raid->rowSize == 2) && 450 + (raid->spanDepth == 1) && raid->ldState == 451 + MR_LD_STATE_OPTIMAL) { 452 + u32 pd, arRef; 453 + 454 + lbInfo[ldCount].loadBalanceFlag = 1; 455 + 456 + /* Get the array on which this span is present */ 457 + arRef = MR_LdSpanArrayGet(ld, 0, map); 458 + 459 + /* Get the Pd */ 460 + pd = MR_ArPdGet(arRef, 0, map); 461 + /* Get dev handle from Pd */ 462 + lbInfo[ldCount].raid1DevHandle[0] = 463 + MR_PdDevHandleGet(pd, map); 464 + /* Get the Pd */ 465 + pd = MR_ArPdGet(arRef, 1, map); 466 + 467 + /* Get the dev handle from Pd */ 468 + lbInfo[ldCount].raid1DevHandle[1] = 469 + MR_PdDevHandleGet(pd, map); 470 + } else 471 + lbInfo[ldCount].loadBalanceFlag = 0; 472 + } 473 + } 474 + 475 + u8 megasas_get_best_arm(struct LD_LOAD_BALANCE_INFO *lbInfo, u8 arm, u64 block, 476 + u32 count) 477 + { 478 + u16 pend0, pend1; 479 + u64 diff0, diff1; 480 + u8 bestArm; 481 + 482 + /* get the pending cmds for the data and mirror arms */ 483 + pend0 = atomic_read(&lbInfo->scsi_pending_cmds[0]); 484 + pend1 = atomic_read(&lbInfo->scsi_pending_cmds[1]); 485 + 486 + /* Determine the disk whose head is nearer to the req. block */ 487 + diff0 = ABS_DIFF(block, lbInfo->last_accessed_block[0]); 488 + diff1 = ABS_DIFF(block, lbInfo->last_accessed_block[1]); 489 + bestArm = (diff0 <= diff1 ? 0 : 1); 490 + 491 + if ((bestArm == arm && pend0 > pend1 + 16) || 492 + (bestArm != arm && pend1 > pend0 + 16)) 493 + bestArm ^= 1; 494 + 495 + /* Update the last accessed block on the correct pd */ 496 + lbInfo->last_accessed_block[bestArm] = block + count - 1; 497 + 498 + return bestArm; 499 + } 500 + 501 + u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo, 502 + struct IO_REQUEST_INFO *io_info) 503 + { 504 + u8 arm, old_arm; 505 + u16 devHandle; 506 + 507 + old_arm = lbInfo->raid1DevHandle[0] == io_info->devHandle ? 0 : 1; 508 + 509 + /* get best new arm */ 510 + arm = megasas_get_best_arm(lbInfo, old_arm, io_info->ldStartBlock, 511 + io_info->numBlocks); 512 + devHandle = lbInfo->raid1DevHandle[arm]; 513 + atomic_inc(&lbInfo->scsi_pending_cmds[arm]); 514 + 515 + return devHandle; 516 + }
+2248
drivers/scsi/megaraid/megaraid_sas_fusion.c
··· 1 + /* 2 + * Linux MegaRAID driver for SAS based RAID controllers 3 + * 4 + * Copyright (c) 2009-2011 LSI Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 2 9 + * of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 + * 20 + * FILE: megaraid_sas_fusion.c 21 + * 22 + * Authors: LSI Corporation 23 + * Sumant Patro 24 + * Adam Radford <linuxraid@lsi.com> 25 + * 26 + * Send feedback to: <megaraidlinux@lsi.com> 27 + * 28 + * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035 29 + * ATTN: Linuxraid 30 + */ 31 + 32 + #include <linux/kernel.h> 33 + #include <linux/types.h> 34 + #include <linux/pci.h> 35 + #include <linux/list.h> 36 + #include <linux/moduleparam.h> 37 + #include <linux/module.h> 38 + #include <linux/spinlock.h> 39 + #include <linux/interrupt.h> 40 + #include <linux/delay.h> 41 + #include <linux/smp_lock.h> 42 + #include <linux/uio.h> 43 + #include <linux/uaccess.h> 44 + #include <linux/fs.h> 45 + #include <linux/compat.h> 46 + #include <linux/blkdev.h> 47 + #include <linux/mutex.h> 48 + #include <linux/poll.h> 49 + 50 + #include <scsi/scsi.h> 51 + #include <scsi/scsi_cmnd.h> 52 + #include <scsi/scsi_device.h> 53 + #include <scsi/scsi_host.h> 54 + 55 + #include "megaraid_sas_fusion.h" 56 + #include "megaraid_sas.h" 57 + 58 + extern void megasas_free_cmds(struct megasas_instance *instance); 59 + extern struct megasas_cmd *megasas_get_cmd(struct megasas_instance 60 + *instance); 61 + extern void 62 + megasas_complete_cmd(struct megasas_instance *instance, 63 + struct megasas_cmd *cmd, u8 alt_status); 64 + int megasas_is_ldio(struct scsi_cmnd *cmd); 65 + int 66 + wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd); 67 + 68 + void 69 + megasas_return_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd); 70 + int megasas_alloc_cmds(struct megasas_instance *instance); 71 + int 72 + megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs); 73 + int 74 + megasas_issue_polled(struct megasas_instance *instance, 75 + struct megasas_cmd *cmd); 76 + 77 + u8 78 + MR_BuildRaidContext(struct IO_REQUEST_INFO *io_info, 79 + struct RAID_CONTEXT *pRAID_Context, 80 + struct MR_FW_RAID_MAP_ALL *map); 81 + u16 MR_TargetIdToLdGet(u32 ldTgtId, struct MR_FW_RAID_MAP_ALL *map); 82 + struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map); 83 + 84 + u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map); 85 + u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map, 86 + struct LD_LOAD_BALANCE_INFO *lbInfo); 87 + u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo, 88 + struct IO_REQUEST_INFO *in_info); 89 + int megasas_transition_to_ready(struct megasas_instance *instance); 90 + void megaraid_sas_kill_hba(struct megasas_instance *instance); 91 + 92 + extern u32 megasas_dbg_lvl; 93 + 94 + /** 95 + * megasas_enable_intr_fusion - Enables interrupts 96 + * @regs: MFI register set 97 + */ 98 + void 99 + megasas_enable_intr_fusion(struct megasas_register_set __iomem *regs) 100 + { 101 + writel(~MFI_FUSION_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); 102 + 103 + /* Dummy readl to force pci flush */ 104 + readl(&regs->outbound_intr_mask); 105 + } 106 + 107 + /** 108 + * megasas_disable_intr_fusion - Disables interrupt 109 + * @regs: MFI register set 110 + */ 111 + void 112 + megasas_disable_intr_fusion(struct megasas_register_set __iomem *regs) 113 + { 114 + u32 mask = 0xFFFFFFFF; 115 + u32 status; 116 + 117 + writel(mask, &regs->outbound_intr_mask); 118 + /* Dummy readl to force pci flush */ 119 + status = readl(&regs->outbound_intr_mask); 120 + } 121 + 122 + int 123 + megasas_clear_intr_fusion(struct megasas_register_set __iomem *regs) 124 + { 125 + u32 status; 126 + /* 127 + * Check if it is our interrupt 128 + */ 129 + status = readl(&regs->outbound_intr_status); 130 + 131 + if (status & 1) { 132 + writel(status, &regs->outbound_intr_status); 133 + readl(&regs->outbound_intr_status); 134 + return 1; 135 + } 136 + if (!(status & MFI_FUSION_ENABLE_INTERRUPT_MASK)) 137 + return 0; 138 + 139 + /* 140 + * dummy read to flush PCI 141 + */ 142 + readl(&regs->outbound_intr_status); 143 + 144 + return 1; 145 + } 146 + 147 + /** 148 + * megasas_get_cmd_fusion - Get a command from the free pool 149 + * @instance: Adapter soft state 150 + * 151 + * Returns a free command from the pool 152 + */ 153 + struct megasas_cmd_fusion *megasas_get_cmd_fusion(struct megasas_instance 154 + *instance) 155 + { 156 + unsigned long flags; 157 + struct fusion_context *fusion = 158 + (struct fusion_context *)instance->ctrl_context; 159 + struct megasas_cmd_fusion *cmd = NULL; 160 + 161 + spin_lock_irqsave(&fusion->cmd_pool_lock, flags); 162 + 163 + if (!list_empty(&fusion->cmd_pool)) { 164 + cmd = list_entry((&fusion->cmd_pool)->next, 165 + struct megasas_cmd_fusion, list); 166 + list_del_init(&cmd->list); 167 + } else { 168 + printk(KERN_ERR "megasas: Command pool (fusion) empty!\n"); 169 + } 170 + 171 + spin_unlock_irqrestore(&fusion->cmd_pool_lock, flags); 172 + return cmd; 173 + } 174 + 175 + /** 176 + * megasas_return_cmd_fusion - Return a cmd to free command pool 177 + * @instance: Adapter soft state 178 + * @cmd: Command packet to be returned to free command pool 179 + */ 180 + static inline void 181 + megasas_return_cmd_fusion(struct megasas_instance *instance, 182 + struct megasas_cmd_fusion *cmd) 183 + { 184 + unsigned long flags; 185 + struct fusion_context *fusion = 186 + (struct fusion_context *)instance->ctrl_context; 187 + 188 + spin_lock_irqsave(&fusion->cmd_pool_lock, flags); 189 + 190 + cmd->scmd = NULL; 191 + cmd->sync_cmd_idx = (u32)ULONG_MAX; 192 + list_add_tail(&cmd->list, &fusion->cmd_pool); 193 + 194 + spin_unlock_irqrestore(&fusion->cmd_pool_lock, flags); 195 + } 196 + 197 + /** 198 + * megasas_teardown_frame_pool_fusion - Destroy the cmd frame DMA pool 199 + * @instance: Adapter soft state 200 + */ 201 + static void megasas_teardown_frame_pool_fusion( 202 + struct megasas_instance *instance) 203 + { 204 + int i; 205 + struct fusion_context *fusion = instance->ctrl_context; 206 + 207 + u16 max_cmd = instance->max_fw_cmds; 208 + 209 + struct megasas_cmd_fusion *cmd; 210 + 211 + if (!fusion->sg_dma_pool || !fusion->sense_dma_pool) { 212 + printk(KERN_ERR "megasas: dma pool is null. SG Pool %p, " 213 + "sense pool : %p\n", fusion->sg_dma_pool, 214 + fusion->sense_dma_pool); 215 + return; 216 + } 217 + 218 + /* 219 + * Return all frames to pool 220 + */ 221 + for (i = 0; i < max_cmd; i++) { 222 + 223 + cmd = fusion->cmd_list[i]; 224 + 225 + if (cmd->sg_frame) 226 + pci_pool_free(fusion->sg_dma_pool, cmd->sg_frame, 227 + cmd->sg_frame_phys_addr); 228 + 229 + if (cmd->sense) 230 + pci_pool_free(fusion->sense_dma_pool, cmd->sense, 231 + cmd->sense_phys_addr); 232 + } 233 + 234 + /* 235 + * Now destroy the pool itself 236 + */ 237 + pci_pool_destroy(fusion->sg_dma_pool); 238 + pci_pool_destroy(fusion->sense_dma_pool); 239 + 240 + fusion->sg_dma_pool = NULL; 241 + fusion->sense_dma_pool = NULL; 242 + } 243 + 244 + /** 245 + * megasas_free_cmds_fusion - Free all the cmds in the free cmd pool 246 + * @instance: Adapter soft state 247 + */ 248 + void 249 + megasas_free_cmds_fusion(struct megasas_instance *instance) 250 + { 251 + int i; 252 + struct fusion_context *fusion = instance->ctrl_context; 253 + 254 + u32 max_cmds, req_sz, reply_sz, io_frames_sz; 255 + 256 + 257 + req_sz = fusion->request_alloc_sz; 258 + reply_sz = fusion->reply_alloc_sz; 259 + io_frames_sz = fusion->io_frames_alloc_sz; 260 + 261 + max_cmds = instance->max_fw_cmds; 262 + 263 + /* Free descriptors and request Frames memory */ 264 + if (fusion->req_frames_desc) 265 + dma_free_coherent(&instance->pdev->dev, req_sz, 266 + fusion->req_frames_desc, 267 + fusion->req_frames_desc_phys); 268 + 269 + if (fusion->reply_frames_desc) { 270 + pci_pool_free(fusion->reply_frames_desc_pool, 271 + fusion->reply_frames_desc, 272 + fusion->reply_frames_desc_phys); 273 + pci_pool_destroy(fusion->reply_frames_desc_pool); 274 + } 275 + 276 + if (fusion->io_request_frames) { 277 + pci_pool_free(fusion->io_request_frames_pool, 278 + fusion->io_request_frames, 279 + fusion->io_request_frames_phys); 280 + pci_pool_destroy(fusion->io_request_frames_pool); 281 + } 282 + 283 + /* Free the Fusion frame pool */ 284 + megasas_teardown_frame_pool_fusion(instance); 285 + 286 + /* Free all the commands in the cmd_list */ 287 + for (i = 0; i < max_cmds; i++) 288 + kfree(fusion->cmd_list[i]); 289 + 290 + /* Free the cmd_list buffer itself */ 291 + kfree(fusion->cmd_list); 292 + fusion->cmd_list = NULL; 293 + 294 + INIT_LIST_HEAD(&fusion->cmd_pool); 295 + } 296 + 297 + /** 298 + * megasas_create_frame_pool_fusion - Creates DMA pool for cmd frames 299 + * @instance: Adapter soft state 300 + * 301 + */ 302 + static int megasas_create_frame_pool_fusion(struct megasas_instance *instance) 303 + { 304 + int i; 305 + u32 max_cmd; 306 + struct fusion_context *fusion; 307 + struct megasas_cmd_fusion *cmd; 308 + u32 total_sz_chain_frame; 309 + 310 + fusion = instance->ctrl_context; 311 + max_cmd = instance->max_fw_cmds; 312 + 313 + total_sz_chain_frame = MEGASAS_MAX_SZ_CHAIN_FRAME; 314 + 315 + /* 316 + * Use DMA pool facility provided by PCI layer 317 + */ 318 + 319 + fusion->sg_dma_pool = pci_pool_create("megasas sg pool fusion", 320 + instance->pdev, 321 + total_sz_chain_frame, 4, 322 + 0); 323 + if (!fusion->sg_dma_pool) { 324 + printk(KERN_DEBUG "megasas: failed to setup request pool " 325 + "fusion\n"); 326 + return -ENOMEM; 327 + } 328 + fusion->sense_dma_pool = pci_pool_create("megasas sense pool fusion", 329 + instance->pdev, 330 + SCSI_SENSE_BUFFERSIZE, 64, 0); 331 + 332 + if (!fusion->sense_dma_pool) { 333 + printk(KERN_DEBUG "megasas: failed to setup sense pool " 334 + "fusion\n"); 335 + pci_pool_destroy(fusion->sg_dma_pool); 336 + fusion->sg_dma_pool = NULL; 337 + return -ENOMEM; 338 + } 339 + 340 + /* 341 + * Allocate and attach a frame to each of the commands in cmd_list 342 + */ 343 + for (i = 0; i < max_cmd; i++) { 344 + 345 + cmd = fusion->cmd_list[i]; 346 + 347 + cmd->sg_frame = pci_pool_alloc(fusion->sg_dma_pool, 348 + GFP_KERNEL, 349 + &cmd->sg_frame_phys_addr); 350 + 351 + cmd->sense = pci_pool_alloc(fusion->sense_dma_pool, 352 + GFP_KERNEL, &cmd->sense_phys_addr); 353 + /* 354 + * megasas_teardown_frame_pool_fusion() takes care of freeing 355 + * whatever has been allocated 356 + */ 357 + if (!cmd->sg_frame || !cmd->sense) { 358 + printk(KERN_DEBUG "megasas: pci_pool_alloc failed\n"); 359 + megasas_teardown_frame_pool_fusion(instance); 360 + return -ENOMEM; 361 + } 362 + } 363 + return 0; 364 + } 365 + 366 + /** 367 + * megasas_alloc_cmds_fusion - Allocates the command packets 368 + * @instance: Adapter soft state 369 + * 370 + * 371 + * Each frame has a 32-bit field called context. This context is used to get 372 + * back the megasas_cmd_fusion from the frame when a frame gets completed 373 + * In this driver, the 32 bit values are the indices into an array cmd_list. 374 + * This array is used only to look up the megasas_cmd_fusion given the context. 375 + * The free commands themselves are maintained in a linked list called cmd_pool. 376 + * 377 + * cmds are formed in the io_request and sg_frame members of the 378 + * megasas_cmd_fusion. The context field is used to get a request descriptor 379 + * and is used as SMID of the cmd. 380 + * SMID value range is from 1 to max_fw_cmds. 381 + */ 382 + int 383 + megasas_alloc_cmds_fusion(struct megasas_instance *instance) 384 + { 385 + int i, j; 386 + u32 max_cmd, io_frames_sz; 387 + struct fusion_context *fusion; 388 + struct megasas_cmd_fusion *cmd; 389 + union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc; 390 + u32 offset; 391 + dma_addr_t io_req_base_phys; 392 + u8 *io_req_base; 393 + 394 + fusion = instance->ctrl_context; 395 + 396 + max_cmd = instance->max_fw_cmds; 397 + 398 + fusion->req_frames_desc = 399 + dma_alloc_coherent(&instance->pdev->dev, 400 + fusion->request_alloc_sz, 401 + &fusion->req_frames_desc_phys, GFP_KERNEL); 402 + 403 + if (!fusion->req_frames_desc) { 404 + printk(KERN_ERR "megasas; Could not allocate memory for " 405 + "request_frames\n"); 406 + goto fail_req_desc; 407 + } 408 + 409 + fusion->reply_frames_desc_pool = 410 + pci_pool_create("reply_frames pool", instance->pdev, 411 + fusion->reply_alloc_sz, 16, 0); 412 + 413 + if (!fusion->reply_frames_desc_pool) { 414 + printk(KERN_ERR "megasas; Could not allocate memory for " 415 + "reply_frame pool\n"); 416 + goto fail_reply_desc; 417 + } 418 + 419 + fusion->reply_frames_desc = 420 + pci_pool_alloc(fusion->reply_frames_desc_pool, GFP_KERNEL, 421 + &fusion->reply_frames_desc_phys); 422 + if (!fusion->reply_frames_desc) { 423 + printk(KERN_ERR "megasas; Could not allocate memory for " 424 + "reply_frame pool\n"); 425 + pci_pool_destroy(fusion->reply_frames_desc_pool); 426 + goto fail_reply_desc; 427 + } 428 + 429 + reply_desc = fusion->reply_frames_desc; 430 + for (i = 0; i < fusion->reply_q_depth; i++, reply_desc++) 431 + reply_desc->Words = ULLONG_MAX; 432 + 433 + io_frames_sz = fusion->io_frames_alloc_sz; 434 + 435 + fusion->io_request_frames_pool = 436 + pci_pool_create("io_request_frames pool", instance->pdev, 437 + fusion->io_frames_alloc_sz, 16, 0); 438 + 439 + if (!fusion->io_request_frames_pool) { 440 + printk(KERN_ERR "megasas: Could not allocate memory for " 441 + "io_request_frame pool\n"); 442 + goto fail_io_frames; 443 + } 444 + 445 + fusion->io_request_frames = 446 + pci_pool_alloc(fusion->io_request_frames_pool, GFP_KERNEL, 447 + &fusion->io_request_frames_phys); 448 + if (!fusion->io_request_frames) { 449 + printk(KERN_ERR "megasas: Could not allocate memory for " 450 + "io_request_frames frames\n"); 451 + pci_pool_destroy(fusion->io_request_frames_pool); 452 + goto fail_io_frames; 453 + } 454 + 455 + /* 456 + * fusion->cmd_list is an array of struct megasas_cmd_fusion pointers. 457 + * Allocate the dynamic array first and then allocate individual 458 + * commands. 459 + */ 460 + fusion->cmd_list = kmalloc(sizeof(struct megasas_cmd_fusion *) 461 + *max_cmd, GFP_KERNEL); 462 + 463 + if (!fusion->cmd_list) { 464 + printk(KERN_DEBUG "megasas: out of memory. Could not alloc " 465 + "memory for cmd_list_fusion\n"); 466 + goto fail_cmd_list; 467 + } 468 + 469 + memset(fusion->cmd_list, 0, sizeof(struct megasas_cmd_fusion *) 470 + *max_cmd); 471 + 472 + max_cmd = instance->max_fw_cmds; 473 + for (i = 0; i < max_cmd; i++) { 474 + fusion->cmd_list[i] = kmalloc(sizeof(struct megasas_cmd_fusion), 475 + GFP_KERNEL); 476 + if (!fusion->cmd_list[i]) { 477 + printk(KERN_ERR "Could not alloc cmd list fusion\n"); 478 + 479 + for (j = 0; j < i; j++) 480 + kfree(fusion->cmd_list[j]); 481 + 482 + kfree(fusion->cmd_list); 483 + fusion->cmd_list = NULL; 484 + goto fail_cmd_list; 485 + } 486 + } 487 + 488 + /* The first 256 bytes (SMID 0) is not used. Don't add to cmd list */ 489 + io_req_base = fusion->io_request_frames + 490 + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE; 491 + io_req_base_phys = fusion->io_request_frames_phys + 492 + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE; 493 + 494 + /* 495 + * Add all the commands to command pool (fusion->cmd_pool) 496 + */ 497 + 498 + /* SMID 0 is reserved. Set SMID/index from 1 */ 499 + for (i = 0; i < max_cmd; i++) { 500 + cmd = fusion->cmd_list[i]; 501 + offset = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * i; 502 + memset(cmd, 0, sizeof(struct megasas_cmd_fusion)); 503 + cmd->index = i + 1; 504 + cmd->scmd = NULL; 505 + cmd->sync_cmd_idx = (u32)ULONG_MAX; /* Set to Invalid */ 506 + cmd->instance = instance; 507 + cmd->io_request = 508 + (struct MPI2_RAID_SCSI_IO_REQUEST *) 509 + (io_req_base + offset); 510 + memset(cmd->io_request, 0, 511 + sizeof(struct MPI2_RAID_SCSI_IO_REQUEST)); 512 + cmd->io_request_phys_addr = io_req_base_phys + offset; 513 + 514 + list_add_tail(&cmd->list, &fusion->cmd_pool); 515 + } 516 + 517 + /* 518 + * Create a frame pool and assign one frame to each cmd 519 + */ 520 + if (megasas_create_frame_pool_fusion(instance)) { 521 + printk(KERN_DEBUG "megasas: Error creating frame DMA pool\n"); 522 + megasas_free_cmds_fusion(instance); 523 + goto fail_req_desc; 524 + } 525 + 526 + return 0; 527 + 528 + fail_cmd_list: 529 + pci_pool_free(fusion->io_request_frames_pool, fusion->io_request_frames, 530 + fusion->io_request_frames_phys); 531 + pci_pool_destroy(fusion->io_request_frames_pool); 532 + fail_io_frames: 533 + dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz, 534 + fusion->reply_frames_desc, 535 + fusion->reply_frames_desc_phys); 536 + pci_pool_free(fusion->reply_frames_desc_pool, 537 + fusion->reply_frames_desc, 538 + fusion->reply_frames_desc_phys); 539 + pci_pool_destroy(fusion->reply_frames_desc_pool); 540 + 541 + fail_reply_desc: 542 + dma_free_coherent(&instance->pdev->dev, fusion->request_alloc_sz, 543 + fusion->req_frames_desc, 544 + fusion->req_frames_desc_phys); 545 + fail_req_desc: 546 + return -ENOMEM; 547 + } 548 + 549 + /** 550 + * wait_and_poll - Issues a polling command 551 + * @instance: Adapter soft state 552 + * @cmd: Command packet to be issued 553 + * 554 + * For polling, MFI requires the cmd_status to be set to 0xFF before posting. 555 + */ 556 + int 557 + wait_and_poll(struct megasas_instance *instance, struct megasas_cmd *cmd) 558 + { 559 + int i; 560 + struct megasas_header *frame_hdr = &cmd->frame->hdr; 561 + 562 + u32 msecs = MFI_POLL_TIMEOUT_SECS * 1000; 563 + 564 + /* 565 + * Wait for cmd_status to change 566 + */ 567 + for (i = 0; (i < msecs) && (frame_hdr->cmd_status == 0xff); i += 20) { 568 + rmb(); 569 + msleep(20); 570 + } 571 + 572 + if (frame_hdr->cmd_status == 0xff) 573 + return -ETIME; 574 + 575 + return 0; 576 + } 577 + 578 + /** 579 + * megasas_ioc_init_fusion - Initializes the FW 580 + * @instance: Adapter soft state 581 + * 582 + * Issues the IOC Init cmd 583 + */ 584 + int 585 + megasas_ioc_init_fusion(struct megasas_instance *instance) 586 + { 587 + struct megasas_init_frame *init_frame; 588 + struct MPI2_IOC_INIT_REQUEST *IOCInitMessage; 589 + dma_addr_t ioc_init_handle; 590 + u32 context; 591 + struct megasas_cmd *cmd; 592 + u8 ret; 593 + struct fusion_context *fusion; 594 + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; 595 + int i; 596 + struct megasas_header *frame_hdr; 597 + 598 + fusion = instance->ctrl_context; 599 + 600 + cmd = megasas_get_cmd(instance); 601 + 602 + if (!cmd) { 603 + printk(KERN_ERR "Could not allocate cmd for INIT Frame\n"); 604 + ret = 1; 605 + goto fail_get_cmd; 606 + } 607 + 608 + IOCInitMessage = 609 + dma_alloc_coherent(&instance->pdev->dev, 610 + sizeof(struct MPI2_IOC_INIT_REQUEST), 611 + &ioc_init_handle, GFP_KERNEL); 612 + 613 + if (!IOCInitMessage) { 614 + printk(KERN_ERR "Could not allocate memory for " 615 + "IOCInitMessage\n"); 616 + ret = 1; 617 + goto fail_fw_init; 618 + } 619 + 620 + memset(IOCInitMessage, 0, sizeof(struct MPI2_IOC_INIT_REQUEST)); 621 + 622 + IOCInitMessage->Function = MPI2_FUNCTION_IOC_INIT; 623 + IOCInitMessage->WhoInit = MPI2_WHOINIT_HOST_DRIVER; 624 + IOCInitMessage->MsgVersion = MPI2_VERSION; 625 + IOCInitMessage->HeaderVersion = MPI2_HEADER_VERSION; 626 + IOCInitMessage->SystemRequestFrameSize = 627 + MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE / 4; 628 + 629 + IOCInitMessage->ReplyDescriptorPostQueueDepth = fusion->reply_q_depth; 630 + IOCInitMessage->ReplyDescriptorPostQueueAddress = 631 + fusion->reply_frames_desc_phys; 632 + IOCInitMessage->SystemRequestFrameBaseAddress = 633 + fusion->io_request_frames_phys; 634 + 635 + init_frame = (struct megasas_init_frame *)cmd->frame; 636 + memset(init_frame, 0, MEGAMFI_FRAME_SIZE); 637 + 638 + frame_hdr = &cmd->frame->hdr; 639 + context = init_frame->context; 640 + init_frame->context = context; 641 + 642 + frame_hdr->cmd_status = 0xFF; 643 + frame_hdr->flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; 644 + 645 + init_frame->cmd = MFI_CMD_INIT; 646 + init_frame->cmd_status = 0xFF; 647 + 648 + init_frame->queue_info_new_phys_addr_lo = ioc_init_handle; 649 + init_frame->data_xfer_len = sizeof(struct MPI2_IOC_INIT_REQUEST); 650 + 651 + req_desc = 652 + (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)fusion->req_frames_desc; 653 + 654 + req_desc->Words = cmd->frame_phys_addr; 655 + req_desc->MFAIo.RequestFlags = 656 + (MEGASAS_REQ_DESCRIPT_FLAGS_MFA << 657 + MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 658 + 659 + /* 660 + * disable the intr before firing the init frame 661 + */ 662 + instance->instancet->disable_intr(instance->reg_set); 663 + 664 + for (i = 0; i < (10 * 1000); i += 20) { 665 + if (readl(&instance->reg_set->doorbell) & 1) 666 + msleep(20); 667 + else 668 + break; 669 + } 670 + 671 + instance->instancet->fire_cmd(instance, req_desc->u.low, 672 + req_desc->u.high, instance->reg_set); 673 + 674 + wait_and_poll(instance, cmd); 675 + 676 + frame_hdr = &cmd->frame->hdr; 677 + if (frame_hdr->cmd_status != 0) { 678 + ret = 1; 679 + goto fail_fw_init; 680 + } 681 + printk(KERN_ERR "megasas:IOC Init cmd success\n"); 682 + 683 + ret = 0; 684 + 685 + fail_fw_init: 686 + megasas_return_cmd(instance, cmd); 687 + if (IOCInitMessage) 688 + dma_free_coherent(&instance->pdev->dev, 689 + sizeof(struct MPI2_IOC_INIT_REQUEST), 690 + IOCInitMessage, ioc_init_handle); 691 + fail_get_cmd: 692 + return ret; 693 + } 694 + 695 + /* 696 + * megasas_return_cmd_for_smid - Returns a cmd_fusion for a SMID 697 + * @instance: Adapter soft state 698 + * 699 + */ 700 + void 701 + megasas_return_cmd_for_smid(struct megasas_instance *instance, u16 smid) 702 + { 703 + struct fusion_context *fusion; 704 + struct megasas_cmd_fusion *cmd; 705 + 706 + fusion = instance->ctrl_context; 707 + cmd = fusion->cmd_list[smid - 1]; 708 + megasas_return_cmd_fusion(instance, cmd); 709 + } 710 + 711 + /* 712 + * megasas_get_ld_map_info - Returns FW's ld_map structure 713 + * @instance: Adapter soft state 714 + * @pend: Pend the command or not 715 + * Issues an internal command (DCMD) to get the FW's controller PD 716 + * list structure. This information is mainly used to find out SYSTEM 717 + * supported by the FW. 718 + */ 719 + static int 720 + megasas_get_ld_map_info(struct megasas_instance *instance) 721 + { 722 + int ret = 0; 723 + struct megasas_cmd *cmd; 724 + struct megasas_dcmd_frame *dcmd; 725 + struct MR_FW_RAID_MAP_ALL *ci; 726 + dma_addr_t ci_h = 0; 727 + u32 size_map_info; 728 + struct fusion_context *fusion; 729 + 730 + cmd = megasas_get_cmd(instance); 731 + 732 + if (!cmd) { 733 + printk(KERN_DEBUG "megasas: Failed to get cmd for map info.\n"); 734 + return -ENOMEM; 735 + } 736 + 737 + fusion = instance->ctrl_context; 738 + 739 + if (!fusion) { 740 + megasas_return_cmd(instance, cmd); 741 + return 1; 742 + } 743 + 744 + dcmd = &cmd->frame->dcmd; 745 + 746 + size_map_info = sizeof(struct MR_FW_RAID_MAP) + 747 + (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1)); 748 + 749 + ci = fusion->ld_map[(instance->map_id & 1)]; 750 + ci_h = fusion->ld_map_phys[(instance->map_id & 1)]; 751 + 752 + if (!ci) { 753 + printk(KERN_DEBUG "Failed to alloc mem for ld_map_info\n"); 754 + megasas_return_cmd(instance, cmd); 755 + return -ENOMEM; 756 + } 757 + 758 + memset(ci, 0, sizeof(*ci)); 759 + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 760 + 761 + dcmd->cmd = MFI_CMD_DCMD; 762 + dcmd->cmd_status = 0xFF; 763 + dcmd->sge_count = 1; 764 + dcmd->flags = MFI_FRAME_DIR_READ; 765 + dcmd->timeout = 0; 766 + dcmd->pad_0 = 0; 767 + dcmd->data_xfer_len = size_map_info; 768 + dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO; 769 + dcmd->sgl.sge32[0].phys_addr = ci_h; 770 + dcmd->sgl.sge32[0].length = size_map_info; 771 + 772 + if (!megasas_issue_polled(instance, cmd)) 773 + ret = 0; 774 + else { 775 + printk(KERN_ERR "megasas: Get LD Map Info Failed\n"); 776 + ret = -1; 777 + } 778 + 779 + megasas_return_cmd(instance, cmd); 780 + 781 + return ret; 782 + } 783 + 784 + u8 785 + megasas_get_map_info(struct megasas_instance *instance) 786 + { 787 + struct fusion_context *fusion = instance->ctrl_context; 788 + 789 + fusion->fast_path_io = 0; 790 + if (!megasas_get_ld_map_info(instance)) { 791 + if (MR_ValidateMapInfo(fusion->ld_map[(instance->map_id & 1)], 792 + fusion->load_balance_info)) { 793 + fusion->fast_path_io = 1; 794 + return 0; 795 + } 796 + } 797 + return 1; 798 + } 799 + 800 + /* 801 + * megasas_sync_map_info - Returns FW's ld_map structure 802 + * @instance: Adapter soft state 803 + * 804 + * Issues an internal command (DCMD) to get the FW's controller PD 805 + * list structure. This information is mainly used to find out SYSTEM 806 + * supported by the FW. 807 + */ 808 + int 809 + megasas_sync_map_info(struct megasas_instance *instance) 810 + { 811 + int ret = 0, i; 812 + struct megasas_cmd *cmd; 813 + struct megasas_dcmd_frame *dcmd; 814 + u32 size_sync_info, num_lds; 815 + struct fusion_context *fusion; 816 + struct MR_LD_TARGET_SYNC *ci = NULL; 817 + struct MR_FW_RAID_MAP_ALL *map; 818 + struct MR_LD_RAID *raid; 819 + struct MR_LD_TARGET_SYNC *ld_sync; 820 + dma_addr_t ci_h = 0; 821 + u32 size_map_info; 822 + 823 + cmd = megasas_get_cmd(instance); 824 + 825 + if (!cmd) { 826 + printk(KERN_DEBUG "megasas: Failed to get cmd for sync" 827 + "info.\n"); 828 + return -ENOMEM; 829 + } 830 + 831 + fusion = instance->ctrl_context; 832 + 833 + if (!fusion) { 834 + megasas_return_cmd(instance, cmd); 835 + return 1; 836 + } 837 + 838 + map = fusion->ld_map[instance->map_id & 1]; 839 + 840 + num_lds = map->raidMap.ldCount; 841 + 842 + dcmd = &cmd->frame->dcmd; 843 + 844 + size_sync_info = sizeof(struct MR_LD_TARGET_SYNC) *num_lds; 845 + 846 + memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE); 847 + 848 + ci = (struct MR_LD_TARGET_SYNC *) 849 + fusion->ld_map[(instance->map_id - 1) & 1]; 850 + memset(ci, 0, sizeof(struct MR_FW_RAID_MAP_ALL)); 851 + 852 + ci_h = fusion->ld_map_phys[(instance->map_id - 1) & 1]; 853 + 854 + ld_sync = (struct MR_LD_TARGET_SYNC *)ci; 855 + 856 + for (i = 0; i < num_lds; i++, ld_sync++) { 857 + raid = MR_LdRaidGet(i, map); 858 + ld_sync->targetId = MR_GetLDTgtId(i, map); 859 + ld_sync->seqNum = raid->seqNum; 860 + } 861 + 862 + size_map_info = sizeof(struct MR_FW_RAID_MAP) + 863 + (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1)); 864 + 865 + dcmd->cmd = MFI_CMD_DCMD; 866 + dcmd->cmd_status = 0xFF; 867 + dcmd->sge_count = 1; 868 + dcmd->flags = MFI_FRAME_DIR_WRITE; 869 + dcmd->timeout = 0; 870 + dcmd->pad_0 = 0; 871 + dcmd->data_xfer_len = size_map_info; 872 + dcmd->mbox.b[0] = num_lds; 873 + dcmd->mbox.b[1] = MEGASAS_DCMD_MBOX_PEND_FLAG; 874 + dcmd->opcode = MR_DCMD_LD_MAP_GET_INFO; 875 + dcmd->sgl.sge32[0].phys_addr = ci_h; 876 + dcmd->sgl.sge32[0].length = size_map_info; 877 + 878 + instance->map_update_cmd = cmd; 879 + 880 + instance->instancet->issue_dcmd(instance, cmd); 881 + 882 + return ret; 883 + } 884 + 885 + /** 886 + * megasas_init_adapter_fusion - Initializes the FW 887 + * @instance: Adapter soft state 888 + * 889 + * This is the main function for initializing firmware. 890 + */ 891 + u32 892 + megasas_init_adapter_fusion(struct megasas_instance *instance) 893 + { 894 + struct megasas_register_set __iomem *reg_set; 895 + struct fusion_context *fusion; 896 + u32 max_cmd; 897 + int i = 0; 898 + 899 + fusion = instance->ctrl_context; 900 + 901 + reg_set = instance->reg_set; 902 + 903 + /* 904 + * Get various operational parameters from status register 905 + */ 906 + instance->max_fw_cmds = 907 + instance->instancet->read_fw_status_reg(reg_set) & 0x00FFFF; 908 + instance->max_fw_cmds = min(instance->max_fw_cmds, (u16)1008); 909 + 910 + /* 911 + * Reduce the max supported cmds by 1. This is to ensure that the 912 + * reply_q_sz (1 more than the max cmd that driver may send) 913 + * does not exceed max cmds that the FW can support 914 + */ 915 + instance->max_fw_cmds = instance->max_fw_cmds-1; 916 + /* Only internal cmds (DCMD) need to have MFI frames */ 917 + instance->max_mfi_cmds = MEGASAS_INT_CMDS; 918 + 919 + max_cmd = instance->max_fw_cmds; 920 + 921 + fusion->reply_q_depth = ((max_cmd + 1 + 15)/16)*16; 922 + 923 + fusion->request_alloc_sz = 924 + sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *max_cmd; 925 + fusion->reply_alloc_sz = sizeof(union MPI2_REPLY_DESCRIPTORS_UNION) 926 + *(fusion->reply_q_depth); 927 + fusion->io_frames_alloc_sz = MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE + 928 + (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE * 929 + (max_cmd + 1)); /* Extra 1 for SMID 0 */ 930 + 931 + fusion->max_sge_in_main_msg = 932 + (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - 933 + offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL))/16; 934 + 935 + fusion->max_sge_in_chain = 936 + MEGASAS_MAX_SZ_CHAIN_FRAME / sizeof(union MPI2_SGE_IO_UNION); 937 + 938 + instance->max_num_sge = fusion->max_sge_in_main_msg + 939 + fusion->max_sge_in_chain - 2; 940 + 941 + /* Used for pass thru MFI frame (DCMD) */ 942 + fusion->chain_offset_mfi_pthru = 943 + offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL)/16; 944 + 945 + fusion->chain_offset_io_request = 946 + (MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE - 947 + sizeof(union MPI2_SGE_IO_UNION))/16; 948 + 949 + fusion->last_reply_idx = 0; 950 + 951 + /* 952 + * Allocate memory for descriptors 953 + * Create a pool of commands 954 + */ 955 + if (megasas_alloc_cmds(instance)) 956 + goto fail_alloc_mfi_cmds; 957 + if (megasas_alloc_cmds_fusion(instance)) 958 + goto fail_alloc_cmds; 959 + 960 + if (megasas_ioc_init_fusion(instance)) 961 + goto fail_ioc_init; 962 + 963 + instance->flag_ieee = 1; 964 + 965 + fusion->map_sz = sizeof(struct MR_FW_RAID_MAP) + 966 + (sizeof(struct MR_LD_SPAN_MAP) *(MAX_LOGICAL_DRIVES - 1)); 967 + 968 + fusion->fast_path_io = 0; 969 + 970 + for (i = 0; i < 2; i++) { 971 + fusion->ld_map[i] = dma_alloc_coherent(&instance->pdev->dev, 972 + fusion->map_sz, 973 + &fusion->ld_map_phys[i], 974 + GFP_KERNEL); 975 + if (!fusion->ld_map[i]) { 976 + printk(KERN_ERR "megasas: Could not allocate memory " 977 + "for map info\n"); 978 + goto fail_map_info; 979 + } 980 + } 981 + 982 + if (!megasas_get_map_info(instance)) 983 + megasas_sync_map_info(instance); 984 + 985 + return 0; 986 + 987 + fail_alloc_cmds: 988 + fail_alloc_mfi_cmds: 989 + fail_map_info: 990 + if (i == 1) 991 + dma_free_coherent(&instance->pdev->dev, fusion->map_sz, 992 + fusion->ld_map[0], fusion->ld_map_phys[0]); 993 + fail_ioc_init: 994 + return 1; 995 + } 996 + 997 + /** 998 + * megasas_fire_cmd_fusion - Sends command to the FW 999 + * @frame_phys_addr : Physical address of cmd 1000 + * @frame_count : Number of frames for the command 1001 + * @regs : MFI register set 1002 + */ 1003 + void 1004 + megasas_fire_cmd_fusion(struct megasas_instance *instance, 1005 + dma_addr_t req_desc_lo, 1006 + u32 req_desc_hi, 1007 + struct megasas_register_set __iomem *regs) 1008 + { 1009 + unsigned long flags; 1010 + 1011 + spin_lock_irqsave(&instance->hba_lock, flags); 1012 + 1013 + writel(req_desc_lo, 1014 + &(regs)->inbound_low_queue_port); 1015 + writel(req_desc_hi, &(regs)->inbound_high_queue_port); 1016 + spin_unlock_irqrestore(&instance->hba_lock, flags); 1017 + } 1018 + 1019 + /** 1020 + * map_cmd_status - Maps FW cmd status to OS cmd status 1021 + * @cmd : Pointer to cmd 1022 + * @status : status of cmd returned by FW 1023 + * @ext_status : ext status of cmd returned by FW 1024 + */ 1025 + 1026 + void 1027 + map_cmd_status(struct megasas_cmd_fusion *cmd, u8 status, u8 ext_status) 1028 + { 1029 + 1030 + switch (status) { 1031 + 1032 + case MFI_STAT_OK: 1033 + cmd->scmd->result = DID_OK << 16; 1034 + break; 1035 + 1036 + case MFI_STAT_SCSI_IO_FAILED: 1037 + case MFI_STAT_LD_INIT_IN_PROGRESS: 1038 + cmd->scmd->result = (DID_ERROR << 16) | ext_status; 1039 + break; 1040 + 1041 + case MFI_STAT_SCSI_DONE_WITH_ERROR: 1042 + 1043 + cmd->scmd->result = (DID_OK << 16) | ext_status; 1044 + if (ext_status == SAM_STAT_CHECK_CONDITION) { 1045 + memset(cmd->scmd->sense_buffer, 0, 1046 + SCSI_SENSE_BUFFERSIZE); 1047 + memcpy(cmd->scmd->sense_buffer, cmd->sense, 1048 + SCSI_SENSE_BUFFERSIZE); 1049 + cmd->scmd->result |= DRIVER_SENSE << 24; 1050 + } 1051 + break; 1052 + 1053 + case MFI_STAT_LD_OFFLINE: 1054 + case MFI_STAT_DEVICE_NOT_FOUND: 1055 + cmd->scmd->result = DID_BAD_TARGET << 16; 1056 + break; 1057 + 1058 + default: 1059 + printk(KERN_DEBUG "megasas: FW status %#x\n", status); 1060 + cmd->scmd->result = DID_ERROR << 16; 1061 + break; 1062 + } 1063 + } 1064 + 1065 + /** 1066 + * megasas_make_sgl_fusion - Prepares 32-bit SGL 1067 + * @instance: Adapter soft state 1068 + * @scp: SCSI command from the mid-layer 1069 + * @sgl_ptr: SGL to be filled in 1070 + * @cmd: cmd we are working on 1071 + * 1072 + * If successful, this function returns the number of SG elements. 1073 + */ 1074 + static int 1075 + megasas_make_sgl_fusion(struct megasas_instance *instance, 1076 + struct scsi_cmnd *scp, 1077 + struct MPI25_IEEE_SGE_CHAIN64 *sgl_ptr, 1078 + struct megasas_cmd_fusion *cmd) 1079 + { 1080 + int i, sg_processed; 1081 + int sge_count, sge_idx; 1082 + struct scatterlist *os_sgl; 1083 + struct fusion_context *fusion; 1084 + 1085 + fusion = instance->ctrl_context; 1086 + 1087 + cmd->io_request->ChainOffset = 0; 1088 + 1089 + sge_count = scsi_dma_map(scp); 1090 + 1091 + BUG_ON(sge_count < 0); 1092 + 1093 + if (sge_count > instance->max_num_sge || !sge_count) 1094 + return sge_count; 1095 + 1096 + if (sge_count > fusion->max_sge_in_main_msg) { 1097 + /* One element to store the chain info */ 1098 + sge_idx = fusion->max_sge_in_main_msg - 1; 1099 + } else 1100 + sge_idx = sge_count; 1101 + 1102 + scsi_for_each_sg(scp, os_sgl, sge_count, i) { 1103 + sgl_ptr->Length = sg_dma_len(os_sgl); 1104 + sgl_ptr->Address = sg_dma_address(os_sgl); 1105 + sgl_ptr->Flags = 0; 1106 + sgl_ptr++; 1107 + 1108 + sg_processed = i + 1; 1109 + 1110 + if ((sg_processed == (fusion->max_sge_in_main_msg - 1)) && 1111 + (sge_count > fusion->max_sge_in_main_msg)) { 1112 + 1113 + struct MPI25_IEEE_SGE_CHAIN64 *sg_chain; 1114 + cmd->io_request->ChainOffset = 1115 + fusion->chain_offset_io_request; 1116 + sg_chain = sgl_ptr; 1117 + /* Prepare chain element */ 1118 + sg_chain->NextChainOffset = 0; 1119 + sg_chain->Flags = (IEEE_SGE_FLAGS_CHAIN_ELEMENT | 1120 + MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR); 1121 + sg_chain->Length = (sizeof(union MPI2_SGE_IO_UNION) 1122 + *(sge_count - sg_processed)); 1123 + sg_chain->Address = cmd->sg_frame_phys_addr; 1124 + 1125 + sgl_ptr = 1126 + (struct MPI25_IEEE_SGE_CHAIN64 *)cmd->sg_frame; 1127 + } 1128 + } 1129 + 1130 + return sge_count; 1131 + } 1132 + 1133 + /** 1134 + * megasas_set_pd_lba - Sets PD LBA 1135 + * @cdb: CDB 1136 + * @cdb_len: cdb length 1137 + * @start_blk: Start block of IO 1138 + * 1139 + * Used to set the PD LBA in CDB for FP IOs 1140 + */ 1141 + void 1142 + megasas_set_pd_lba(struct MPI2_RAID_SCSI_IO_REQUEST *io_request, u8 cdb_len, 1143 + struct IO_REQUEST_INFO *io_info, struct scsi_cmnd *scp, 1144 + struct MR_FW_RAID_MAP_ALL *local_map_ptr, u32 ref_tag) 1145 + { 1146 + struct MR_LD_RAID *raid; 1147 + u32 ld; 1148 + u64 start_blk = io_info->pdBlock; 1149 + u8 *cdb = io_request->CDB.CDB32; 1150 + u32 num_blocks = io_info->numBlocks; 1151 + u8 opcode, flagvals, groupnum, control; 1152 + 1153 + /* Check if T10 PI (DIF) is enabled for this LD */ 1154 + ld = MR_TargetIdToLdGet(io_info->ldTgtId, local_map_ptr); 1155 + raid = MR_LdRaidGet(ld, local_map_ptr); 1156 + if (raid->capability.ldPiMode == MR_PROT_INFO_TYPE_CONTROLLER) { 1157 + memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1158 + cdb[0] = MEGASAS_SCSI_VARIABLE_LENGTH_CMD; 1159 + cdb[7] = MEGASAS_SCSI_ADDL_CDB_LEN; 1160 + 1161 + if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) 1162 + cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_READ32; 1163 + else 1164 + cdb[9] = MEGASAS_SCSI_SERVICE_ACTION_WRITE32; 1165 + cdb[10] = MEGASAS_RD_WR_PROTECT_CHECK_ALL; 1166 + 1167 + /* LBA */ 1168 + cdb[12] = (u8)((start_blk >> 56) & 0xff); 1169 + cdb[13] = (u8)((start_blk >> 48) & 0xff); 1170 + cdb[14] = (u8)((start_blk >> 40) & 0xff); 1171 + cdb[15] = (u8)((start_blk >> 32) & 0xff); 1172 + cdb[16] = (u8)((start_blk >> 24) & 0xff); 1173 + cdb[17] = (u8)((start_blk >> 16) & 0xff); 1174 + cdb[18] = (u8)((start_blk >> 8) & 0xff); 1175 + cdb[19] = (u8)(start_blk & 0xff); 1176 + 1177 + /* Logical block reference tag */ 1178 + io_request->CDB.EEDP32.PrimaryReferenceTag = 1179 + cpu_to_be32(ref_tag); 1180 + io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0xffff; 1181 + 1182 + io_request->DataLength = num_blocks * 512; 1183 + io_request->IoFlags = 32; /* Specify 32-byte cdb */ 1184 + 1185 + /* Transfer length */ 1186 + cdb[28] = (u8)((num_blocks >> 24) & 0xff); 1187 + cdb[29] = (u8)((num_blocks >> 16) & 0xff); 1188 + cdb[30] = (u8)((num_blocks >> 8) & 0xff); 1189 + cdb[31] = (u8)(num_blocks & 0xff); 1190 + 1191 + /* set SCSI IO EEDPFlags */ 1192 + if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) { 1193 + io_request->EEDPFlags = 1194 + MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1195 + MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | 1196 + MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP | 1197 + MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG | 1198 + MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; 1199 + } else { 1200 + io_request->EEDPFlags = 1201 + MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | 1202 + MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; 1203 + } 1204 + io_request->Control |= (0x4 << 26); 1205 + io_request->EEDPBlockSize = MEGASAS_EEDPBLOCKSIZE; 1206 + } else { 1207 + /* Some drives don't support 16/12 byte CDB's, convert to 10 */ 1208 + if (((cdb_len == 12) || (cdb_len == 16)) && 1209 + (start_blk <= 0xffffffff)) { 1210 + if (cdb_len == 16) { 1211 + opcode = cdb[0] == READ_16 ? READ_10 : WRITE_10; 1212 + flagvals = cdb[1]; 1213 + groupnum = cdb[14]; 1214 + control = cdb[15]; 1215 + } else { 1216 + opcode = cdb[0] == READ_12 ? READ_10 : WRITE_10; 1217 + flagvals = cdb[1]; 1218 + groupnum = cdb[10]; 1219 + control = cdb[11]; 1220 + } 1221 + 1222 + memset(cdb, 0, sizeof(io_request->CDB.CDB32)); 1223 + 1224 + cdb[0] = opcode; 1225 + cdb[1] = flagvals; 1226 + cdb[6] = groupnum; 1227 + cdb[9] = control; 1228 + 1229 + /* Transfer length */ 1230 + cdb[8] = (u8)(num_blocks & 0xff); 1231 + cdb[7] = (u8)((num_blocks >> 8) & 0xff); 1232 + 1233 + cdb_len = 10; 1234 + } 1235 + 1236 + /* Normal case, just load LBA here */ 1237 + switch (cdb_len) { 1238 + case 6: 1239 + { 1240 + u8 val = cdb[1] & 0xE0; 1241 + cdb[3] = (u8)(start_blk & 0xff); 1242 + cdb[2] = (u8)((start_blk >> 8) & 0xff); 1243 + cdb[1] = val | ((u8)(start_blk >> 16) & 0x1f); 1244 + break; 1245 + } 1246 + case 10: 1247 + cdb[5] = (u8)(start_blk & 0xff); 1248 + cdb[4] = (u8)((start_blk >> 8) & 0xff); 1249 + cdb[3] = (u8)((start_blk >> 16) & 0xff); 1250 + cdb[2] = (u8)((start_blk >> 24) & 0xff); 1251 + break; 1252 + case 12: 1253 + cdb[5] = (u8)(start_blk & 0xff); 1254 + cdb[4] = (u8)((start_blk >> 8) & 0xff); 1255 + cdb[3] = (u8)((start_blk >> 16) & 0xff); 1256 + cdb[2] = (u8)((start_blk >> 24) & 0xff); 1257 + break; 1258 + case 16: 1259 + cdb[9] = (u8)(start_blk & 0xff); 1260 + cdb[8] = (u8)((start_blk >> 8) & 0xff); 1261 + cdb[7] = (u8)((start_blk >> 16) & 0xff); 1262 + cdb[6] = (u8)((start_blk >> 24) & 0xff); 1263 + cdb[5] = (u8)((start_blk >> 32) & 0xff); 1264 + cdb[4] = (u8)((start_blk >> 40) & 0xff); 1265 + cdb[3] = (u8)((start_blk >> 48) & 0xff); 1266 + cdb[2] = (u8)((start_blk >> 56) & 0xff); 1267 + break; 1268 + } 1269 + } 1270 + } 1271 + 1272 + /** 1273 + * megasas_build_ldio_fusion - Prepares IOs to devices 1274 + * @instance: Adapter soft state 1275 + * @scp: SCSI command 1276 + * @cmd: Command to be prepared 1277 + * 1278 + * Prepares the io_request and chain elements (sg_frame) for IO 1279 + * The IO can be for PD (Fast Path) or LD 1280 + */ 1281 + void 1282 + megasas_build_ldio_fusion(struct megasas_instance *instance, 1283 + struct scsi_cmnd *scp, 1284 + struct megasas_cmd_fusion *cmd) 1285 + { 1286 + u8 fp_possible; 1287 + u32 start_lba_lo, start_lba_hi, device_id; 1288 + struct MPI2_RAID_SCSI_IO_REQUEST *io_request; 1289 + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; 1290 + struct IO_REQUEST_INFO io_info; 1291 + struct fusion_context *fusion; 1292 + struct MR_FW_RAID_MAP_ALL *local_map_ptr; 1293 + 1294 + device_id = MEGASAS_DEV_INDEX(instance, scp); 1295 + 1296 + fusion = instance->ctrl_context; 1297 + 1298 + io_request = cmd->io_request; 1299 + io_request->RaidContext.VirtualDiskTgtId = device_id; 1300 + io_request->RaidContext.status = 0; 1301 + io_request->RaidContext.exStatus = 0; 1302 + 1303 + req_desc = (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)cmd->request_desc; 1304 + 1305 + start_lba_lo = 0; 1306 + start_lba_hi = 0; 1307 + fp_possible = 0; 1308 + 1309 + /* 1310 + * 6-byte READ(0x08) or WRITE(0x0A) cdb 1311 + */ 1312 + if (scp->cmd_len == 6) { 1313 + io_request->DataLength = (u32) scp->cmnd[4]; 1314 + start_lba_lo = ((u32) scp->cmnd[1] << 16) | 1315 + ((u32) scp->cmnd[2] << 8) | (u32) scp->cmnd[3]; 1316 + 1317 + start_lba_lo &= 0x1FFFFF; 1318 + } 1319 + 1320 + /* 1321 + * 10-byte READ(0x28) or WRITE(0x2A) cdb 1322 + */ 1323 + else if (scp->cmd_len == 10) { 1324 + io_request->DataLength = (u32) scp->cmnd[8] | 1325 + ((u32) scp->cmnd[7] << 8); 1326 + start_lba_lo = ((u32) scp->cmnd[2] << 24) | 1327 + ((u32) scp->cmnd[3] << 16) | 1328 + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; 1329 + } 1330 + 1331 + /* 1332 + * 12-byte READ(0xA8) or WRITE(0xAA) cdb 1333 + */ 1334 + else if (scp->cmd_len == 12) { 1335 + io_request->DataLength = ((u32) scp->cmnd[6] << 24) | 1336 + ((u32) scp->cmnd[7] << 16) | 1337 + ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; 1338 + start_lba_lo = ((u32) scp->cmnd[2] << 24) | 1339 + ((u32) scp->cmnd[3] << 16) | 1340 + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; 1341 + } 1342 + 1343 + /* 1344 + * 16-byte READ(0x88) or WRITE(0x8A) cdb 1345 + */ 1346 + else if (scp->cmd_len == 16) { 1347 + io_request->DataLength = ((u32) scp->cmnd[10] << 24) | 1348 + ((u32) scp->cmnd[11] << 16) | 1349 + ((u32) scp->cmnd[12] << 8) | (u32) scp->cmnd[13]; 1350 + start_lba_lo = ((u32) scp->cmnd[6] << 24) | 1351 + ((u32) scp->cmnd[7] << 16) | 1352 + ((u32) scp->cmnd[8] << 8) | (u32) scp->cmnd[9]; 1353 + 1354 + start_lba_hi = ((u32) scp->cmnd[2] << 24) | 1355 + ((u32) scp->cmnd[3] << 16) | 1356 + ((u32) scp->cmnd[4] << 8) | (u32) scp->cmnd[5]; 1357 + } 1358 + 1359 + memset(&io_info, 0, sizeof(struct IO_REQUEST_INFO)); 1360 + io_info.ldStartBlock = ((u64)start_lba_hi << 32) | start_lba_lo; 1361 + io_info.numBlocks = io_request->DataLength; 1362 + io_info.ldTgtId = device_id; 1363 + 1364 + if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) 1365 + io_info.isRead = 1; 1366 + 1367 + local_map_ptr = fusion->ld_map[(instance->map_id & 1)]; 1368 + 1369 + if ((MR_TargetIdToLdGet(device_id, local_map_ptr) >= 1370 + MAX_LOGICAL_DRIVES) || (!fusion->fast_path_io)) { 1371 + io_request->RaidContext.regLockFlags = 0; 1372 + fp_possible = 0; 1373 + } else { 1374 + if (MR_BuildRaidContext(&io_info, &io_request->RaidContext, 1375 + local_map_ptr)) 1376 + fp_possible = io_info.fpOkForIo; 1377 + } 1378 + 1379 + if (fp_possible) { 1380 + megasas_set_pd_lba(io_request, scp->cmd_len, &io_info, scp, 1381 + local_map_ptr, start_lba_lo); 1382 + io_request->DataLength = scsi_bufflen(scp); 1383 + io_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; 1384 + cmd->request_desc->SCSIIO.RequestFlags = 1385 + (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY 1386 + << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 1387 + if ((fusion->load_balance_info[device_id].loadBalanceFlag) && 1388 + (io_info.isRead)) { 1389 + io_info.devHandle = 1390 + get_updated_dev_handle( 1391 + &fusion->load_balance_info[device_id], 1392 + &io_info); 1393 + scp->SCp.Status |= MEGASAS_LOAD_BALANCE_FLAG; 1394 + } else 1395 + scp->SCp.Status &= ~MEGASAS_LOAD_BALANCE_FLAG; 1396 + cmd->request_desc->SCSIIO.DevHandle = io_info.devHandle; 1397 + io_request->DevHandle = io_info.devHandle; 1398 + } else { 1399 + io_request->RaidContext.timeoutValue = 1400 + local_map_ptr->raidMap.fpPdIoTimeoutSec; 1401 + io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST; 1402 + io_request->DevHandle = device_id; 1403 + cmd->request_desc->SCSIIO.RequestFlags = 1404 + (MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO 1405 + << MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 1406 + } /* Not FP */ 1407 + } 1408 + 1409 + /** 1410 + * megasas_build_dcdb_fusion - Prepares IOs to devices 1411 + * @instance: Adapter soft state 1412 + * @scp: SCSI command 1413 + * @cmd: Command to be prepared 1414 + * 1415 + * Prepares the io_request frame for non-io cmds 1416 + */ 1417 + static void 1418 + megasas_build_dcdb_fusion(struct megasas_instance *instance, 1419 + struct scsi_cmnd *scmd, 1420 + struct megasas_cmd_fusion *cmd) 1421 + { 1422 + u32 device_id; 1423 + struct MPI2_RAID_SCSI_IO_REQUEST *io_request; 1424 + u16 pd_index = 0; 1425 + struct MR_FW_RAID_MAP_ALL *local_map_ptr; 1426 + struct fusion_context *fusion = instance->ctrl_context; 1427 + 1428 + io_request = cmd->io_request; 1429 + device_id = MEGASAS_DEV_INDEX(instance, scmd); 1430 + pd_index = (scmd->device->channel * MEGASAS_MAX_DEV_PER_CHANNEL) 1431 + +scmd->device->id; 1432 + local_map_ptr = fusion->ld_map[(instance->map_id & 1)]; 1433 + 1434 + /* Check if this is a system PD I/O */ 1435 + if ((instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) && 1436 + (instance->pd_list[pd_index].driveType == TYPE_DISK)) { 1437 + io_request->Function = 0; 1438 + io_request->DevHandle = 1439 + local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl; 1440 + io_request->RaidContext.timeoutValue = 1441 + local_map_ptr->raidMap.fpPdIoTimeoutSec; 1442 + io_request->RaidContext.regLockFlags = 0; 1443 + io_request->RaidContext.regLockRowLBA = 0; 1444 + io_request->RaidContext.regLockLength = 0; 1445 + io_request->RaidContext.RAIDFlags = 1446 + MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD << 1447 + MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT; 1448 + cmd->request_desc->SCSIIO.RequestFlags = 1449 + (MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY << 1450 + MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 1451 + } else { 1452 + io_request->Function = MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST; 1453 + io_request->DevHandle = device_id; 1454 + cmd->request_desc->SCSIIO.RequestFlags = 1455 + (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << 1456 + MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 1457 + } 1458 + io_request->RaidContext.VirtualDiskTgtId = device_id; 1459 + io_request->LUN[0] = scmd->device->lun; 1460 + io_request->DataLength = scsi_bufflen(scmd); 1461 + } 1462 + 1463 + /** 1464 + * megasas_build_io_fusion - Prepares IOs to devices 1465 + * @instance: Adapter soft state 1466 + * @scp: SCSI command 1467 + * @cmd: Command to be prepared 1468 + * 1469 + * Invokes helper functions to prepare request frames 1470 + * and sets flags appropriate for IO/Non-IO cmd 1471 + */ 1472 + int 1473 + megasas_build_io_fusion(struct megasas_instance *instance, 1474 + struct scsi_cmnd *scp, 1475 + struct megasas_cmd_fusion *cmd) 1476 + { 1477 + u32 device_id, sge_count; 1478 + struct MPI2_RAID_SCSI_IO_REQUEST *io_request = cmd->io_request; 1479 + 1480 + device_id = MEGASAS_DEV_INDEX(instance, scp); 1481 + 1482 + /* Zero out some fields so they don't get reused */ 1483 + io_request->LUN[0] = 0; 1484 + io_request->CDB.EEDP32.PrimaryReferenceTag = 0; 1485 + io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0; 1486 + io_request->EEDPFlags = 0; 1487 + io_request->Control = 0; 1488 + io_request->EEDPBlockSize = 0; 1489 + io_request->IoFlags = 0; 1490 + io_request->RaidContext.RAIDFlags = 0; 1491 + 1492 + memcpy(io_request->CDB.CDB32, scp->cmnd, scp->cmd_len); 1493 + /* 1494 + * Just the CDB length,rest of the Flags are zero 1495 + * This will be modified for FP in build_ldio_fusion 1496 + */ 1497 + io_request->IoFlags = scp->cmd_len; 1498 + 1499 + if (megasas_is_ldio(scp)) 1500 + megasas_build_ldio_fusion(instance, scp, cmd); 1501 + else 1502 + megasas_build_dcdb_fusion(instance, scp, cmd); 1503 + 1504 + /* 1505 + * Construct SGL 1506 + */ 1507 + 1508 + sge_count = 1509 + megasas_make_sgl_fusion(instance, scp, 1510 + (struct MPI25_IEEE_SGE_CHAIN64 *) 1511 + &io_request->SGL, cmd); 1512 + 1513 + if (sge_count > instance->max_num_sge) { 1514 + printk(KERN_ERR "megasas: Error. sge_count (0x%x) exceeds " 1515 + "max (0x%x) allowed\n", sge_count, 1516 + instance->max_num_sge); 1517 + return 1; 1518 + } 1519 + 1520 + io_request->RaidContext.numSGE = sge_count; 1521 + 1522 + io_request->SGLFlags = MPI2_SGE_FLAGS_64_BIT_ADDRESSING; 1523 + 1524 + if (scp->sc_data_direction == PCI_DMA_TODEVICE) 1525 + io_request->Control |= MPI2_SCSIIO_CONTROL_WRITE; 1526 + else if (scp->sc_data_direction == PCI_DMA_FROMDEVICE) 1527 + io_request->Control |= MPI2_SCSIIO_CONTROL_READ; 1528 + 1529 + io_request->SGLOffset0 = 1530 + offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, SGL) / 4; 1531 + 1532 + io_request->SenseBufferLowAddress = cmd->sense_phys_addr; 1533 + io_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; 1534 + 1535 + cmd->scmd = scp; 1536 + scp->SCp.ptr = (char *)cmd; 1537 + 1538 + return 0; 1539 + } 1540 + 1541 + union MEGASAS_REQUEST_DESCRIPTOR_UNION * 1542 + megasas_get_request_descriptor(struct megasas_instance *instance, u16 index) 1543 + { 1544 + u8 *p; 1545 + struct fusion_context *fusion; 1546 + 1547 + if (index >= instance->max_fw_cmds) { 1548 + printk(KERN_ERR "megasas: Invalid SMID (0x%x)request for " 1549 + "descriptor\n", index); 1550 + return NULL; 1551 + } 1552 + fusion = instance->ctrl_context; 1553 + p = fusion->req_frames_desc 1554 + +sizeof(union MEGASAS_REQUEST_DESCRIPTOR_UNION) *index; 1555 + 1556 + return (union MEGASAS_REQUEST_DESCRIPTOR_UNION *)p; 1557 + } 1558 + 1559 + /** 1560 + * megasas_build_and_issue_cmd_fusion -Main routine for building and 1561 + * issuing non IOCTL cmd 1562 + * @instance: Adapter soft state 1563 + * @scmd: pointer to scsi cmd from OS 1564 + */ 1565 + static u32 1566 + megasas_build_and_issue_cmd_fusion(struct megasas_instance *instance, 1567 + struct scsi_cmnd *scmd) 1568 + { 1569 + struct megasas_cmd_fusion *cmd; 1570 + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; 1571 + u32 index; 1572 + struct fusion_context *fusion; 1573 + 1574 + fusion = instance->ctrl_context; 1575 + 1576 + cmd = megasas_get_cmd_fusion(instance); 1577 + if (!cmd) 1578 + return SCSI_MLQUEUE_HOST_BUSY; 1579 + 1580 + index = cmd->index; 1581 + 1582 + req_desc = megasas_get_request_descriptor(instance, index-1); 1583 + if (!req_desc) 1584 + return 1; 1585 + 1586 + req_desc->Words = 0; 1587 + cmd->request_desc = req_desc; 1588 + cmd->request_desc->Words = 0; 1589 + 1590 + if (megasas_build_io_fusion(instance, scmd, cmd)) { 1591 + megasas_return_cmd_fusion(instance, cmd); 1592 + printk(KERN_ERR "megasas: Error building command.\n"); 1593 + cmd->request_desc = NULL; 1594 + return 1; 1595 + } 1596 + 1597 + req_desc = cmd->request_desc; 1598 + req_desc->SCSIIO.SMID = index; 1599 + 1600 + if (cmd->io_request->ChainOffset != 0 && 1601 + cmd->io_request->ChainOffset != 0xF) 1602 + printk(KERN_ERR "megasas: The chain offset value is not " 1603 + "correct : %x\n", cmd->io_request->ChainOffset); 1604 + 1605 + /* 1606 + * Issue the command to the FW 1607 + */ 1608 + atomic_inc(&instance->fw_outstanding); 1609 + 1610 + instance->instancet->fire_cmd(instance, 1611 + req_desc->u.low, req_desc->u.high, 1612 + instance->reg_set); 1613 + 1614 + return 0; 1615 + } 1616 + 1617 + /** 1618 + * complete_cmd_fusion - Completes command 1619 + * @instance: Adapter soft state 1620 + * Completes all commands that is in reply descriptor queue 1621 + */ 1622 + int 1623 + complete_cmd_fusion(struct megasas_instance *instance) 1624 + { 1625 + union MPI2_REPLY_DESCRIPTORS_UNION *desc; 1626 + struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *reply_desc; 1627 + struct MPI2_RAID_SCSI_IO_REQUEST *scsi_io_req; 1628 + struct fusion_context *fusion; 1629 + struct megasas_cmd *cmd_mfi; 1630 + struct megasas_cmd_fusion *cmd_fusion; 1631 + u16 smid, num_completed; 1632 + u8 reply_descript_type, arm; 1633 + u32 status, extStatus, device_id; 1634 + union desc_value d_val; 1635 + struct LD_LOAD_BALANCE_INFO *lbinfo; 1636 + 1637 + fusion = instance->ctrl_context; 1638 + 1639 + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) 1640 + return IRQ_HANDLED; 1641 + 1642 + desc = fusion->reply_frames_desc; 1643 + desc += fusion->last_reply_idx; 1644 + 1645 + reply_desc = (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc; 1646 + 1647 + d_val.word = desc->Words; 1648 + 1649 + reply_descript_type = reply_desc->ReplyFlags & 1650 + MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; 1651 + 1652 + if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) 1653 + return IRQ_NONE; 1654 + 1655 + d_val.word = desc->Words; 1656 + 1657 + num_completed = 0; 1658 + 1659 + while ((d_val.u.low != UINT_MAX) && (d_val.u.high != UINT_MAX)) { 1660 + smid = reply_desc->SMID; 1661 + 1662 + cmd_fusion = fusion->cmd_list[smid - 1]; 1663 + 1664 + scsi_io_req = 1665 + (struct MPI2_RAID_SCSI_IO_REQUEST *) 1666 + cmd_fusion->io_request; 1667 + 1668 + if (cmd_fusion->scmd) 1669 + cmd_fusion->scmd->SCp.ptr = NULL; 1670 + 1671 + status = scsi_io_req->RaidContext.status; 1672 + extStatus = scsi_io_req->RaidContext.exStatus; 1673 + 1674 + switch (scsi_io_req->Function) { 1675 + case MPI2_FUNCTION_SCSI_IO_REQUEST: /*Fast Path IO.*/ 1676 + /* Update load balancing info */ 1677 + device_id = MEGASAS_DEV_INDEX(instance, 1678 + cmd_fusion->scmd); 1679 + lbinfo = &fusion->load_balance_info[device_id]; 1680 + if (cmd_fusion->scmd->SCp.Status & 1681 + MEGASAS_LOAD_BALANCE_FLAG) { 1682 + arm = lbinfo->raid1DevHandle[0] == 1683 + cmd_fusion->io_request->DevHandle ? 0 : 1684 + 1; 1685 + atomic_dec(&lbinfo->scsi_pending_cmds[arm]); 1686 + cmd_fusion->scmd->SCp.Status &= 1687 + ~MEGASAS_LOAD_BALANCE_FLAG; 1688 + } 1689 + if (reply_descript_type == 1690 + MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) { 1691 + if (megasas_dbg_lvl == 5) 1692 + printk(KERN_ERR "\nmegasas: FAST Path " 1693 + "IO Success\n"); 1694 + } 1695 + /* Fall thru and complete IO */ 1696 + case MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST: /* LD-IO Path */ 1697 + /* Map the FW Cmd Status */ 1698 + map_cmd_status(cmd_fusion, status, extStatus); 1699 + scsi_dma_unmap(cmd_fusion->scmd); 1700 + cmd_fusion->scmd->scsi_done(cmd_fusion->scmd); 1701 + scsi_io_req->RaidContext.status = 0; 1702 + scsi_io_req->RaidContext.exStatus = 0; 1703 + megasas_return_cmd_fusion(instance, cmd_fusion); 1704 + atomic_dec(&instance->fw_outstanding); 1705 + 1706 + break; 1707 + case MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST: /*MFI command */ 1708 + cmd_mfi = instance->cmd_list[cmd_fusion->sync_cmd_idx]; 1709 + megasas_complete_cmd(instance, cmd_mfi, DID_OK); 1710 + cmd_fusion->flags = 0; 1711 + megasas_return_cmd_fusion(instance, cmd_fusion); 1712 + 1713 + break; 1714 + } 1715 + 1716 + fusion->last_reply_idx++; 1717 + if (fusion->last_reply_idx >= fusion->reply_q_depth) 1718 + fusion->last_reply_idx = 0; 1719 + 1720 + desc->Words = ULLONG_MAX; 1721 + num_completed++; 1722 + 1723 + /* Get the next reply descriptor */ 1724 + if (!fusion->last_reply_idx) 1725 + desc = fusion->reply_frames_desc; 1726 + else 1727 + desc++; 1728 + 1729 + reply_desc = 1730 + (struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR *)desc; 1731 + 1732 + d_val.word = desc->Words; 1733 + 1734 + reply_descript_type = reply_desc->ReplyFlags & 1735 + MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; 1736 + 1737 + if (reply_descript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) 1738 + break; 1739 + } 1740 + 1741 + if (!num_completed) 1742 + return IRQ_NONE; 1743 + 1744 + wmb(); 1745 + writel(fusion->last_reply_idx, 1746 + &instance->reg_set->reply_post_host_index); 1747 + 1748 + return IRQ_HANDLED; 1749 + } 1750 + 1751 + /** 1752 + * megasas_complete_cmd_dpc_fusion - Completes command 1753 + * @instance: Adapter soft state 1754 + * 1755 + * Tasklet to complete cmds 1756 + */ 1757 + void 1758 + megasas_complete_cmd_dpc_fusion(unsigned long instance_addr) 1759 + { 1760 + struct megasas_instance *instance = 1761 + (struct megasas_instance *)instance_addr; 1762 + unsigned long flags; 1763 + 1764 + /* If we have already declared adapter dead, donot complete cmds */ 1765 + spin_lock_irqsave(&instance->hba_lock, flags); 1766 + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { 1767 + spin_unlock_irqrestore(&instance->hba_lock, flags); 1768 + return; 1769 + } 1770 + spin_unlock_irqrestore(&instance->hba_lock, flags); 1771 + 1772 + spin_lock_irqsave(&instance->completion_lock, flags); 1773 + complete_cmd_fusion(instance); 1774 + spin_unlock_irqrestore(&instance->completion_lock, flags); 1775 + } 1776 + 1777 + /** 1778 + * megasas_isr_fusion - isr entry point 1779 + */ 1780 + irqreturn_t megasas_isr_fusion(int irq, void *devp) 1781 + { 1782 + struct megasas_instance *instance = (struct megasas_instance *)devp; 1783 + u32 mfiStatus, fw_state; 1784 + 1785 + if (!instance->msi_flag) { 1786 + mfiStatus = instance->instancet->clear_intr(instance->reg_set); 1787 + if (!mfiStatus) 1788 + return IRQ_NONE; 1789 + } 1790 + 1791 + /* If we are resetting, bail */ 1792 + if (test_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags)) 1793 + return IRQ_HANDLED; 1794 + 1795 + if (!complete_cmd_fusion(instance)) { 1796 + /* If we didn't complete any commands, check for FW fault */ 1797 + fw_state = instance->instancet->read_fw_status_reg( 1798 + instance->reg_set) & MFI_STATE_MASK; 1799 + if (fw_state == MFI_STATE_FAULT) 1800 + schedule_work(&instance->work_init); 1801 + } 1802 + 1803 + return IRQ_HANDLED; 1804 + } 1805 + 1806 + /** 1807 + * build_mpt_mfi_pass_thru - builds a cmd fo MFI Pass thru 1808 + * @instance: Adapter soft state 1809 + * mfi_cmd: megasas_cmd pointer 1810 + * 1811 + */ 1812 + u8 1813 + build_mpt_mfi_pass_thru(struct megasas_instance *instance, 1814 + struct megasas_cmd *mfi_cmd) 1815 + { 1816 + struct MPI25_IEEE_SGE_CHAIN64 *mpi25_ieee_chain; 1817 + struct MPI2_RAID_SCSI_IO_REQUEST *io_req; 1818 + struct megasas_cmd_fusion *cmd; 1819 + struct fusion_context *fusion; 1820 + struct megasas_header *frame_hdr = &mfi_cmd->frame->hdr; 1821 + 1822 + cmd = megasas_get_cmd_fusion(instance); 1823 + if (!cmd) 1824 + return 1; 1825 + 1826 + /* Save the smid. To be used for returning the cmd */ 1827 + mfi_cmd->context.smid = cmd->index; 1828 + 1829 + cmd->sync_cmd_idx = mfi_cmd->index; 1830 + 1831 + /* 1832 + * For cmds where the flag is set, store the flag and check 1833 + * on completion. For cmds with this flag, don't call 1834 + * megasas_complete_cmd 1835 + */ 1836 + 1837 + if (frame_hdr->flags & MFI_FRAME_DONT_POST_IN_REPLY_QUEUE) 1838 + cmd->flags = MFI_FRAME_DONT_POST_IN_REPLY_QUEUE; 1839 + 1840 + fusion = instance->ctrl_context; 1841 + io_req = cmd->io_request; 1842 + mpi25_ieee_chain = 1843 + (struct MPI25_IEEE_SGE_CHAIN64 *)&io_req->SGL.IeeeChain; 1844 + 1845 + io_req->Function = MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST; 1846 + io_req->SGLOffset0 = offsetof(struct MPI2_RAID_SCSI_IO_REQUEST, 1847 + SGL) / 4; 1848 + io_req->ChainOffset = fusion->chain_offset_mfi_pthru; 1849 + 1850 + mpi25_ieee_chain->Address = mfi_cmd->frame_phys_addr; 1851 + 1852 + mpi25_ieee_chain->Flags = IEEE_SGE_FLAGS_CHAIN_ELEMENT | 1853 + MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR; 1854 + 1855 + mpi25_ieee_chain->Length = MEGASAS_MAX_SZ_CHAIN_FRAME; 1856 + 1857 + return 0; 1858 + } 1859 + 1860 + /** 1861 + * build_mpt_cmd - Calls helper function to build a cmd MFI Pass thru cmd 1862 + * @instance: Adapter soft state 1863 + * @cmd: mfi cmd to build 1864 + * 1865 + */ 1866 + union MEGASAS_REQUEST_DESCRIPTOR_UNION * 1867 + build_mpt_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd) 1868 + { 1869 + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; 1870 + u16 index; 1871 + 1872 + if (build_mpt_mfi_pass_thru(instance, cmd)) { 1873 + printk(KERN_ERR "Couldn't build MFI pass thru cmd\n"); 1874 + return NULL; 1875 + } 1876 + 1877 + index = cmd->context.smid; 1878 + 1879 + req_desc = megasas_get_request_descriptor(instance, index - 1); 1880 + 1881 + if (!req_desc) 1882 + return NULL; 1883 + 1884 + req_desc->Words = 0; 1885 + req_desc->SCSIIO.RequestFlags = (MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO << 1886 + MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT); 1887 + 1888 + req_desc->SCSIIO.SMID = index; 1889 + 1890 + return req_desc; 1891 + } 1892 + 1893 + /** 1894 + * megasas_issue_dcmd_fusion - Issues a MFI Pass thru cmd 1895 + * @instance: Adapter soft state 1896 + * @cmd: mfi cmd pointer 1897 + * 1898 + */ 1899 + void 1900 + megasas_issue_dcmd_fusion(struct megasas_instance *instance, 1901 + struct megasas_cmd *cmd) 1902 + { 1903 + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; 1904 + union desc_value d_val; 1905 + 1906 + req_desc = build_mpt_cmd(instance, cmd); 1907 + if (!req_desc) { 1908 + printk(KERN_ERR "Couldn't issue MFI pass thru cmd\n"); 1909 + return; 1910 + } 1911 + d_val.word = req_desc->Words; 1912 + 1913 + instance->instancet->fire_cmd(instance, req_desc->u.low, 1914 + req_desc->u.high, instance->reg_set); 1915 + } 1916 + 1917 + /** 1918 + * megasas_release_fusion - Reverses the FW initialization 1919 + * @intance: Adapter soft state 1920 + */ 1921 + void 1922 + megasas_release_fusion(struct megasas_instance *instance) 1923 + { 1924 + megasas_free_cmds(instance); 1925 + megasas_free_cmds_fusion(instance); 1926 + 1927 + iounmap(instance->reg_set); 1928 + 1929 + pci_release_selected_regions(instance->pdev, instance->bar); 1930 + } 1931 + 1932 + /** 1933 + * megasas_read_fw_status_reg_fusion - returns the current FW status value 1934 + * @regs: MFI register set 1935 + */ 1936 + static u32 1937 + megasas_read_fw_status_reg_fusion(struct megasas_register_set __iomem *regs) 1938 + { 1939 + return readl(&(regs)->outbound_scratch_pad); 1940 + } 1941 + 1942 + /** 1943 + * megasas_adp_reset_fusion - For controller reset 1944 + * @regs: MFI register set 1945 + */ 1946 + static int 1947 + megasas_adp_reset_fusion(struct megasas_instance *instance, 1948 + struct megasas_register_set __iomem *regs) 1949 + { 1950 + return 0; 1951 + } 1952 + 1953 + /** 1954 + * megasas_check_reset_fusion - For controller reset check 1955 + * @regs: MFI register set 1956 + */ 1957 + static int 1958 + megasas_check_reset_fusion(struct megasas_instance *instance, 1959 + struct megasas_register_set __iomem *regs) 1960 + { 1961 + return 0; 1962 + } 1963 + 1964 + /* This function waits for outstanding commands on fusion to complete */ 1965 + int megasas_wait_for_outstanding_fusion(struct megasas_instance *instance) 1966 + { 1967 + int i, outstanding, retval = 0; 1968 + u32 fw_state, wait_time = MEGASAS_RESET_WAIT_TIME; 1969 + 1970 + for (i = 0; i < wait_time; i++) { 1971 + /* Check if firmware is in fault state */ 1972 + fw_state = instance->instancet->read_fw_status_reg( 1973 + instance->reg_set) & MFI_STATE_MASK; 1974 + if (fw_state == MFI_STATE_FAULT) { 1975 + printk(KERN_WARNING "megasas: Found FW in FAULT state," 1976 + " will reset adapter.\n"); 1977 + retval = 1; 1978 + goto out; 1979 + } 1980 + 1981 + outstanding = atomic_read(&instance->fw_outstanding); 1982 + if (!outstanding) 1983 + goto out; 1984 + 1985 + if (!(i % MEGASAS_RESET_NOTICE_INTERVAL)) { 1986 + printk(KERN_NOTICE "megasas: [%2d]waiting for %d " 1987 + "commands to complete\n", i, outstanding); 1988 + megasas_complete_cmd_dpc_fusion( 1989 + (unsigned long)instance); 1990 + } 1991 + msleep(1000); 1992 + } 1993 + 1994 + if (atomic_read(&instance->fw_outstanding)) { 1995 + printk("megaraid_sas: pending commands remain after waiting, " 1996 + "will reset adapter.\n"); 1997 + retval = 1; 1998 + } 1999 + out: 2000 + return retval; 2001 + } 2002 + 2003 + void megasas_reset_reply_desc(struct megasas_instance *instance) 2004 + { 2005 + int i; 2006 + struct fusion_context *fusion; 2007 + union MPI2_REPLY_DESCRIPTORS_UNION *reply_desc; 2008 + 2009 + fusion = instance->ctrl_context; 2010 + fusion->last_reply_idx = 0; 2011 + reply_desc = fusion->reply_frames_desc; 2012 + for (i = 0 ; i < fusion->reply_q_depth; i++, reply_desc++) 2013 + reply_desc->Words = ULLONG_MAX; 2014 + } 2015 + 2016 + /* Core fusion reset function */ 2017 + int megasas_reset_fusion(struct Scsi_Host *shost) 2018 + { 2019 + int retval = SUCCESS, i, j, retry = 0; 2020 + struct megasas_instance *instance; 2021 + struct megasas_cmd_fusion *cmd_fusion; 2022 + struct fusion_context *fusion; 2023 + struct megasas_cmd *cmd_mfi; 2024 + union MEGASAS_REQUEST_DESCRIPTOR_UNION *req_desc; 2025 + u32 host_diag, abs_state; 2026 + 2027 + instance = (struct megasas_instance *)shost->hostdata; 2028 + fusion = instance->ctrl_context; 2029 + 2030 + mutex_lock(&instance->reset_mutex); 2031 + set_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); 2032 + instance->adprecovery = MEGASAS_ADPRESET_SM_INFAULT; 2033 + instance->instancet->disable_intr(instance->reg_set); 2034 + msleep(1000); 2035 + 2036 + if (instance->adprecovery == MEGASAS_HW_CRITICAL_ERROR) { 2037 + printk(KERN_WARNING "megaraid_sas: Hardware critical error, " 2038 + "returning FAILED.\n"); 2039 + retval = FAILED; 2040 + goto out; 2041 + } 2042 + 2043 + /* First try waiting for commands to complete */ 2044 + if (megasas_wait_for_outstanding_fusion(instance)) { 2045 + printk(KERN_WARNING "megaraid_sas: resetting fusion " 2046 + "adapter.\n"); 2047 + /* Now return commands back to the OS */ 2048 + for (i = 0 ; i < instance->max_fw_cmds; i++) { 2049 + cmd_fusion = fusion->cmd_list[i]; 2050 + if (cmd_fusion->scmd) { 2051 + scsi_dma_unmap(cmd_fusion->scmd); 2052 + cmd_fusion->scmd->result = (DID_RESET << 16); 2053 + cmd_fusion->scmd->scsi_done(cmd_fusion->scmd); 2054 + megasas_return_cmd_fusion(instance, cmd_fusion); 2055 + atomic_dec(&instance->fw_outstanding); 2056 + } 2057 + } 2058 + 2059 + if (instance->disableOnlineCtrlReset == 1) { 2060 + /* Reset not supported, kill adapter */ 2061 + printk(KERN_WARNING "megaraid_sas: Reset not supported" 2062 + ", killing adapter.\n"); 2063 + megaraid_sas_kill_hba(instance); 2064 + instance->adprecovery = MEGASAS_HW_CRITICAL_ERROR; 2065 + retval = FAILED; 2066 + goto out; 2067 + } 2068 + 2069 + /* Now try to reset the chip */ 2070 + for (i = 0; i < MEGASAS_FUSION_MAX_RESET_TRIES; i++) { 2071 + writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, 2072 + &instance->reg_set->fusion_seq_offset); 2073 + writel(MPI2_WRSEQ_1ST_KEY_VALUE, 2074 + &instance->reg_set->fusion_seq_offset); 2075 + writel(MPI2_WRSEQ_2ND_KEY_VALUE, 2076 + &instance->reg_set->fusion_seq_offset); 2077 + writel(MPI2_WRSEQ_3RD_KEY_VALUE, 2078 + &instance->reg_set->fusion_seq_offset); 2079 + writel(MPI2_WRSEQ_4TH_KEY_VALUE, 2080 + &instance->reg_set->fusion_seq_offset); 2081 + writel(MPI2_WRSEQ_5TH_KEY_VALUE, 2082 + &instance->reg_set->fusion_seq_offset); 2083 + writel(MPI2_WRSEQ_6TH_KEY_VALUE, 2084 + &instance->reg_set->fusion_seq_offset); 2085 + 2086 + /* Check that the diag write enable (DRWE) bit is on */ 2087 + host_diag = readl(&instance->reg_set->fusion_host_diag); 2088 + while (!(host_diag & HOST_DIAG_WRITE_ENABLE)) { 2089 + msleep(100); 2090 + host_diag = 2091 + readl(&instance->reg_set->fusion_host_diag); 2092 + if (retry++ == 100) { 2093 + printk(KERN_WARNING "megaraid_sas: " 2094 + "Host diag unlock failed!\n"); 2095 + break; 2096 + } 2097 + } 2098 + if (!(host_diag & HOST_DIAG_WRITE_ENABLE)) 2099 + continue; 2100 + 2101 + /* Send chip reset command */ 2102 + writel(host_diag | HOST_DIAG_RESET_ADAPTER, 2103 + &instance->reg_set->fusion_host_diag); 2104 + msleep(3000); 2105 + 2106 + /* Make sure reset adapter bit is cleared */ 2107 + host_diag = readl(&instance->reg_set->fusion_host_diag); 2108 + retry = 0; 2109 + while (host_diag & HOST_DIAG_RESET_ADAPTER) { 2110 + msleep(100); 2111 + host_diag = 2112 + readl(&instance->reg_set->fusion_host_diag); 2113 + if (retry++ == 1000) { 2114 + printk(KERN_WARNING "megaraid_sas: " 2115 + "Diag reset adapter never " 2116 + "cleared!\n"); 2117 + break; 2118 + } 2119 + } 2120 + if (host_diag & HOST_DIAG_RESET_ADAPTER) 2121 + continue; 2122 + 2123 + abs_state = 2124 + instance->instancet->read_fw_status_reg( 2125 + instance->reg_set); 2126 + retry = 0; 2127 + 2128 + while ((abs_state <= MFI_STATE_FW_INIT) && 2129 + (retry++ < 1000)) { 2130 + msleep(100); 2131 + abs_state = 2132 + instance->instancet->read_fw_status_reg( 2133 + instance->reg_set); 2134 + } 2135 + if (abs_state <= MFI_STATE_FW_INIT) { 2136 + printk(KERN_WARNING "megaraid_sas: firmware " 2137 + "state < MFI_STATE_FW_INIT, state = " 2138 + "0x%x\n", abs_state); 2139 + continue; 2140 + } 2141 + 2142 + /* Wait for FW to become ready */ 2143 + if (megasas_transition_to_ready(instance)) { 2144 + printk(KERN_WARNING "megaraid_sas: Failed to " 2145 + "transition controller to ready.\n"); 2146 + continue; 2147 + } 2148 + 2149 + megasas_reset_reply_desc(instance); 2150 + if (megasas_ioc_init_fusion(instance)) { 2151 + printk(KERN_WARNING "megaraid_sas: " 2152 + "megasas_ioc_init_fusion() failed!\n"); 2153 + continue; 2154 + } 2155 + 2156 + instance->instancet->enable_intr(instance->reg_set); 2157 + instance->adprecovery = MEGASAS_HBA_OPERATIONAL; 2158 + 2159 + /* Re-fire management commands */ 2160 + for (j = 0 ; j < instance->max_fw_cmds; j++) { 2161 + cmd_fusion = fusion->cmd_list[j]; 2162 + if (cmd_fusion->sync_cmd_idx != 2163 + (u32)ULONG_MAX) { 2164 + cmd_mfi = 2165 + instance-> 2166 + cmd_list[cmd_fusion->sync_cmd_idx]; 2167 + if (cmd_mfi->frame->dcmd.opcode == 2168 + MR_DCMD_LD_MAP_GET_INFO) { 2169 + megasas_return_cmd(instance, 2170 + cmd_mfi); 2171 + megasas_return_cmd_fusion( 2172 + instance, cmd_fusion); 2173 + } else { 2174 + req_desc = 2175 + megasas_get_request_descriptor( 2176 + instance, 2177 + cmd_mfi->context.smid 2178 + -1); 2179 + if (!req_desc) 2180 + printk(KERN_WARNING 2181 + "req_desc NULL" 2182 + "\n"); 2183 + else { 2184 + instance->instancet-> 2185 + fire_cmd(instance, 2186 + req_desc-> 2187 + u.low, 2188 + req_desc-> 2189 + u.high, 2190 + instance-> 2191 + reg_set); 2192 + } 2193 + } 2194 + } 2195 + } 2196 + 2197 + /* Reset load balance info */ 2198 + memset(fusion->load_balance_info, 0, 2199 + sizeof(struct LD_LOAD_BALANCE_INFO) 2200 + *MAX_LOGICAL_DRIVES); 2201 + 2202 + if (!megasas_get_map_info(instance)) 2203 + megasas_sync_map_info(instance); 2204 + 2205 + /* Adapter reset completed successfully */ 2206 + printk(KERN_WARNING "megaraid_sas: Reset " 2207 + "successful.\n"); 2208 + retval = SUCCESS; 2209 + goto out; 2210 + } 2211 + /* Reset failed, kill the adapter */ 2212 + printk(KERN_WARNING "megaraid_sas: Reset failed, killing " 2213 + "adapter.\n"); 2214 + megaraid_sas_kill_hba(instance); 2215 + retval = FAILED; 2216 + } else { 2217 + instance->instancet->enable_intr(instance->reg_set); 2218 + instance->adprecovery = MEGASAS_HBA_OPERATIONAL; 2219 + } 2220 + out: 2221 + clear_bit(MEGASAS_FUSION_IN_RESET, &instance->reset_flags); 2222 + mutex_unlock(&instance->reset_mutex); 2223 + return retval; 2224 + } 2225 + 2226 + /* Fusion OCR work queue */ 2227 + void megasas_fusion_ocr_wq(struct work_struct *work) 2228 + { 2229 + struct megasas_instance *instance = 2230 + container_of(work, struct megasas_instance, work_init); 2231 + 2232 + megasas_reset_fusion(instance->host); 2233 + } 2234 + 2235 + struct megasas_instance_template megasas_instance_template_fusion = { 2236 + .fire_cmd = megasas_fire_cmd_fusion, 2237 + .enable_intr = megasas_enable_intr_fusion, 2238 + .disable_intr = megasas_disable_intr_fusion, 2239 + .clear_intr = megasas_clear_intr_fusion, 2240 + .read_fw_status_reg = megasas_read_fw_status_reg_fusion, 2241 + .adp_reset = megasas_adp_reset_fusion, 2242 + .check_reset = megasas_check_reset_fusion, 2243 + .service_isr = megasas_isr_fusion, 2244 + .tasklet = megasas_complete_cmd_dpc_fusion, 2245 + .init_adapter = megasas_init_adapter_fusion, 2246 + .build_and_issue_cmd = megasas_build_and_issue_cmd_fusion, 2247 + .issue_dcmd = megasas_issue_dcmd_fusion, 2248 + };
+695
drivers/scsi/megaraid/megaraid_sas_fusion.h
··· 1 + /* 2 + * Linux MegaRAID driver for SAS based RAID controllers 3 + * 4 + * Copyright (c) 2009-2011 LSI Corporation. 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 2 9 + * of the License, or (at your option) any later version. 10 + * 11 + * This program is distributed in the hope that it will be useful, 12 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 + * GNU General Public License for more details. 15 + * 16 + * You should have received a copy of the GNU General Public License 17 + * along with this program; if not, write to the Free Software 18 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 19 + * 20 + * FILE: megaraid_sas_fusion.h 21 + * 22 + * Authors: LSI Corporation 23 + * Manoj Jose 24 + * Sumant Patro 25 + * 26 + * Send feedback to: <megaraidlinux@lsi.com> 27 + * 28 + * Mail to: LSI Corporation, 1621 Barber Lane, Milpitas, CA 95035 29 + * ATTN: Linuxraid 30 + */ 31 + 32 + #ifndef _MEGARAID_SAS_FUSION_H_ 33 + #define _MEGARAID_SAS_FUSION_H_ 34 + 35 + /* Fusion defines */ 36 + #define MEGASAS_MAX_SZ_CHAIN_FRAME 1024 37 + #define MFI_FUSION_ENABLE_INTERRUPT_MASK (0x00000009) 38 + #define MEGA_MPI2_RAID_DEFAULT_IO_FRAME_SIZE 256 39 + #define MEGASAS_MPI2_FUNCTION_PASSTHRU_IO_REQUEST 0xF0 40 + #define MEGASAS_MPI2_FUNCTION_LD_IO_REQUEST 0xF1 41 + #define MEGASAS_LOAD_BALANCE_FLAG 0x1 42 + #define MEGASAS_DCMD_MBOX_PEND_FLAG 0x1 43 + #define HOST_DIAG_WRITE_ENABLE 0x80 44 + #define HOST_DIAG_RESET_ADAPTER 0x4 45 + #define MEGASAS_FUSION_MAX_RESET_TRIES 3 46 + 47 + /* T10 PI defines */ 48 + #define MR_PROT_INFO_TYPE_CONTROLLER 0x8 49 + #define MEGASAS_SCSI_VARIABLE_LENGTH_CMD 0x7f 50 + #define MEGASAS_SCSI_SERVICE_ACTION_READ32 0x9 51 + #define MEGASAS_SCSI_SERVICE_ACTION_WRITE32 0xB 52 + #define MEGASAS_SCSI_ADDL_CDB_LEN 0x18 53 + #define MEGASAS_RD_WR_PROTECT_CHECK_ALL 0x20 54 + #define MEGASAS_RD_WR_PROTECT_CHECK_NONE 0x60 55 + #define MEGASAS_EEDPBLOCKSIZE 512 56 + 57 + /* 58 + * Raid context flags 59 + */ 60 + 61 + #define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_SHIFT 0x4 62 + #define MR_RAID_CTX_RAID_FLAGS_IO_SUB_TYPE_MASK 0x30 63 + enum MR_RAID_FLAGS_IO_SUB_TYPE { 64 + MR_RAID_FLAGS_IO_SUB_TYPE_NONE = 0, 65 + MR_RAID_FLAGS_IO_SUB_TYPE_SYSTEM_PD = 1, 66 + }; 67 + 68 + /* 69 + * Request descriptor types 70 + */ 71 + #define MEGASAS_REQ_DESCRIPT_FLAGS_LD_IO 0x7 72 + #define MEGASAS_REQ_DESCRIPT_FLAGS_MFA 0x1 73 + 74 + #define MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT 1 75 + 76 + #define MEGASAS_FP_CMD_LEN 16 77 + #define MEGASAS_FUSION_IN_RESET 0 78 + 79 + /* 80 + * Raid Context structure which describes MegaRAID specific IO Paramenters 81 + * This resides at offset 0x60 where the SGL normally starts in MPT IO Frames 82 + */ 83 + 84 + struct RAID_CONTEXT { 85 + u16 resvd0; 86 + u16 timeoutValue; 87 + u8 regLockFlags; 88 + u8 resvd1; 89 + u16 VirtualDiskTgtId; 90 + u64 regLockRowLBA; 91 + u32 regLockLength; 92 + u16 nextLMId; 93 + u8 exStatus; 94 + u8 status; 95 + u8 RAIDFlags; 96 + u8 numSGE; 97 + u16 configSeqNum; 98 + u8 spanArm; 99 + u8 resvd2[3]; 100 + }; 101 + 102 + #define RAID_CTX_SPANARM_ARM_SHIFT (0) 103 + #define RAID_CTX_SPANARM_ARM_MASK (0x1f) 104 + 105 + #define RAID_CTX_SPANARM_SPAN_SHIFT (5) 106 + #define RAID_CTX_SPANARM_SPAN_MASK (0xE0) 107 + 108 + /* 109 + * define region lock types 110 + */ 111 + enum REGION_TYPE { 112 + REGION_TYPE_UNUSED = 0, 113 + REGION_TYPE_SHARED_READ = 1, 114 + REGION_TYPE_SHARED_WRITE = 2, 115 + REGION_TYPE_EXCLUSIVE = 3, 116 + }; 117 + 118 + /* MPI2 defines */ 119 + #define MPI2_FUNCTION_IOC_INIT (0x02) /* IOC Init */ 120 + #define MPI2_WHOINIT_HOST_DRIVER (0x04) 121 + #define MPI2_VERSION_MAJOR (0x02) 122 + #define MPI2_VERSION_MINOR (0x00) 123 + #define MPI2_VERSION_MAJOR_MASK (0xFF00) 124 + #define MPI2_VERSION_MAJOR_SHIFT (8) 125 + #define MPI2_VERSION_MINOR_MASK (0x00FF) 126 + #define MPI2_VERSION_MINOR_SHIFT (0) 127 + #define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ 128 + MPI2_VERSION_MINOR) 129 + #define MPI2_HEADER_VERSION_UNIT (0x10) 130 + #define MPI2_HEADER_VERSION_DEV (0x00) 131 + #define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) 132 + #define MPI2_HEADER_VERSION_UNIT_SHIFT (8) 133 + #define MPI2_HEADER_VERSION_DEV_MASK (0x00FF) 134 + #define MPI2_HEADER_VERSION_DEV_SHIFT (0) 135 + #define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | \ 136 + MPI2_HEADER_VERSION_DEV) 137 + #define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) 138 + #define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000) 139 + #define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400) 140 + #define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003) 141 + #define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200) 142 + #define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100) 143 + #define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004) 144 + #define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) /* SCSI IO */ 145 + #define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06) 146 + #define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00) 147 + #define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02) 148 + #define MPI2_SCSIIO_CONTROL_WRITE (0x01000000) 149 + #define MPI2_SCSIIO_CONTROL_READ (0x02000000) 150 + #define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E) 151 + #define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F) 152 + #define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00) 153 + #define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F) 154 + #define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0) 155 + #define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004) 156 + #define MPI2_WRSEQ_1ST_KEY_VALUE (0xF) 157 + #define MPI2_WRSEQ_2ND_KEY_VALUE (0x4) 158 + #define MPI2_WRSEQ_3RD_KEY_VALUE (0xB) 159 + #define MPI2_WRSEQ_4TH_KEY_VALUE (0x2) 160 + #define MPI2_WRSEQ_5TH_KEY_VALUE (0x7) 161 + #define MPI2_WRSEQ_6TH_KEY_VALUE (0xD) 162 + 163 + struct MPI25_IEEE_SGE_CHAIN64 { 164 + u64 Address; 165 + u32 Length; 166 + u16 Reserved1; 167 + u8 NextChainOffset; 168 + u8 Flags; 169 + }; 170 + 171 + struct MPI2_SGE_SIMPLE_UNION { 172 + u32 FlagsLength; 173 + union { 174 + u32 Address32; 175 + u64 Address64; 176 + } u; 177 + }; 178 + 179 + struct MPI2_SCSI_IO_CDB_EEDP32 { 180 + u8 CDB[20]; /* 0x00 */ 181 + u32 PrimaryReferenceTag; /* 0x14 */ 182 + u16 PrimaryApplicationTag; /* 0x18 */ 183 + u16 PrimaryApplicationTagMask; /* 0x1A */ 184 + u32 TransferLength; /* 0x1C */ 185 + }; 186 + 187 + struct MPI2_SGE_CHAIN_UNION { 188 + u16 Length; 189 + u8 NextChainOffset; 190 + u8 Flags; 191 + union { 192 + u32 Address32; 193 + u64 Address64; 194 + } u; 195 + }; 196 + 197 + struct MPI2_IEEE_SGE_SIMPLE32 { 198 + u32 Address; 199 + u32 FlagsLength; 200 + }; 201 + 202 + struct MPI2_IEEE_SGE_CHAIN32 { 203 + u32 Address; 204 + u32 FlagsLength; 205 + }; 206 + 207 + struct MPI2_IEEE_SGE_SIMPLE64 { 208 + u64 Address; 209 + u32 Length; 210 + u16 Reserved1; 211 + u8 Reserved2; 212 + u8 Flags; 213 + }; 214 + 215 + struct MPI2_IEEE_SGE_CHAIN64 { 216 + u64 Address; 217 + u32 Length; 218 + u16 Reserved1; 219 + u8 Reserved2; 220 + u8 Flags; 221 + }; 222 + 223 + union MPI2_IEEE_SGE_SIMPLE_UNION { 224 + struct MPI2_IEEE_SGE_SIMPLE32 Simple32; 225 + struct MPI2_IEEE_SGE_SIMPLE64 Simple64; 226 + }; 227 + 228 + union MPI2_IEEE_SGE_CHAIN_UNION { 229 + struct MPI2_IEEE_SGE_CHAIN32 Chain32; 230 + struct MPI2_IEEE_SGE_CHAIN64 Chain64; 231 + }; 232 + 233 + union MPI2_SGE_IO_UNION { 234 + struct MPI2_SGE_SIMPLE_UNION MpiSimple; 235 + struct MPI2_SGE_CHAIN_UNION MpiChain; 236 + union MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; 237 + union MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; 238 + }; 239 + 240 + union MPI2_SCSI_IO_CDB_UNION { 241 + u8 CDB32[32]; 242 + struct MPI2_SCSI_IO_CDB_EEDP32 EEDP32; 243 + struct MPI2_SGE_SIMPLE_UNION SGE; 244 + }; 245 + 246 + /* 247 + * RAID SCSI IO Request Message 248 + * Total SGE count will be one less than _MPI2_SCSI_IO_REQUEST 249 + */ 250 + struct MPI2_RAID_SCSI_IO_REQUEST { 251 + u16 DevHandle; /* 0x00 */ 252 + u8 ChainOffset; /* 0x02 */ 253 + u8 Function; /* 0x03 */ 254 + u16 Reserved1; /* 0x04 */ 255 + u8 Reserved2; /* 0x06 */ 256 + u8 MsgFlags; /* 0x07 */ 257 + u8 VP_ID; /* 0x08 */ 258 + u8 VF_ID; /* 0x09 */ 259 + u16 Reserved3; /* 0x0A */ 260 + u32 SenseBufferLowAddress; /* 0x0C */ 261 + u16 SGLFlags; /* 0x10 */ 262 + u8 SenseBufferLength; /* 0x12 */ 263 + u8 Reserved4; /* 0x13 */ 264 + u8 SGLOffset0; /* 0x14 */ 265 + u8 SGLOffset1; /* 0x15 */ 266 + u8 SGLOffset2; /* 0x16 */ 267 + u8 SGLOffset3; /* 0x17 */ 268 + u32 SkipCount; /* 0x18 */ 269 + u32 DataLength; /* 0x1C */ 270 + u32 BidirectionalDataLength; /* 0x20 */ 271 + u16 IoFlags; /* 0x24 */ 272 + u16 EEDPFlags; /* 0x26 */ 273 + u32 EEDPBlockSize; /* 0x28 */ 274 + u32 SecondaryReferenceTag; /* 0x2C */ 275 + u16 SecondaryApplicationTag; /* 0x30 */ 276 + u16 ApplicationTagTranslationMask; /* 0x32 */ 277 + u8 LUN[8]; /* 0x34 */ 278 + u32 Control; /* 0x3C */ 279 + union MPI2_SCSI_IO_CDB_UNION CDB; /* 0x40 */ 280 + struct RAID_CONTEXT RaidContext; /* 0x60 */ 281 + union MPI2_SGE_IO_UNION SGL; /* 0x80 */ 282 + }; 283 + 284 + /* 285 + * MPT RAID MFA IO Descriptor. 286 + */ 287 + struct MEGASAS_RAID_MFA_IO_REQUEST_DESCRIPTOR { 288 + u32 RequestFlags:8; 289 + u32 MessageAddress1:24; /* bits 31:8*/ 290 + u32 MessageAddress2; /* bits 61:32 */ 291 + }; 292 + 293 + /* Default Request Descriptor */ 294 + struct MPI2_DEFAULT_REQUEST_DESCRIPTOR { 295 + u8 RequestFlags; /* 0x00 */ 296 + u8 MSIxIndex; /* 0x01 */ 297 + u16 SMID; /* 0x02 */ 298 + u16 LMID; /* 0x04 */ 299 + u16 DescriptorTypeDependent; /* 0x06 */ 300 + }; 301 + 302 + /* High Priority Request Descriptor */ 303 + struct MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR { 304 + u8 RequestFlags; /* 0x00 */ 305 + u8 MSIxIndex; /* 0x01 */ 306 + u16 SMID; /* 0x02 */ 307 + u16 LMID; /* 0x04 */ 308 + u16 Reserved1; /* 0x06 */ 309 + }; 310 + 311 + /* SCSI IO Request Descriptor */ 312 + struct MPI2_SCSI_IO_REQUEST_DESCRIPTOR { 313 + u8 RequestFlags; /* 0x00 */ 314 + u8 MSIxIndex; /* 0x01 */ 315 + u16 SMID; /* 0x02 */ 316 + u16 LMID; /* 0x04 */ 317 + u16 DevHandle; /* 0x06 */ 318 + }; 319 + 320 + /* SCSI Target Request Descriptor */ 321 + struct MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR { 322 + u8 RequestFlags; /* 0x00 */ 323 + u8 MSIxIndex; /* 0x01 */ 324 + u16 SMID; /* 0x02 */ 325 + u16 LMID; /* 0x04 */ 326 + u16 IoIndex; /* 0x06 */ 327 + }; 328 + 329 + /* RAID Accelerator Request Descriptor */ 330 + struct MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR { 331 + u8 RequestFlags; /* 0x00 */ 332 + u8 MSIxIndex; /* 0x01 */ 333 + u16 SMID; /* 0x02 */ 334 + u16 LMID; /* 0x04 */ 335 + u16 Reserved; /* 0x06 */ 336 + }; 337 + 338 + /* union of Request Descriptors */ 339 + union MEGASAS_REQUEST_DESCRIPTOR_UNION { 340 + struct MPI2_DEFAULT_REQUEST_DESCRIPTOR Default; 341 + struct MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority; 342 + struct MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO; 343 + struct MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget; 344 + struct MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator; 345 + struct MEGASAS_RAID_MFA_IO_REQUEST_DESCRIPTOR MFAIo; 346 + union { 347 + struct { 348 + u32 low; 349 + u32 high; 350 + } u; 351 + u64 Words; 352 + }; 353 + }; 354 + 355 + /* Default Reply Descriptor */ 356 + struct MPI2_DEFAULT_REPLY_DESCRIPTOR { 357 + u8 ReplyFlags; /* 0x00 */ 358 + u8 MSIxIndex; /* 0x01 */ 359 + u16 DescriptorTypeDependent1; /* 0x02 */ 360 + u32 DescriptorTypeDependent2; /* 0x04 */ 361 + }; 362 + 363 + /* Address Reply Descriptor */ 364 + struct MPI2_ADDRESS_REPLY_DESCRIPTOR { 365 + u8 ReplyFlags; /* 0x00 */ 366 + u8 MSIxIndex; /* 0x01 */ 367 + u16 SMID; /* 0x02 */ 368 + u32 ReplyFrameAddress; /* 0x04 */ 369 + }; 370 + 371 + /* SCSI IO Success Reply Descriptor */ 372 + struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR { 373 + u8 ReplyFlags; /* 0x00 */ 374 + u8 MSIxIndex; /* 0x01 */ 375 + u16 SMID; /* 0x02 */ 376 + u16 TaskTag; /* 0x04 */ 377 + u16 Reserved1; /* 0x06 */ 378 + }; 379 + 380 + /* TargetAssist Success Reply Descriptor */ 381 + struct MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR { 382 + u8 ReplyFlags; /* 0x00 */ 383 + u8 MSIxIndex; /* 0x01 */ 384 + u16 SMID; /* 0x02 */ 385 + u8 SequenceNumber; /* 0x04 */ 386 + u8 Reserved1; /* 0x05 */ 387 + u16 IoIndex; /* 0x06 */ 388 + }; 389 + 390 + /* Target Command Buffer Reply Descriptor */ 391 + struct MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR { 392 + u8 ReplyFlags; /* 0x00 */ 393 + u8 MSIxIndex; /* 0x01 */ 394 + u8 VP_ID; /* 0x02 */ 395 + u8 Flags; /* 0x03 */ 396 + u16 InitiatorDevHandle; /* 0x04 */ 397 + u16 IoIndex; /* 0x06 */ 398 + }; 399 + 400 + /* RAID Accelerator Success Reply Descriptor */ 401 + struct MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR { 402 + u8 ReplyFlags; /* 0x00 */ 403 + u8 MSIxIndex; /* 0x01 */ 404 + u16 SMID; /* 0x02 */ 405 + u32 Reserved; /* 0x04 */ 406 + }; 407 + 408 + /* union of Reply Descriptors */ 409 + union MPI2_REPLY_DESCRIPTORS_UNION { 410 + struct MPI2_DEFAULT_REPLY_DESCRIPTOR Default; 411 + struct MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply; 412 + struct MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess; 413 + struct MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess; 414 + struct MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; 415 + struct MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR 416 + RAIDAcceleratorSuccess; 417 + u64 Words; 418 + }; 419 + 420 + /* IOCInit Request message */ 421 + struct MPI2_IOC_INIT_REQUEST { 422 + u8 WhoInit; /* 0x00 */ 423 + u8 Reserved1; /* 0x01 */ 424 + u8 ChainOffset; /* 0x02 */ 425 + u8 Function; /* 0x03 */ 426 + u16 Reserved2; /* 0x04 */ 427 + u8 Reserved3; /* 0x06 */ 428 + u8 MsgFlags; /* 0x07 */ 429 + u8 VP_ID; /* 0x08 */ 430 + u8 VF_ID; /* 0x09 */ 431 + u16 Reserved4; /* 0x0A */ 432 + u16 MsgVersion; /* 0x0C */ 433 + u16 HeaderVersion; /* 0x0E */ 434 + u32 Reserved5; /* 0x10 */ 435 + u16 Reserved6; /* 0x14 */ 436 + u8 Reserved7; /* 0x16 */ 437 + u8 HostMSIxVectors; /* 0x17 */ 438 + u16 Reserved8; /* 0x18 */ 439 + u16 SystemRequestFrameSize; /* 0x1A */ 440 + u16 ReplyDescriptorPostQueueDepth; /* 0x1C */ 441 + u16 ReplyFreeQueueDepth; /* 0x1E */ 442 + u32 SenseBufferAddressHigh; /* 0x20 */ 443 + u32 SystemReplyAddressHigh; /* 0x24 */ 444 + u64 SystemRequestFrameBaseAddress; /* 0x28 */ 445 + u64 ReplyDescriptorPostQueueAddress;/* 0x30 */ 446 + u64 ReplyFreeQueueAddress; /* 0x38 */ 447 + u64 TimeStamp; /* 0x40 */ 448 + }; 449 + 450 + /* mrpriv defines */ 451 + #define MR_PD_INVALID 0xFFFF 452 + #define MAX_SPAN_DEPTH 8 453 + #define MAX_RAIDMAP_SPAN_DEPTH (MAX_SPAN_DEPTH) 454 + #define MAX_ROW_SIZE 32 455 + #define MAX_RAIDMAP_ROW_SIZE (MAX_ROW_SIZE) 456 + #define MAX_LOGICAL_DRIVES 64 457 + #define MAX_RAIDMAP_LOGICAL_DRIVES (MAX_LOGICAL_DRIVES) 458 + #define MAX_RAIDMAP_VIEWS (MAX_LOGICAL_DRIVES) 459 + #define MAX_ARRAYS 128 460 + #define MAX_RAIDMAP_ARRAYS (MAX_ARRAYS) 461 + #define MAX_PHYSICAL_DEVICES 256 462 + #define MAX_RAIDMAP_PHYSICAL_DEVICES (MAX_PHYSICAL_DEVICES) 463 + #define MR_DCMD_LD_MAP_GET_INFO 0x0300e101 464 + 465 + struct MR_DEV_HANDLE_INFO { 466 + u16 curDevHdl; 467 + u8 validHandles; 468 + u8 reserved; 469 + u16 devHandle[2]; 470 + }; 471 + 472 + struct MR_ARRAY_INFO { 473 + u16 pd[MAX_RAIDMAP_ROW_SIZE]; 474 + }; 475 + 476 + struct MR_QUAD_ELEMENT { 477 + u64 logStart; 478 + u64 logEnd; 479 + u64 offsetInSpan; 480 + u32 diff; 481 + u32 reserved1; 482 + }; 483 + 484 + struct MR_SPAN_INFO { 485 + u32 noElements; 486 + u32 reserved1; 487 + struct MR_QUAD_ELEMENT quad[MAX_RAIDMAP_SPAN_DEPTH]; 488 + }; 489 + 490 + struct MR_LD_SPAN { 491 + u64 startBlk; 492 + u64 numBlks; 493 + u16 arrayRef; 494 + u8 reserved[6]; 495 + }; 496 + 497 + struct MR_SPAN_BLOCK_INFO { 498 + u64 num_rows; 499 + struct MR_LD_SPAN span; 500 + struct MR_SPAN_INFO block_span_info; 501 + }; 502 + 503 + struct MR_LD_RAID { 504 + struct { 505 + u32 fpCapable:1; 506 + u32 reserved5:3; 507 + u32 ldPiMode:4; 508 + u32 pdPiMode:4; 509 + u32 encryptionType:8; 510 + u32 fpWriteCapable:1; 511 + u32 fpReadCapable:1; 512 + u32 fpWriteAcrossStripe:1; 513 + u32 fpReadAcrossStripe:1; 514 + u32 reserved4:8; 515 + } capability; 516 + u32 reserved6; 517 + u64 size; 518 + u8 spanDepth; 519 + u8 level; 520 + u8 stripeShift; 521 + u8 rowSize; 522 + u8 rowDataSize; 523 + u8 writeMode; 524 + u8 PRL; 525 + u8 SRL; 526 + u16 targetId; 527 + u8 ldState; 528 + u8 regTypeReqOnWrite; 529 + u8 modFactor; 530 + u8 reserved2[1]; 531 + u16 seqNum; 532 + 533 + struct { 534 + u32 ldSyncRequired:1; 535 + u32 reserved:31; 536 + } flags; 537 + 538 + u8 reserved3[0x5C]; 539 + }; 540 + 541 + struct MR_LD_SPAN_MAP { 542 + struct MR_LD_RAID ldRaid; 543 + u8 dataArmMap[MAX_RAIDMAP_ROW_SIZE]; 544 + struct MR_SPAN_BLOCK_INFO spanBlock[MAX_RAIDMAP_SPAN_DEPTH]; 545 + }; 546 + 547 + struct MR_FW_RAID_MAP { 548 + u32 totalSize; 549 + union { 550 + struct { 551 + u32 maxLd; 552 + u32 maxSpanDepth; 553 + u32 maxRowSize; 554 + u32 maxPdCount; 555 + u32 maxArrays; 556 + } validationInfo; 557 + u32 version[5]; 558 + u32 reserved1[5]; 559 + }; 560 + 561 + u32 ldCount; 562 + u32 Reserved1; 563 + u8 ldTgtIdToLd[MAX_RAIDMAP_LOGICAL_DRIVES+ 564 + MAX_RAIDMAP_VIEWS]; 565 + u8 fpPdIoTimeoutSec; 566 + u8 reserved2[7]; 567 + struct MR_ARRAY_INFO arMapInfo[MAX_RAIDMAP_ARRAYS]; 568 + struct MR_DEV_HANDLE_INFO devHndlInfo[MAX_RAIDMAP_PHYSICAL_DEVICES]; 569 + struct MR_LD_SPAN_MAP ldSpanMap[1]; 570 + }; 571 + 572 + struct IO_REQUEST_INFO { 573 + u64 ldStartBlock; 574 + u32 numBlocks; 575 + u16 ldTgtId; 576 + u8 isRead; 577 + u16 devHandle; 578 + u64 pdBlock; 579 + u8 fpOkForIo; 580 + }; 581 + 582 + struct MR_LD_TARGET_SYNC { 583 + u8 targetId; 584 + u8 reserved; 585 + u16 seqNum; 586 + }; 587 + 588 + #define IEEE_SGE_FLAGS_ADDR_MASK (0x03) 589 + #define IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) 590 + #define IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01) 591 + #define IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02) 592 + #define IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) 593 + #define IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80) 594 + #define IEEE_SGE_FLAGS_END_OF_LIST (0x40) 595 + 596 + struct megasas_register_set; 597 + struct megasas_instance; 598 + 599 + union desc_word { 600 + u64 word; 601 + struct { 602 + u32 low; 603 + u32 high; 604 + } u; 605 + }; 606 + 607 + struct megasas_cmd_fusion { 608 + struct MPI2_RAID_SCSI_IO_REQUEST *io_request; 609 + dma_addr_t io_request_phys_addr; 610 + 611 + union MPI2_SGE_IO_UNION *sg_frame; 612 + dma_addr_t sg_frame_phys_addr; 613 + 614 + u8 *sense; 615 + dma_addr_t sense_phys_addr; 616 + 617 + struct list_head list; 618 + struct scsi_cmnd *scmd; 619 + struct megasas_instance *instance; 620 + 621 + u8 retry_for_fw_reset; 622 + union MEGASAS_REQUEST_DESCRIPTOR_UNION *request_desc; 623 + 624 + /* 625 + * Context for a MFI frame. 626 + * Used to get the mfi cmd from list when a MFI cmd is completed 627 + */ 628 + u32 sync_cmd_idx; 629 + u32 index; 630 + u8 flags; 631 + }; 632 + 633 + struct LD_LOAD_BALANCE_INFO { 634 + u8 loadBalanceFlag; 635 + u8 reserved1; 636 + u16 raid1DevHandle[2]; 637 + atomic_t scsi_pending_cmds[2]; 638 + u64 last_accessed_block[2]; 639 + }; 640 + 641 + struct MR_FW_RAID_MAP_ALL { 642 + struct MR_FW_RAID_MAP raidMap; 643 + struct MR_LD_SPAN_MAP ldSpanMap[MAX_LOGICAL_DRIVES - 1]; 644 + } __attribute__ ((packed)); 645 + 646 + struct fusion_context { 647 + struct megasas_cmd_fusion **cmd_list; 648 + struct list_head cmd_pool; 649 + 650 + spinlock_t cmd_pool_lock; 651 + 652 + dma_addr_t req_frames_desc_phys; 653 + u8 *req_frames_desc; 654 + 655 + struct dma_pool *io_request_frames_pool; 656 + dma_addr_t io_request_frames_phys; 657 + u8 *io_request_frames; 658 + 659 + struct dma_pool *sg_dma_pool; 660 + struct dma_pool *sense_dma_pool; 661 + 662 + dma_addr_t reply_frames_desc_phys; 663 + union MPI2_REPLY_DESCRIPTORS_UNION *reply_frames_desc; 664 + struct dma_pool *reply_frames_desc_pool; 665 + 666 + u16 last_reply_idx; 667 + 668 + u32 reply_q_depth; 669 + u32 request_alloc_sz; 670 + u32 reply_alloc_sz; 671 + u32 io_frames_alloc_sz; 672 + 673 + u16 max_sge_in_main_msg; 674 + u16 max_sge_in_chain; 675 + 676 + u8 chain_offset_io_request; 677 + u8 chain_offset_mfi_pthru; 678 + 679 + struct MR_FW_RAID_MAP_ALL *ld_map[2]; 680 + dma_addr_t ld_map_phys[2]; 681 + 682 + u32 map_sz; 683 + u8 fast_path_io; 684 + struct LD_LOAD_BALANCE_INFO load_balance_info[MAX_LOGICAL_DRIVES]; 685 + }; 686 + 687 + union desc_value { 688 + u64 word; 689 + struct { 690 + u32 low; 691 + u32 high; 692 + } u; 693 + }; 694 + 695 + #endif /* _MEGARAID_SAS_FUSION_H_ */