mv_sas.c revision 24ae163ed33d2b8a70d2f0b1947b401d0a8e8719
1b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik/* 220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * Marvell 88SE64xx/88SE94xx main function 320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * 420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * Copyright 2007 Red Hat, Inc. 520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * Copyright 2008 Marvell. <kewei@marvell.com> 620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * 720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * This file is licensed under GPLv2. 820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * 920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * This program is free software; you can redistribute it and/or 1020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * modify it under the terms of the GNU General Public License as 1120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * published by the Free Software Foundation; version 2 of the 1220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * License. 1320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * 1420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * This program is distributed in the hope that it will be useful, 1520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * but WITHOUT ANY WARRANTY; without even the implied warranty of 1620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * General Public License for more details. 1820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * 1920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * You should have received a copy of the GNU General Public License 2020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * along with this program; if not, write to the Free Software 2120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 2220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * USA 2320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan*/ 24b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 25dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#include "mv_sas.h" 26b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 27dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag) 28dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 29dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (task->lldd_task) { 30dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_slot_info *slot; 31f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan slot = task->lldd_task; 3220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan *tag = slot->slot_tag; 33dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return 1; 34dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 35dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return 0; 36dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 3820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_tag_clear(struct mvs_info *mvi, u32 tag) 39dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 40f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan void *bitmap = &mvi->tags; 41dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik clear_bit(tag, bitmap); 42dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 4420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_tag_free(struct mvs_info *mvi, u32 tag) 45dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 46dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_tag_clear(mvi, tag); 47dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 4920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_tag_set(struct mvs_info *mvi, unsigned int tag) 50dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 51f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan void *bitmap = &mvi->tags; 52dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik set_bit(tag, bitmap); 53dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 5520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yaninline int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out) 56dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 57dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik unsigned int index, tag; 58f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan void *bitmap = &mvi->tags; 59b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 6020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan index = find_first_zero_bit(bitmap, mvi->tags_num); 61dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik tag = index; 6220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (tag >= mvi->tags_num) 63dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return -SAS_QUEUE_FULL; 64dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_tag_set(mvi, tag); 65dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik *tag_out = tag; 66dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return 0; 67dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 68b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 69dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikvoid mvs_tag_init(struct mvs_info *mvi) 70dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 71dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik int i; 7220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (i = 0; i < mvi->tags_num; ++i) 73dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_tag_clear(mvi, i); 74dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 75b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 7620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_hexdump(u32 size, u8 *data, u32 baseaddr) 778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 i; 798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 run; 808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 offset; 818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei offset = 0; 838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei while (size) { 8420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan printk(KERN_DEBUG"%08X : ", baseaddr + offset); 858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (size >= 16) 868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei run = 16; 878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei run = size; 898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei size -= run; 908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for (i = 0; i < 16; i++) { 918f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (i < run) 9220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan printk(KERN_DEBUG"%02X ", (u32)data[i]); 938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 9420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan printk(KERN_DEBUG" "); 958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 9620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan printk(KERN_DEBUG": "); 978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei for (i = 0; i < run; i++) 9820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan printk(KERN_DEBUG"%c", 9920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan isalnum(data[i]) ? data[i] : '.'); 10020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan printk(KERN_DEBUG"\n"); 1018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei data = &data[16]; 1028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei offset += run; 1038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 10420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan printk(KERN_DEBUG"\n"); 1058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 1068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 10720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#if (_MV_DUMP > 1) 1088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_hba_sb_dump(struct mvs_info *mvi, u32 tag, 1098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei enum sas_protocol proto) 1108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 1118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 offset; 1128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_slot_info *slot = &mvi->slot_info[tag]; 1138f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei offset = slot->cmd_size + MVS_OAF_SZ + 11520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->prd_size() * slot->n_elem; 11620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, "+---->Status buffer[%d] :\n", 1178f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei tag); 1188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(32, (u8 *) slot->response, 1198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) slot->buf_dma + offset); 1208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 121ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei#endif 1228f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_hba_memory_dump(struct mvs_info *mvi, u32 tag, 1248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei enum sas_protocol proto) 1258f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 12620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#if (_MV_DUMP > 1) 127ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei u32 sz, w_ptr; 1288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u64 addr; 1298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_slot_info *slot = &mvi->slot_info[tag]; 1308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*Delivery Queue */ 13220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sz = MVS_CHIP_SLOT_SZ; 133ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei w_ptr = slot->tx; 13420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan addr = mvi->tx_dma; 13520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, 136ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei "Delivery Queue Size=%04d , WRT_PTR=%04X\n", sz, w_ptr); 13720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, 1388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "Delivery Queue Base Address=0x%llX (PA)" 1398f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "(tx_dma=0x%llX), Entry=%04d\n", 14020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan addr, (unsigned long long)mvi->tx_dma, w_ptr); 1418f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(sizeof(u32), (u8 *)(&mvi->tx[mvi->tx_prod]), 1428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) mvi->tx_dma + sizeof(u32) * w_ptr); 1438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*Command List */ 144ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei addr = mvi->slot_dma; 14520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, 1468f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "Command List Base Address=0x%llX (PA)" 1478f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "(slot_dma=0x%llX), Header=%03d\n", 14820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan addr, (unsigned long long)slot->buf_dma, tag); 14920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, "Command Header[%03d]:\n", tag); 1508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*mvs_cmd_hdr */ 1518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(sizeof(struct mvs_cmd_hdr), (u8 *)(&mvi->slot[tag]), 1528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) mvi->slot_dma + tag * sizeof(struct mvs_cmd_hdr)); 1538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*1.command table area */ 15420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, "+---->Command Table :\n"); 1558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(slot->cmd_size, (u8 *) slot->buf, (u32) slot->buf_dma); 1568f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*2.open address frame area */ 15720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, "+---->Open Address Frame :\n"); 1588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(MVS_OAF_SZ, (u8 *) slot->buf + slot->cmd_size, 1598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) slot->buf_dma + slot->cmd_size); 1608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*3.status buffer */ 1618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hba_sb_dump(mvi, tag, proto); 1628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*4.PRD table */ 16320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, "+---->PRD table :\n"); 16420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_hexdump(MVS_CHIP_DISP->prd_size() * slot->n_elem, 1658f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u8 *) slot->buf + slot->cmd_size + MVS_OAF_SZ, 1668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (u32) slot->buf_dma + slot->cmd_size + MVS_OAF_SZ); 1678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 1688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 1698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Weistatic void mvs_hba_cq_dump(struct mvs_info *mvi) 1718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 172ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei#if (_MV_DUMP > 2) 1738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u64 addr; 1748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei void __iomem *regs = mvi->regs; 1758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 entry = mvi->rx_cons + 1; 1768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 rx_desc = le32_to_cpu(mvi->rx[entry]); 1778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /*Completion Queue */ 1798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei addr = mr32(RX_HI) << 16 << 16 | mr32(RX_LO); 18020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, "Completion Task = 0x%p\n", 181ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei mvi->slot_info[rx_desc & RXQ_SLOT_MASK].task); 18220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, 1838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "Completion List Base Address=0x%llX (PA), " 1848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei "CQ_Entry=%04d, CQ_WP=0x%08X\n", 1858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei addr, entry - 1, mvi->rx[0]); 1868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvs_hexdump(sizeof(u32), (u8 *)(&rx_desc), 1878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->rx_dma + sizeof(u32) * entry); 1888f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 1898f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 1908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 19120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_get_sas_addr(void *buf, u32 buflen) 1928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 19320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /*memcpy(buf, "\x50\x05\x04\x30\x11\xab\x64\x40", 8);*/ 19420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 1958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 19620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstruct mvs_info *mvs_find_dev_mvi(struct domain_device *dev) 19720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 19820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned long i = 0, j = 0, hi = 0; 19920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sha = dev->port->ha; 20020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi = NULL; 20120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_phy *phy; 20220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 20320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan while (sha->sas_port[i]) { 20420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (sha->sas_port[i] == dev->port) { 20520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy = container_of(sha->sas_port[i]->phy_list.next, 20620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_phy, port_phy_el); 20720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan j = 0; 20820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan while (sha->sas_phy[j]) { 20920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (sha->sas_phy[j] == phy) 21020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 21120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan j++; 21220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 21320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 21420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 21520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan i++; 21620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 21720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan hi = j/((struct mvs_prv_info *)sha->lldd_ha)->n_phy; 21820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[hi]; 2198f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 22020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return mvi; 2218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 22220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 2238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 22420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan/* FIXME */ 22520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_find_dev_phyno(struct domain_device *dev, int *phyno) 22620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 22720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned long i = 0, j = 0, n = 0, num = 0; 2289870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; 2299870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan struct mvs_info *mvi = mvi_dev->mvi_info; 23020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sha = dev->port->ha; 23120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 23220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan while (sha->sas_port[i]) { 23320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (sha->sas_port[i] == dev->port) { 23420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_phy *phy; 23520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan list_for_each_entry(phy, 23620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan &sha->sas_port[i]->phy_list, port_phy_el) { 23720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan j = 0; 23820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan while (sha->sas_phy[j]) { 23920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (sha->sas_phy[j] == phy) 24020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 24120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan j++; 24220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 24320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phyno[n] = (j >= mvi->chip->n_phy) ? 24420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan (j - mvi->chip->n_phy) : j; 24520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan num++; 24620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan n++; 247dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 248dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 249dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 25020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan i++; 25120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 25220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return num; 25320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 25420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 25520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic inline void mvs_free_reg_set(struct mvs_info *mvi, 25620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_device *dev) 25720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 25820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!dev) { 25920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("device has been free.\n"); 26020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return; 26120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 26220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (dev->taskfileset == MVS_ID_NOT_MAPPED) 26320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return; 26420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->free_reg_set(mvi, &dev->taskfileset); 26520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 26620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 26720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic inline u8 mvs_assign_reg_set(struct mvs_info *mvi, 26820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_device *dev) 26920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 27020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (dev->taskfileset != MVS_ID_NOT_MAPPED) 27120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return 0; 27220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return MVS_CHIP_DISP->assign_reg_set(mvi, &dev->taskfileset); 27320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 27420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 27520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_phys_reset(struct mvs_info *mvi, u32 phy_mask, int hard) 27620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 27720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 no; 27820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for_each_phy(phy_mask, phy_mask, no) { 27920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!(phy_mask & 1)) 28020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan continue; 28120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->phy_reset(mvi, no, hard); 28220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 28320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 28420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 28520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan/* FIXME: locking? */ 28620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func, 28720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan void *funcdata) 28820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 28920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int rc = 0, phy_id = sas_phy->id; 29020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 tmp, i = 0, hi; 29120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sha = sas_phy->ha; 29220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi = NULL; 29320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 29420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan while (sha->sas_phy[i]) { 29520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (sha->sas_phy[i] == sas_phy) 29620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 29720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan i++; 29820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 29920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan hi = i/((struct mvs_prv_info *)sha->lldd_ha)->n_phy; 30020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[hi]; 30120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 30220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan switch (func) { 30320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case PHY_FUNC_SET_LINK_RATE: 30420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->phy_set_link_rate(mvi, phy_id, funcdata); 30520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 3068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 307dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case PHY_FUNC_HARD_RESET: 30820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_id); 309dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (tmp & PHY_RST_HARD) 310dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 31120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->phy_reset(mvi, phy_id, 1); 312dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 313b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 314dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case PHY_FUNC_LINK_RESET: 31520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->phy_enable(mvi, phy_id); 31620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->phy_reset(mvi, phy_id, 0); 317dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 318b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 319dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case PHY_FUNC_DISABLE: 32020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->phy_disable(mvi, phy_id); 32120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 322dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case PHY_FUNC_RELEASE_SPINUP_HOLD: 323dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik default: 324dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = -EOPNOTSUPP; 325b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 32620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan msleep(200); 327b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 328b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 329b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 33020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid __devinit mvs_set_sas_addr(struct mvs_info *mvi, int port_id, 33120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 off_lo, u32 off_hi, u64 sas_addr) 33220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 33320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 lo = (u32)sas_addr; 33420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 hi = (u32)(sas_addr>>32); 33520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 33620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_addr(mvi, port_id, off_lo); 33720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, lo); 33820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_addr(mvi, port_id, off_hi); 33920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_data(mvi, port_id, hi); 34020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 34120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 342dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic void mvs_bytes_dmaed(struct mvs_info *mvi, int i) 343ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei{ 344dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_phy *phy = &mvi->phy[i]; 34520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_phy *sas_phy = &phy->sas_phy; 34620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sas_ha; 347dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!phy->phy_attached) 348dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return; 349dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 35020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!(phy->att_dev_info & PORT_DEV_TRGT_MASK) 35120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan && phy->phy_type & PORT_TYPE_SAS) { 35220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return; 35320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 35420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 35520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_ha = mvi->sas; 35620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_ha->notify_phy_event(sas_phy, PHYE_OOB_DONE); 35720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 358dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (sas_phy->phy) { 359dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct sas_phy *sphy = sas_phy->phy; 360dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 361dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sphy->negotiated_linkrate = sas_phy->linkrate; 362dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sphy->minimum_linkrate = phy->minimum_linkrate; 363dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sphy->minimum_linkrate_hw = SAS_LINK_RATE_1_5_GBPS; 364dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sphy->maximum_linkrate = phy->maximum_linkrate; 36520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sphy->maximum_linkrate_hw = MVS_CHIP_DISP->phy_max_link_rate(); 366ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei } 367ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei 368dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (phy->phy_type & PORT_TYPE_SAS) { 369dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct sas_identify_frame *id; 370b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 371dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik id = (struct sas_identify_frame *)phy->frame_rcvd; 372dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik id->dev_type = phy->identify.device_type; 373dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik id->initiator_bits = SAS_PROTOCOL_ALL; 374dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik id->target_bits = phy->identify.target_port_protocols; 375dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } else if (phy->phy_type & PORT_TYPE_SATA) { 37620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /*Nothing*/ 377dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 37820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("phy %d byte dmaded.\n", i + mvi->id * mvi->chip->n_phy); 37920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 38020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_phy->frame_rcvd_size = phy->frame_rcvd_size; 38120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 38220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->sas->notify_port_event(sas_phy, 383dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik PORTE_BYTES_DMAED); 384ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei} 385ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei 38620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_slave_alloc(struct scsi_device *scsi_dev) 38720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 38820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct domain_device *dev = sdev_to_domain_dev(scsi_dev); 38920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (dev_is_sata(dev)) { 39020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* We don't need to rescan targets 39120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * if REPORT_LUNS request is failed 39220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan */ 39320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (scsi_dev->lun > 0) 39420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return -ENXIO; 39520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan scsi_dev->tagged_supported = 1; 39620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 39720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 39820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return sas_slave_alloc(scsi_dev); 39920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 40020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 401dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikint mvs_slave_configure(struct scsi_device *sdev) 402ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei{ 403dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct domain_device *dev = sdev_to_domain_dev(sdev); 404dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik int ret = sas_slave_configure(sdev); 405b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 406dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (ret) 407dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return ret; 408dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (dev_is_sata(dev)) { 40920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* may set PIO mode */ 41020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan #if MV_DISABLE_NCQ 41120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct ata_port *ap = dev->sata_dev.ap; 41220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct ata_device *adev = ap->link.device; 41320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan adev->flags |= ATA_DFLAG_NCQ_OFF; 414dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1); 41520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan #endif 416dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 417ee1f1c2ef95258351e1ecb89a2dbd2763cb3a6edKe Wei return 0; 418b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 419b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 420dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikvoid mvs_scan_start(struct Scsi_Host *shost) 421b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 42220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int i, j; 42320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned short core_nr; 42420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi; 42520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost); 42620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 42720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host; 428dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 42920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (j = 0; j < core_nr; j++) { 43020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[j]; 43120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (i = 0; i < mvi->chip->n_phy; ++i) 43220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_bytes_dmaed(mvi, i); 433dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 434b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 435b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 436dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikint mvs_scan_finished(struct Scsi_Host *shost, unsigned long time) 437b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 438dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* give the phy enabling interrupt event time to come in (1s 439dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik * is empirically about all it takes) */ 440dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (time < HZ) 441dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return 0; 442dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* Wait for discovery to finish */ 443dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik scsi_flush_work(shost); 444dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return 1; 445b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 446b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 447dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic int mvs_task_prep_smp(struct mvs_info *mvi, 448dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_task_exec_info *tei) 449b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 450dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik int elem, rc, i; 451dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct sas_task *task = tei->task; 452dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_cmd_hdr *hdr = tei->hdr; 45320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct domain_device *dev = task->dev; 45420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_port *sas_port = dev->port; 455dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct scatterlist *sg_req, *sg_resp; 456dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik u32 req_len, resp_len, tag = tei->tag; 457dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik void *buf_tmp; 458dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik u8 *buf_oaf; 459dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik dma_addr_t buf_tmp_dma; 46020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan void *buf_prd; 461dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_slot_info *slot = &mvi->slot_info[tag]; 462dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik u32 flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); 463dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#if _MV_DUMP 464dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik u8 *buf_cmd; 465dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik void *from; 466dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#endif 467dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* 468dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik * DMA-map SMP request, response buffers 469dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik */ 470dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sg_req = &task->smp_task.smp_req; 47120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan elem = dma_map_sg(mvi->dev, sg_req, 1, PCI_DMA_TODEVICE); 472dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!elem) 473dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return -ENOMEM; 474dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik req_len = sg_dma_len(sg_req); 475b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 476dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sg_resp = &task->smp_task.smp_resp; 47720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan elem = dma_map_sg(mvi->dev, sg_resp, 1, PCI_DMA_FROMDEVICE); 478dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!elem) { 479dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = -ENOMEM; 480dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out; 481dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 48220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan resp_len = SB_RFB_MAX; 483b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 484dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* must be in dwords */ 485dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if ((req_len & 0x3) || (resp_len & 0x3)) { 486dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = -EINVAL; 487dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out_2; 488b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 489b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 490dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* 491dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs 492dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik */ 493b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 49420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ***** */ 495dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_tmp = slot->buf; 496dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_tmp_dma = slot->buf_dma; 497b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 498dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#if _MV_DUMP 499dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_cmd = buf_tmp; 500dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); 501dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_tmp += req_len; 502dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_tmp_dma += req_len; 503dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik slot->cmd_size = req_len; 504dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#else 505dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik hdr->cmd_tbl = cpu_to_le64(sg_dma_address(sg_req)); 506dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#endif 507b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 508dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ 509dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_oaf = buf_tmp; 510dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik hdr->open_frame = cpu_to_le64(buf_tmp_dma); 511b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 512dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_tmp += MVS_OAF_SZ; 513dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_tmp_dma += MVS_OAF_SZ; 514b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 51520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* region 3: PRD table *********************************** */ 516dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_prd = buf_tmp; 517dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (tei->n_elem) 518dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); 519dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik else 520dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik hdr->prd_tbl = 0; 521b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 52220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan i = MVS_CHIP_DISP->prd_size() * tei->n_elem; 523dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_tmp += i; 524dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik buf_tmp_dma += i; 525b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 526dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ 527dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik slot->response = buf_tmp; 528dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik hdr->status_buf = cpu_to_le64(buf_tmp_dma); 52920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->flags & MVF_FLAG_SOC) 53020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan hdr->reserved[0] = 0; 531b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 532dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* 533dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik * Fill in TX ring and command slot header 534dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik */ 535dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik slot->tx = mvi->tx_prod; 536dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvi->tx[mvi->tx_prod] = cpu_to_le32((TXQ_CMD_SMP << TXQ_CMD_SHIFT) | 537dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik TXQ_MODE_I | tag | 538dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik (sas_port->phy_mask << TXQ_PHY_SHIFT)); 539b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 540dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik hdr->flags |= flags; 541dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | ((req_len - 4) / 4)); 542dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik hdr->tags = cpu_to_le32(tag); 543dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik hdr->data_len = 0; 544b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 545dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* generate open address frame hdr (first 12 bytes) */ 54620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* initiator, SMP, ftype 1h */ 54720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan buf_oaf[0] = (1 << 7) | (PROTOCOL_SMP << 4) | 0x01; 54820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan buf_oaf[1] = dev->linkrate & 0xf; 549dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik *(u16 *)(buf_oaf + 2) = 0xFFFF; /* SAS SPEC */ 55020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE); 551dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 552dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* fill in PRD (scatter/gather) table, if any */ 55320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd); 554b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 555dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#if _MV_DUMP 556dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* copy cmd table */ 557dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik from = kmap_atomic(sg_page(sg_req), KM_IRQ0); 558dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik memcpy(buf_cmd, from + sg_req->offset, req_len); 559dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik kunmap_atomic(from, KM_IRQ0); 560dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik#endif 561b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 562b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 563dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikerr_out_2: 56420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_unmap_sg(mvi->dev, &tei->task->smp_task.smp_resp, 1, 565dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik PCI_DMA_FROMDEVICE); 566b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikerr_out: 56720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_unmap_sg(mvi->dev, &tei->task->smp_task.smp_req, 1, 568dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik PCI_DMA_TODEVICE); 569b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return rc; 5708f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 5718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 572dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic u32 mvs_get_ncq_tag(struct sas_task *task, u32 *tag) 5738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 574dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct ata_queued_cmd *qc = task->uldd_task; 5758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 576dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (qc) { 577dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (qc->tf.command == ATA_CMD_FPDMA_WRITE || 578dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik qc->tf.command == ATA_CMD_FPDMA_READ) { 579dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik *tag = qc->tag; 580dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return 1; 581dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 5828f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 5838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 584dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return 0; 5858f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 5868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 587dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic int mvs_task_prep_ata(struct mvs_info *mvi, 588dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_task_exec_info *tei) 589b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 590b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct sas_task *task = tei->task; 591b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct domain_device *dev = task->dev; 592f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan struct mvs_device *mvi_dev = dev->lldd_dev; 593b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_cmd_hdr *hdr = tei->hdr; 594b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct asd_sas_port *sas_port = dev->port; 5958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_slot_info *slot; 59620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan void *buf_prd; 59720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 tag = tei->tag, hdr_tag; 59820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 flags, del_q; 599b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void *buf_tmp; 600b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u8 *buf_cmd, *buf_oaf; 601b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_addr_t buf_tmp_dma; 6028f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 i, req_len, resp_len; 6038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei const u32 max_resp_len = SB_RFB_MAX; 6048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 60520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvs_assign_reg_set(mvi, mvi_dev) == MVS_ID_NOT_MAPPED) { 60620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("Have not enough regiset for dev %d.\n", 60720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_dev->device_id); 6088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei return -EBUSY; 60920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 6108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot = &mvi->slot_info[tag]; 6118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->tx = mvi->tx_prod; 61220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan del_q = TXQ_MODE_I | tag | 61320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan (TXQ_CMD_STP << TXQ_CMD_SHIFT) | 61420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan (sas_port->phy_mask << TXQ_PHY_SHIFT) | 61520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan (mvi_dev->taskfileset << TXQ_SRS_SHIFT); 61620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q); 61720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 61820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#ifndef DISABLE_HOTPLUG_DMA_FIX 61920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->data_dir == DMA_FROM_DEVICE) 62020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan flags = (MVS_CHIP_DISP->prd_count() << MCH_PRD_LEN_SHIFT); 62120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 62220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); 62320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#else 62420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan flags = (tei->n_elem << MCH_PRD_LEN_SHIFT); 62520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#endif 626b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (task->ata_task.use_ncq) 627b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik flags |= MCH_FPDMA; 6288f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) { 6298f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (task->ata_task.fis.command != ATA_CMD_ID_ATAPI) 6308f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei flags |= MCH_ATAPI; 6318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 6328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 633b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* FIXME: fill in port multiplier number */ 634b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 635b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->flags = cpu_to_le32(flags); 6368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 6378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* FIXME: the low order order 5 bits for the TAG if enable NCQ */ 63820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->ata_task.use_ncq && mvs_get_ncq_tag(task, &hdr_tag)) 63920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->ata_task.fis.sector_count |= (u8) (hdr_tag << 3); 6404e52fc0a0a2ec2158691efba3f149f6416481255Ke Wei else 64120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan hdr_tag = tag; 64220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 64320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan hdr->tags = cpu_to_le32(hdr_tag); 64420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 645b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->data_len = cpu_to_le32(task->total_xfer_len); 646b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 647b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 648b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs 649b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 650b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 6518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 1: command table area (MVS_ATA_CMD_SZ bytes) ************** */ 6528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_cmd = buf_tmp = slot->buf; 653b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma = slot->buf_dma; 654b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 655b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); 656b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 657b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += MVS_ATA_CMD_SZ; 658b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += MVS_ATA_CMD_SZ; 6598f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 6608f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->cmd_size = MVS_ATA_CMD_SZ; 6618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 662b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 6638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ 664b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* used for STP. unused for SATA? */ 665b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_oaf = buf_tmp; 666b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->open_frame = cpu_to_le64(buf_tmp_dma); 667b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 668b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += MVS_OAF_SZ; 669b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += MVS_OAF_SZ; 670b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 6718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 3: PRD table ********************************************* */ 672b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_prd = buf_tmp; 67320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 6748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (tei->n_elem) 6758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); 6768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 6778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->prd_tbl = 0; 67820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan i = MVS_CHIP_DISP->prd_size() * MVS_CHIP_DISP->prd_count(); 679b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 680b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += i; 681b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += i; 682b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 6838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ 684b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* FIXME: probably unused, for SATA. kept here just in case 685b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * we get a STP/SATA error information record 686b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 687b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik slot->response = buf_tmp; 688b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->status_buf = cpu_to_le64(buf_tmp_dma); 68920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->flags & MVF_FLAG_SOC) 69020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan hdr->reserved[0] = 0; 691b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 6928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei req_len = sizeof(struct host_to_dev_fis); 693b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik resp_len = MVS_SLOT_BUF_SZ - MVS_ATA_CMD_SZ - 6948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(struct mvs_err_info) - i; 695b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 696b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* request, response lengths */ 6978f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei resp_len = min(resp_len, max_resp_len); 698b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4)); 699b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 70020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (likely(!task->ata_task.device_control_reg_update)) 70120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->ata_task.fis.flags |= 0x80; /* C=1: update ATA cmd reg */ 702b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* fill in command FIS and ATAPI CDB */ 7038f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(buf_cmd, &task->ata_task.fis, sizeof(struct host_to_dev_fis)); 7048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (dev->sata_dev.command_set == ATAPI_COMMAND_SET) 7058f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei memcpy(buf_cmd + STP_ATAPI_CMD, 7068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei task->ata_task.atapi_packet, 16); 7078f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 7088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* generate open address frame hdr (first 12 bytes) */ 70920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* initiator, STP, ftype 1h */ 71020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan buf_oaf[0] = (1 << 7) | (PROTOCOL_STP << 4) | 0x1; 71120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan buf_oaf[1] = dev->linkrate & 0xf; 71220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan *(u16 *)(buf_oaf + 2) = cpu_to_be16(mvi_dev->device_id + 1); 71320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE); 714b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 715b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* fill in PRD (scatter/gather) table, if any */ 71620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd); 71720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#ifndef DISABLE_HOTPLUG_DMA_FIX 71820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->data_dir == DMA_FROM_DEVICE) 71920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->dma_fix(mvi->bulk_buffer_dma, 72020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan TRASH_BUCKET_SIZE, tei->n_elem, buf_prd); 72120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#endif 722b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 723b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 724b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 725b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzikstatic int mvs_task_prep_ssp(struct mvs_info *mvi, 72620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_task_exec_info *tei, int is_tmf, 72720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_tmf_task *tmf) 728b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 729b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct sas_task *task = tei->task; 730b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_cmd_hdr *hdr = tei->hdr; 7318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct mvs_port *port = tei->port; 73220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct domain_device *dev = task->dev; 733f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan struct mvs_device *mvi_dev = dev->lldd_dev; 73420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_port *sas_port = dev->port; 735b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_slot_info *slot; 73620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan void *buf_prd; 737b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct ssp_frame_hdr *ssp_hdr; 738b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik void *buf_tmp; 739b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u8 *buf_cmd, *buf_oaf, fburst = 0; 740b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik dma_addr_t buf_tmp_dma; 741b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik u32 flags; 7428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 resp_len, req_len, i, tag = tei->tag; 7438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei const u32 max_resp_len = SB_RFB_MAX; 74420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 phy_mask; 745b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 746b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik slot = &mvi->slot_info[tag]; 747b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 74820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy_mask = ((port->wide_port_phymap) ? port->wide_port_phymap : 74920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_port->phy_mask) & TXQ_PHY_MASK; 75020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 7518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->tx = mvi->tx_prod; 7528f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag | 7538f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei (TXQ_CMD_SSP << TXQ_CMD_SHIFT) | 7544e52fc0a0a2ec2158691efba3f149f6416481255Ke Wei (phy_mask << TXQ_PHY_SHIFT)); 755b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 756b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik flags = MCH_RETRY; 757b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik if (task->ssp_task.enable_first_burst) { 758b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik flags |= MCH_FBURST; 759b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik fburst = (1 << 7); 760b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 7612b288133ab6306b1761e0a2ef943b944ead6ad69Andy Yan if (is_tmf) 7622b288133ab6306b1761e0a2ef943b944ead6ad69Andy Yan flags |= (MCH_SSP_FR_TASK << MCH_SSP_FR_TYPE_SHIFT); 7632b288133ab6306b1761e0a2ef943b944ead6ad69Andy Yan hdr->flags = cpu_to_le32(flags | (tei->n_elem << MCH_PRD_LEN_SHIFT)); 764b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->tags = cpu_to_le32(tag); 765b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->data_len = cpu_to_le32(task->total_xfer_len); 766b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 767b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* 768b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs 769b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik */ 770b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 7718f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */ 7728f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei buf_cmd = buf_tmp = slot->buf; 773b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma = slot->buf_dma; 774b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 775b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); 776b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 777b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += MVS_SSP_CMD_SZ; 778b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += MVS_SSP_CMD_SZ; 7798f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#if _MV_DUMP 7808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei slot->cmd_size = MVS_SSP_CMD_SZ; 7818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei#endif 782b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 7838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 2: open address frame area (MVS_OAF_SZ bytes) ********* */ 784b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_oaf = buf_tmp; 785b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->open_frame = cpu_to_le64(buf_tmp_dma); 786b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 787b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += MVS_OAF_SZ; 788b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += MVS_OAF_SZ; 789b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 7908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 3: PRD table ********************************************* */ 791b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_prd = buf_tmp; 7928f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei if (tei->n_elem) 7938f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->prd_tbl = cpu_to_le64(buf_tmp_dma); 7948f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei else 7958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei hdr->prd_tbl = 0; 796b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 79720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan i = MVS_CHIP_DISP->prd_size() * tei->n_elem; 798b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp += i; 799b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_tmp_dma += i; 800b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 8018f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* region 4: status buffer (larger the PRD, smaller this buf) ****** */ 802b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik slot->response = buf_tmp; 803b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->status_buf = cpu_to_le64(buf_tmp_dma); 80420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->flags & MVF_FLAG_SOC) 80520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan hdr->reserved[0] = 0; 806b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 807b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik resp_len = MVS_SLOT_BUF_SZ - MVS_SSP_CMD_SZ - MVS_OAF_SZ - 8088f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei sizeof(struct mvs_err_info) - i; 8098f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei resp_len = min(resp_len, max_resp_len); 8108f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 8118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei req_len = sizeof(struct ssp_frame_hdr) + 28; 812b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 813b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* request, response lengths */ 814b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4)); 815b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 816b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik /* generate open address frame hdr (first 12 bytes) */ 81720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* initiator, SSP, ftype 1h */ 81820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan buf_oaf[0] = (1 << 7) | (PROTOCOL_SSP << 4) | 0x1; 81920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan buf_oaf[1] = dev->linkrate & 0xf; 82020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan *(u16 *)(buf_oaf + 2) = cpu_to_be16(mvi_dev->device_id + 1); 82120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memcpy(buf_oaf + 4, dev->sas_addr, SAS_ADDR_SIZE); 822b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 8238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei /* fill in SSP frame header (Command Table.SSP frame header) */ 8248f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei ssp_hdr = (struct ssp_frame_hdr *)buf_cmd; 82520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 82620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (is_tmf) 82720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan ssp_hdr->frame_type = SSP_TASK; 82820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 82920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan ssp_hdr->frame_type = SSP_COMMAND; 83020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 83120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memcpy(ssp_hdr->hashed_dest_addr, dev->hashed_sas_addr, 832b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik HASHED_SAS_ADDR_SIZE); 833b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memcpy(ssp_hdr->hashed_src_addr, 83420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev->hashed_sas_addr, HASHED_SAS_ADDR_SIZE); 835b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik ssp_hdr->tag = cpu_to_be16(tag); 836b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 83720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* fill in IU for TASK and Command Frame */ 838b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik buf_cmd += sizeof(*ssp_hdr); 839b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik memcpy(buf_cmd, &task->ssp_task.LUN, 8); 840b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 84120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (ssp_hdr->frame_type != SSP_TASK) { 84220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan buf_cmd[9] = fburst | task->ssp_task.task_attr | 84320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan (task->ssp_task.task_prio << 3); 84420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memcpy(buf_cmd + 12, &task->ssp_task.cdb, 16); 84520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else{ 84620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan buf_cmd[10] = tmf->tmf; 84720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan switch (tmf->tmf) { 84820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case TMF_ABORT_TASK: 84920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case TMF_QUERY_TASK: 85020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan buf_cmd[12] = 85120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan (tmf->tag_of_task_to_be_managed >> 8) & 0xff; 85220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan buf_cmd[13] = 85320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmf->tag_of_task_to_be_managed & 0xff; 85420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 85520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan default: 85620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 85720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 858b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 85920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* fill in PRD (scatter/gather) table, if any */ 86020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->make_prd(task->scatter, tei->n_elem, buf_prd); 861b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik return 0; 862b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 863b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 86420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == NO_DEVICE))) 86520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags, 8660b84b7094e87769120def1e703b8b4d037281038Andy Yan struct completion *completion,int is_tmf, 8670b84b7094e87769120def1e703b8b4d037281038Andy Yan struct mvs_tmf_task *tmf) 868b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 8698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct domain_device *dev = task->dev; 8709870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; 8719870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan struct mvs_info *mvi = mvi_dev->mvi_info; 872b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik struct mvs_task_exec_info tei; 8738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei struct sas_task *t = task; 8744e52fc0a0a2ec2158691efba3f149f6416481255Ke Wei struct mvs_slot_info *slot; 8758f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 tag = 0xdeadbeef, rc, n_elem = 0; 8768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei u32 n = num, pass = 0; 8779dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas unsigned long flags = 0, flags_libsas = 0; 878b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 87920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!dev->port) { 88020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct task_status_struct *tsm = &t->task_status; 88120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 88220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tsm->resp = SAS_TASK_UNDELIVERED; 88320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tsm->stat = SAS_PHY_DOWN; 8849dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (dev->dev_type != SATA_DEV) 8859dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas t->task_done(t); 88620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return 0; 88720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 88820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 8890b84b7094e87769120def1e703b8b4d037281038Andy Yan spin_lock_irqsave(&mvi->lock, flags); 8908f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei do { 8914e52fc0a0a2ec2158691efba3f149f6416481255Ke Wei dev = t->dev; 892f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan mvi_dev = dev->lldd_dev; 89320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (DEV_IS_GONE(mvi_dev)) { 89420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi_dev) 89520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("device %d not ready.\n", 89620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_dev->device_id); 89720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 89820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("device %016llx not ready.\n", 89920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan SAS_ADDR(dev->sas_addr)); 90020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 90120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = SAS_PHY_DOWN; 90220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto out_done; 90320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 90420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 90520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (dev->port->id >= mvi->chip->n_phy) 90620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tei.port = &mvi->port[dev->port->id - mvi->chip->n_phy]; 90720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 90820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tei.port = &mvi->port[dev->port->id]; 909b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 9109dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (tei.port && !tei.port->port_attached) { 911dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (sas_protocol_ata(t->task_proto)) { 9129dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct task_status_struct *ts = &t->task_status; 9139dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 91420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("port %d does not" 91520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan "attached device.\n", dev->port->id); 9169dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas ts->stat = SAS_PROTO_RESPONSE; 9179dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas ts->stat = SAS_PHY_DOWN; 9189dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas spin_unlock_irqrestore(dev->sata_dev.ap->lock, 9199dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas flags_libsas); 9209dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas spin_unlock_irqrestore(&mvi->lock, flags); 9219dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas t->task_done(t); 9229dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas spin_lock_irqsave(&mvi->lock, flags); 9239dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas spin_lock_irqsave(dev->sata_dev.ap->lock, 9249dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas flags_libsas); 9259dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (n > 1) 9269dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas t = list_entry(t->list.next, 9279dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct sas_task, list); 9289dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas continue; 929dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } else { 930dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct task_status_struct *ts = &t->task_status; 931dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik ts->resp = SAS_TASK_UNDELIVERED; 932dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik ts->stat = SAS_PHY_DOWN; 933dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik t->task_done(t); 934dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (n > 1) 935dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik t = list_entry(t->list.next, 936dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct sas_task, list); 937dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik continue; 938dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 939dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 940dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 941dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!sas_protocol_ata(t->task_proto)) { 942dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (t->num_scatter) { 94320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan n_elem = dma_map_sg(mvi->dev, 94420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan t->scatter, 945dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik t->num_scatter, 946dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik t->data_dir); 947dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!n_elem) { 948dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = -ENOMEM; 949dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out; 950dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 951dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 952dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } else { 953dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik n_elem = t->num_scatter; 954dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 955dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 956dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = mvs_tag_alloc(mvi, &tag); 957dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (rc) 958dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out; 959dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 960dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik slot = &mvi->slot_info[tag]; 96120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 96220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 963dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik t->lldd_task = NULL; 964dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik slot->n_elem = n_elem; 96520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan slot->slot_tag = tag; 966dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik memset(slot->buf, 0, MVS_SLOT_BUF_SZ); 96720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 968dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik tei.task = t; 969dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik tei.hdr = &mvi->slot[tag]; 970dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik tei.tag = tag; 971dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik tei.n_elem = n_elem; 972dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik switch (t->task_proto) { 973dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_SMP: 974dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = mvs_task_prep_smp(mvi, &tei); 975dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 976dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_SSP: 97720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_task_prep_ssp(mvi, &tei, is_tmf, tmf); 978dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 979dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_SATA: 980dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_STP: 981dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: 982dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = mvs_task_prep_ata(mvi, &tei); 983dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 984dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik default: 98520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_ERR, mvi->dev, 9869dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas "unknown sas_task proto: 0x%x\n", 9879dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas t->task_proto); 988dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = -EINVAL; 989dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 990dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 991dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 99220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rc) { 99320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("rc is %x\n", rc); 994dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto err_out_tag; 99520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 996dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik slot->task = t; 997dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik slot->port = tei.port; 998f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan t->lldd_task = slot; 99920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan list_add_tail(&slot->entry, &tei.port->list); 1000dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* TODO: select normal or high priority */ 1001dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik spin_lock(&t->task_state_lock); 1002dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik t->task_state_flags |= SAS_TASK_AT_INITIATOR; 1003dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik spin_unlock(&t->task_state_lock); 1004dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1005dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_hba_memory_dump(mvi, tag, t->task_proto); 10069dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvi_dev->running_req++; 1007dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik ++pass; 1008dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); 1009dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (n > 1) 1010dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik t = list_entry(t->list.next, struct sas_task, list); 10119dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (likely(pass)) 10129dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas MVS_CHIP_DISP->start_delivery(mvi, (mvi->tx_prod - 1) & 10139dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas (MVS_CHIP_SLOT_SZ - 1)); 10149dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 1015dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } while (--n); 1016dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik rc = 0; 1017dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik goto out_done; 1018dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1019dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikerr_out_tag: 1020dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_tag_free(mvi, tag); 1021dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikerr_out: 102220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 102320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc); 1024dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!sas_protocol_ata(t->task_proto)) 1025dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (n_elem) 102620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_unmap_sg(mvi->dev, t->scatter, n_elem, 1027dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik t->data_dir); 1028dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikout_done: 10290b84b7094e87769120def1e703b8b4d037281038Andy Yan spin_unlock_irqrestore(&mvi->lock, flags); 1030dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return rc; 1031dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1032dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 103320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_queue_command(struct sas_task *task, const int num, 103420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan gfp_t gfp_flags) 103520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 10360b84b7094e87769120def1e703b8b4d037281038Andy Yan return mvs_task_exec(task, num, gfp_flags, NULL, 0, NULL); 103720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 103820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 1039dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc) 1040dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 1041dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik u32 slot_idx = rx_desc & RXQ_SLOT_MASK; 1042dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_tag_clear(mvi, slot_idx); 1043dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1044dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1045dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task, 1046dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_slot_info *slot, u32 slot_idx) 1047dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 104820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!slot->task) 104920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return; 1050dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!sas_protocol_ata(task->task_proto)) 1051dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (slot->n_elem) 105220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_unmap_sg(mvi->dev, task->scatter, 1053dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik slot->n_elem, task->data_dir); 1054dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1055dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik switch (task->task_proto) { 1056dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_SMP: 105720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_unmap_sg(mvi->dev, &task->smp_task.smp_resp, 1, 1058dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik PCI_DMA_FROMDEVICE); 105920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dma_unmap_sg(mvi->dev, &task->smp_task.smp_req, 1, 1060dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik PCI_DMA_TODEVICE); 1061dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 1062dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1063dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_SATA: 1064dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_STP: 1065dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_SSP: 1066dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik default: 1067dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik /* do nothing */ 1068dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 1069dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 107020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan list_del_init(&slot->entry); 1071dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik task->lldd_task = NULL; 1072dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik slot->task = NULL; 1073dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik slot->port = NULL; 107420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan slot->slot_tag = 0xFFFFFFFF; 107520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_slot_free(mvi, slot_idx); 1076dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1077dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1078dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic void mvs_update_wideport(struct mvs_info *mvi, int i) 1079dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 1080dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_phy *phy = &mvi->phy[i]; 1081dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_port *port = phy->port; 1082dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik int j, no; 1083dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 108420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for_each_phy(port->wide_port_phymap, j, no) { 108520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (j & 1) { 108620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_addr(mvi, no, 108720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan PHYR_WIDE_PORT); 108820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_data(mvi, no, 1089dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik port->wide_port_phymap); 1090dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } else { 109120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_addr(mvi, no, 109220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan PHYR_WIDE_PORT); 109320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_data(mvi, no, 109420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 0); 1095dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 109620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 1097dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1098dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1099dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic u32 mvs_is_phy_ready(struct mvs_info *mvi, int i) 1100dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 1101dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik u32 tmp; 1102dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_phy *phy = &mvi->phy[i]; 110320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_port *port = phy->port; 1104dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 110520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, i); 1106dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if ((tmp & PHY_READY_MASK) && !(phy->irq_status & PHYEV_POOF)) { 1107dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!port) 1108dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik phy->phy_attached = 1; 1109dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return tmp; 1110dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 1111dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1112dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (port) { 1113dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (phy->phy_type & PORT_TYPE_SAS) { 1114dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik port->wide_port_phymap &= ~(1U << i); 1115dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!port->wide_port_phymap) 1116dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik port->port_attached = 0; 1117dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_update_wideport(mvi, i); 1118dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } else if (phy->phy_type & PORT_TYPE_SATA) 1119dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik port->port_attached = 0; 1120dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik phy->port = NULL; 1121dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik phy->phy_attached = 0; 1122dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik phy->phy_type &= ~(PORT_TYPE_SAS | PORT_TYPE_SATA); 1123dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 1124dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return 0; 1125dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1126dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1127dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf) 1128dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 1129dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik u32 *s = (u32 *) buf; 1130dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1131dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (!s) 1132dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return NULL; 1133dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 113420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3); 113520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan s[3] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); 1136dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 113720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG2); 113820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan s[2] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); 1139dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 114020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG1); 114120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan s[1] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); 1142dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 114320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG0); 114420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan s[0] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i); 114520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 114620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* Workaround: take some ATAPI devices for ATA */ 114720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (((s[1] & 0x00FFFFFF) == 0x00EB1401) && (*(u8 *)&s[3] == 0x01)) 114820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan s[1] = 0x00EB1401 | (*((u8 *)&s[1] + 3) & 0x10); 1149dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1150f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan return s; 1151dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1152dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1153dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzikstatic u32 mvs_is_sig_fis_received(u32 irq_status) 1154dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 1155dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return irq_status & PHYEV_SIG_FIS; 1156dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1157dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 115820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st) 1159dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 1160dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_phy *phy = &mvi->phy[i]; 116120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_identify_frame *id; 1162b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 116320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan id = (struct sas_identify_frame *)phy->frame_rcvd; 1164b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1165dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (get_st) { 116620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, i); 1167dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik phy->phy_status = mvs_is_phy_ready(mvi, i); 1168dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 11698f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 1170dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (phy->phy_status) { 117120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int oob_done = 0; 117220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_phy *sas_phy = &mvi->phy[i].sas_phy; 1173b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 117420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan oob_done = MVS_CHIP_DISP->oob_done(mvi, i); 117520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 117620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->fix_phy_info(mvi, i, id); 117720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy->phy_type & PORT_TYPE_SATA) { 117820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->identify.target_port_protocols = SAS_PROTOCOL_STP; 117920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvs_is_sig_fis_received(phy->irq_status)) { 118020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->phy_attached = 1; 118120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->att_dev_sas_addr = 118220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan i + mvi->id * mvi->chip->n_phy; 118320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (oob_done) 118420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_phy->oob_mode = SATA_OOB_MODE; 118520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->frame_rcvd_size = 118620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sizeof(struct dev_to_host_fis); 1187f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan mvs_get_d2h_reg(mvi, i, id); 118820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else { 118920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 tmp; 119020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev_printk(KERN_DEBUG, mvi->dev, 119120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan "Phy%d : No sig fis\n", i); 119220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmp = MVS_CHIP_DISP->read_port_irq_mask(mvi, i); 119320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_irq_mask(mvi, i, 119420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmp | PHYEV_SIG_FIS); 119520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->phy_attached = 0; 119620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->phy_type &= ~PORT_TYPE_SATA; 119720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->phy_reset(mvi, i, 0); 119820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto out_done; 119920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 12009dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas } else if (phy->phy_type & PORT_TYPE_SAS 120120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan || phy->att_dev_info & PORT_SSP_INIT_MASK) { 120220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->phy_attached = 1; 1203dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik phy->identify.device_type = 120420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->att_dev_info & PORT_DEV_TYPE_MASK; 1205b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1206dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (phy->identify.device_type == SAS_END_DEV) 1207dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik phy->identify.target_port_protocols = 1208dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik SAS_PROTOCOL_SSP; 1209dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik else if (phy->identify.device_type != NO_DEVICE) 1210dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik phy->identify.target_port_protocols = 1211dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik SAS_PROTOCOL_SMP; 121220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (oob_done) 1213dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sas_phy->oob_mode = SAS_OOB_MODE; 1214dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik phy->frame_rcvd_size = 1215dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik sizeof(struct sas_identify_frame); 1216dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 121720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memcpy(sas_phy->attached_sas_addr, 121820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan &phy->att_dev_sas_addr, SAS_ADDR_SIZE); 1219b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 122020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (MVS_CHIP_DISP->phy_work_around) 122120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->phy_work_around(mvi, i); 1222dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 122320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("port %d attach dev info is %x\n", 122420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan i + mvi->id * mvi->chip->n_phy, phy->att_dev_info); 122520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("port %d attach sas addr is %llx\n", 122620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan i + mvi->id * mvi->chip->n_phy, phy->att_dev_sas_addr); 12274e52fc0a0a2ec2158691efba3f149f6416481255Ke Weiout_done: 1228dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (get_st) 122920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_irq_stat(mvi, i, phy->irq_status); 1230b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1231b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 123220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock) 12338f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 1234dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct sas_ha_struct *sas_ha = sas_phy->ha; 123520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi = NULL; int i = 0, hi; 1236dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik struct mvs_phy *phy = sas_phy->lldd_phy; 123720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_port *sas_port = sas_phy->port; 123820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_port *port; 123920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned long flags = 0; 124020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!sas_port) 124120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return; 12428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 124320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan while (sas_ha->sas_phy[i]) { 124420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (sas_ha->sas_phy[i] == sas_phy) 124520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 124620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan i++; 124720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 124820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan hi = i/((struct mvs_prv_info *)sas_ha->lldd_ha)->n_phy; 124920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = ((struct mvs_prv_info *)sas_ha->lldd_ha)->mvi[hi]; 125020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (sas_port->id >= mvi->chip->n_phy) 125120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan port = &mvi->port[sas_port->id - mvi->chip->n_phy]; 125220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 125320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan port = &mvi->port[sas_port->id]; 125420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (lock) 125520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_lock_irqsave(&mvi->lock, flags); 1256dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik port->port_attached = 1; 1257dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik phy->port = port; 1258dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik if (phy->phy_type & PORT_TYPE_SAS) { 1259dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik port->wide_port_phymap = sas_port->phy_mask; 126020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("set wide port phy map %x\n", sas_port->phy_mask); 1261dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik mvs_update_wideport(mvi, sas_phy->id); 12628f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 126320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (lock) 126420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_unlock_irqrestore(&mvi->lock, flags); 1265dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1266dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 126720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_port_notify_deformed(struct asd_sas_phy *sas_phy, int lock) 1268dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 12699dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct domain_device *dev; 12709dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct mvs_phy *phy = sas_phy->lldd_phy; 12719dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct mvs_info *mvi = phy->mvi; 12729dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct asd_sas_port *port = sas_phy->port; 12739dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas int phy_no = 0; 12749dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 12759dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas while (phy != &mvi->phy[phy_no]) { 12769dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas phy_no++; 12779dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (phy_no >= MVS_MAX_PHYS) 12789dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas return; 12799dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas } 12809dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas list_for_each_entry(dev, &port->dev_list, dev_list_node) 12819dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_do_release_task(phy->mvi, phy_no, NULL); 12829dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 1283dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1284dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 1285dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 128620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_port_formed(struct asd_sas_phy *sas_phy) 128720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 128820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_port_notify_formed(sas_phy, 1); 1289dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1290dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 129120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_port_deformed(struct asd_sas_phy *sas_phy) 1292dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 129320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_port_notify_deformed(sas_phy, 1); 129420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 12958f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 129620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstruct mvs_device *mvs_alloc_dev(struct mvs_info *mvi) 129720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 129820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 dev; 129920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (dev = 0; dev < MVS_MAX_DEVICES; dev++) { 130020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->devices[dev].dev_type == NO_DEVICE) { 130120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->devices[dev].device_id = dev; 130220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return &mvi->devices[dev]; 130320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 13048f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei } 13058121ed420285885654af133a6ca1919590f98917Ke Wei 130620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (dev == MVS_MAX_DEVICES) 130720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("max support %d devices, ignore ..\n", 130820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_MAX_DEVICES); 130920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 131020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return NULL; 13118f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 13128f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 131320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_free_dev(struct mvs_device *mvi_dev) 1314b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 131520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 id = mvi_dev->device_id; 131620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memset(mvi_dev, 0, sizeof(*mvi_dev)); 131720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_dev->device_id = id; 131820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_dev->dev_type = NO_DEVICE; 131920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_dev->dev_status = MVS_DEV_NORMAL; 132020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_dev->taskfileset = MVS_ID_NOT_MAPPED; 132120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 1322b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 132320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_dev_found_notify(struct domain_device *dev, int lock) 132420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 132520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned long flags = 0; 132620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int res = 0; 132720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi = NULL; 132820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct domain_device *parent_dev = dev->parent; 132920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_device *mvi_device; 1330b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 133120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi = mvs_find_dev_mvi(dev); 1332b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 133320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (lock) 133420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_lock_irqsave(&mvi->lock, flags); 133520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 133620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_device = mvs_alloc_dev(mvi); 133720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!mvi_device) { 133820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res = -1; 133920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto found_out; 1340b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1341f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan dev->lldd_dev = mvi_device; 13429dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvi_device->dev_status = MVS_DEV_NORMAL; 134320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_device->dev_type = dev->dev_type; 13449870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan mvi_device->mvi_info = mvi; 134520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) { 134620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int phy_id; 134720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u8 phy_num = parent_dev->ex_dev.num_phys; 134820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct ex_phy *phy; 134920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (phy_id = 0; phy_id < phy_num; phy_id++) { 135020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy = &parent_dev->ex_dev.ex_phy[phy_id]; 135120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (SAS_ADDR(phy->attached_sas_addr) == 135220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan SAS_ADDR(dev->sas_addr)) { 135320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_device->attached_phy = phy_id; 135420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 135520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 135620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 1357b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 135820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy_id == phy_num) { 135920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("Error: no attached dev:%016llx" 136020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan "at ex:%016llx.\n", 136120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan SAS_ADDR(dev->sas_addr), 136220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan SAS_ADDR(parent_dev->sas_addr)); 136320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res = -1; 136420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 1365dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 1366b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 136720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanfound_out: 136820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (lock) 136920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_unlock_irqrestore(&mvi->lock, flags); 137020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return res; 137120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 1372b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 137320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_dev_found(struct domain_device *dev) 137420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 137520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return mvs_dev_found_notify(dev, 1); 137620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 1377b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 13789dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivasvoid mvs_dev_gone_notify(struct domain_device *dev) 137920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 138020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned long flags = 0; 1381f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan struct mvs_device *mvi_dev = dev->lldd_dev; 13829870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan struct mvs_info *mvi = mvi_dev->mvi_info; 1383b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 13849dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas spin_lock_irqsave(&mvi->lock, flags); 1385b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 138620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi_dev) { 138720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("found dev[%d:%x] is gone.\n", 138820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_dev->device_id, mvi_dev->dev_type); 13899dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_release_task(mvi, dev); 139020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_free_reg_set(mvi, mvi_dev); 139120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_free_dev(mvi_dev); 139220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else { 139320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("found dev has gone.\n"); 1394b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 139520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan dev->lldd_dev = NULL; 1396b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 13979dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas spin_unlock_irqrestore(&mvi->lock, flags); 1398b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1399b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1400b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 140120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_dev_gone(struct domain_device *dev) 140220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 14039dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_dev_gone_notify(dev); 140420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 1405b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 140620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic struct sas_task *mvs_alloc_task(void) 140720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 140820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_task *task = kzalloc(sizeof(struct sas_task), GFP_KERNEL); 140920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 141020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task) { 141120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan INIT_LIST_HEAD(&task->list); 141220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_lock_init(&task->task_state_lock); 141320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_state_flags = SAS_TASK_STATE_PENDING; 141420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan init_timer(&task->timer); 141520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan init_completion(&task->completion); 1416b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 141720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return task; 1418dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1419b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 142020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_free_task(struct sas_task *task) 1421dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 142220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task) { 142320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan BUG_ON(!list_empty(&task->list)); 142420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kfree(task); 1425b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 142620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 1427b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 142820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_task_done(struct sas_task *task) 142920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 143020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!del_timer(&task->timer)) 143120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return; 143220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan complete(&task->completion); 1433b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 1434b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 143520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_tmf_timedout(unsigned long data) 1436b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 143720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_task *task = (struct sas_task *)data; 14388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 143920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_state_flags |= SAS_TASK_STATE_ABORTED; 144020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan complete(&task->completion); 144120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 14428f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 144320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan/* XXX */ 144420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan#define MVS_TASK_TIMEOUT 20 144520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic int mvs_exec_internal_tmf_task(struct domain_device *dev, 144620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan void *parameter, u32 para_len, struct mvs_tmf_task *tmf) 144720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 144820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int res, retry; 144920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_task *task = NULL; 14508f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 145120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (retry = 0; retry < 3; retry++) { 145220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task = mvs_alloc_task(); 145320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!task) 145420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return -ENOMEM; 14558f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 145620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->dev = dev; 145720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_proto = dev->tproto; 14588f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 145920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memcpy(&task->ssp_task, parameter, para_len); 146020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_done = mvs_task_done; 14618f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 146220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->timer.data = (unsigned long) task; 146320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->timer.function = mvs_tmf_timedout; 146420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ; 146520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan add_timer(&task->timer); 14668f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 14670b84b7094e87769120def1e703b8b4d037281038Andy Yan res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 1, tmf); 14688f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 146920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (res) { 147020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan del_timer(&task->timer); 147120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("executing internel task failed:%d\n", res); 147220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto ex_err; 147320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 14748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 147520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan wait_for_completion(&task->completion); 147620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res = -TMF_RESP_FUNC_FAILED; 147720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* Even TMF timed out, return direct. */ 147820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if ((task->task_state_flags & SAS_TASK_STATE_ABORTED)) { 147920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!(task->task_state_flags & SAS_TASK_STATE_DONE)) { 148020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("TMF task[%x] timeout.\n", tmf->tmf); 148120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto ex_err; 148220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 148320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 14848f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 148520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->task_status.resp == SAS_TASK_COMPLETE && 148620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_status.stat == SAM_GOOD) { 148720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res = TMF_RESP_FUNC_COMPLETE; 148820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 148920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 1490b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 149120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->task_status.resp == SAS_TASK_COMPLETE && 149220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_status.stat == SAS_DATA_UNDERRUN) { 149320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* no error, but return the number of bytes of 149420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * underrun */ 149520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res = task->task_status.residual; 149620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 149720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 1498b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 149920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->task_status.resp == SAS_TASK_COMPLETE && 150020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_status.stat == SAS_DATA_OVERRUN) { 150120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("blocked task error.\n"); 150220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan res = -EMSGSIZE; 150320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 150420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else { 150520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk(" task to dev %016llx response: 0x%x " 150620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan "status 0x%x\n", 150720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan SAS_ADDR(dev->sas_addr), 150820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_status.resp, 150920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_status.stat); 151020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_free_task(task); 151120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task = NULL; 1512b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 1513dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 1514dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 151520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanex_err: 151620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan BUG_ON(retry == 3 && task != NULL); 151720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task != NULL) 151820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_free_task(task); 151920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return res; 1520dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 1521b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 152220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic int mvs_debug_issue_ssp_tmf(struct domain_device *dev, 152320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u8 *lun, struct mvs_tmf_task *tmf) 1524dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 152520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ssp_task ssp_task; 152620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan DECLARE_COMPLETION_ONSTACK(completion); 152720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!(dev->tproto & SAS_PROTOCOL_SSP)) 152820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return TMF_RESP_FUNC_ESUPP; 1529b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 153020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan strncpy((u8 *)&ssp_task.LUN, lun, 8); 1531b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 153220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return mvs_exec_internal_tmf_task(dev, &ssp_task, 153320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sizeof(ssp_task), tmf); 153420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 15358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 15368f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 153720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan/* Standard mandates link reset for ATA (type 0) 153820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan and hard reset for SSP (type 1) , only for RECOVERY */ 153920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic int mvs_debug_I_T_nexus_reset(struct domain_device *dev) 154020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 154120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int rc; 154220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_phy *phy = sas_find_local_phy(dev); 154320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int reset_type = (dev->dev_type == SATA_DEV || 154420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan (dev->tproto & SAS_PROTOCOL_STP)) ? 0 : 1; 154520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = sas_phy_reset(phy, reset_type); 154620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan msleep(2000); 154720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return rc; 154820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 15498f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 155020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan/* mandatory SAM-3 */ 155120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_lu_reset(struct domain_device *dev, u8 *lun) 155220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 155320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned long flags; 155420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED; 155520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_tmf_task tmf_task; 1556f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan struct mvs_device * mvi_dev = dev->lldd_dev; 15579870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan struct mvs_info *mvi = mvi_dev->mvi_info; 155820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 155920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmf_task.tmf = TMF_LU_RESET; 156020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_dev->dev_status = MVS_DEV_EH; 156120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); 156220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rc == TMF_RESP_FUNC_COMPLETE) { 156320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan num = mvs_find_dev_phyno(dev, phyno); 156420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_lock_irqsave(&mvi->lock, flags); 156520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (i = 0; i < num; i++) 15669dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_release_task(mvi, dev); 156720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_unlock_irqrestore(&mvi->lock, flags); 1568dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 156920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* If failed, fall-through I_T_Nexus reset */ 157020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("%s for device[%x]:rc= %d\n", __func__, 157120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi_dev->device_id, rc); 157220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return rc; 157320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 15748f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 157520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_I_T_nexus_reset(struct domain_device *dev) 157620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 157720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned long flags; 15789dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas int rc = TMF_RESP_FUNC_FAILED; 15799dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev; 15809870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan struct mvs_info *mvi = mvi_dev->mvi_info; 158120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 158220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi_dev->dev_status != MVS_DEV_EH) 158320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return TMF_RESP_FUNC_COMPLETE; 158420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_debug_I_T_nexus_reset(dev); 158520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("%s for device[%x]:rc= %d\n", 158620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan __func__, mvi_dev->device_id, rc); 158720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 158820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* housekeeper */ 158920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_lock_irqsave(&mvi->lock, flags); 15909dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_release_task(mvi, dev); 159120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_unlock_irqrestore(&mvi->lock, flags); 159220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 159320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return rc; 159420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 159520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan/* optional SAM-3 */ 159620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_query_task(struct sas_task *task) 159720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 159820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 tag; 159920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct scsi_lun lun; 160020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_tmf_task tmf_task; 160120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int rc = TMF_RESP_FUNC_FAILED; 160220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 160320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { 160420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task; 160520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct domain_device *dev = task->dev; 16069870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; 16079870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan struct mvs_info *mvi = mvi_dev->mvi_info; 160820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 160920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int_to_scsilun(cmnd->device->lun, &lun); 161020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_find_tag(mvi, task, &tag); 161120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rc == 0) { 161220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = TMF_RESP_FUNC_FAILED; 1613dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return rc; 161420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 16158f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 161620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmf_task.tmf = TMF_QUERY_TASK; 161720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag); 16188f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 161920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_debug_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task); 162020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan switch (rc) { 162120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* The task is still in Lun, release it then */ 162220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case TMF_RESP_FUNC_SUCC: 162320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* The task is not in Lun or failed, reset the phy */ 162420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case TMF_RESP_FUNC_FAILED: 162520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case TMF_RESP_FUNC_COMPLETE: 162620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 16279dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas default: 16289dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas rc = TMF_RESP_FUNC_COMPLETE; 16299dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas break; 163020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 1631dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 163220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("%s:rc= %d\n", __func__, rc); 163320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return rc; 16348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 16358f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 163620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan/* mandatory SAM-3, still need free task/slot info */ 163720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_abort_task(struct sas_task *task) 16388f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 163920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct scsi_lun lun; 164020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_tmf_task tmf_task; 164120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct domain_device *dev = task->dev; 16429870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev; 164324ae163ed33d2b8a70d2f0b1947b401d0a8e8719Jiri Slaby struct mvs_info *mvi; 164420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int rc = TMF_RESP_FUNC_FAILED; 164520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned long flags; 164620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 tag; 16479870d9a2428550e7ac3164a26306ad07a99051aeAndy Yan 16489dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (!mvi_dev) { 16499dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mv_printk("%s:%d TMF_RESP_FUNC_FAILED\n", __func__, __LINE__); 16509dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas rc = TMF_RESP_FUNC_FAILED; 16519dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas } 16529dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 165324ae163ed33d2b8a70d2f0b1947b401d0a8e8719Jiri Slaby mvi = mvi_dev->mvi_info; 165424ae163ed33d2b8a70d2f0b1947b401d0a8e8719Jiri Slaby 165520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_lock_irqsave(&task->task_state_lock, flags); 165620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->task_state_flags & SAS_TASK_STATE_DONE) { 165720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_unlock_irqrestore(&task->task_state_lock, flags); 165820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = TMF_RESP_FUNC_COMPLETE; 165920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto out; 1660dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 166120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_unlock_irqrestore(&task->task_state_lock, flags); 16629dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvi_dev->dev_status = MVS_DEV_EH; 166320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) { 166420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task; 166520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 166620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int_to_scsilun(cmnd->device->lun, &lun); 166720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_find_tag(mvi, task, &tag); 166820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rc == 0) { 166920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("No such tag in %s\n", __func__); 167020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = TMF_RESP_FUNC_FAILED; 167120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return rc; 167220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 16738f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 167420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmf_task.tmf = TMF_ABORT_TASK; 167520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag); 16768f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 167720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_debug_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task); 16788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 167920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* if successful, clear the task and callback forwards.*/ 168020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rc == TMF_RESP_FUNC_COMPLETE) { 168120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 slot_no; 168220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_slot_info *slot; 16838f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 168420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->lldd_task) { 1685f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan slot = task->lldd_task; 168620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan slot_no = (u32) (slot - mvi->slot_info); 16879dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas spin_lock_irqsave(&mvi->lock, flags); 168820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_slot_complete(mvi, slot_no, 1); 16899dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas spin_unlock_irqrestore(&mvi->lock, flags); 169020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 169120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 16929dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 169320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else if (task->task_proto & SAS_PROTOCOL_SATA || 169420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_proto & SAS_PROTOCOL_STP) { 169520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* to do free register_set */ 16969dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (SATA_DEV == dev->dev_type) { 16979dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct mvs_slot_info *slot = task->lldd_task; 16989dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct task_status_struct *tstat; 16999dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas u32 slot_idx = (u32)(slot - mvi->slot_info); 17009dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas tstat = &task->task_status; 17019dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mv_dprintk(KERN_DEBUG "mv_abort_task() mvi=%p task=%p " 17029dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas "slot=%p slot_idx=x%x\n", 17039dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvi, task, slot, slot_idx); 17049dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas tstat->stat = SAS_ABORTED_TASK; 17059dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (mvi_dev && mvi_dev->running_req) 17069dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvi_dev->running_req--; 17079dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (sas_protocol_ata(task->task_proto)) 17089dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_free_reg_set(mvi, mvi_dev); 17099dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_slot_task_free(mvi, task, slot, slot_idx); 17109dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas return -1; 17119dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas } 171220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else { 171320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* SMP */ 17148f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 171520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 171620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanout: 171720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rc != TMF_RESP_FUNC_COMPLETE) 171820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("%s:rc= %d\n", __func__, rc); 1719dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik return rc; 17208f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 17218f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 172220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_abort_task_set(struct domain_device *dev, u8 *lun) 17238f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 172420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int rc = TMF_RESP_FUNC_FAILED; 172520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_tmf_task tmf_task; 17268f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 172720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmf_task.tmf = TMF_ABORT_TASK_SET; 172820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); 1729dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 173020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return rc; 17318f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 17328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 173320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_clear_aca(struct domain_device *dev, u8 *lun) 17348f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 173520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int rc = TMF_RESP_FUNC_FAILED; 173620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_tmf_task tmf_task; 17378f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 173820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmf_task.tmf = TMF_CLEAR_ACA; 173920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); 17408f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 174120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return rc; 174220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 17438f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 174420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_clear_task_set(struct domain_device *dev, u8 *lun) 174520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 174620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int rc = TMF_RESP_FUNC_FAILED; 174720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_tmf_task tmf_task; 17488f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 174920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmf_task.tmf = TMF_CLEAR_TASK_SET; 175020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task); 17518f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 175220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return rc; 1753dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik} 17548f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 175520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task, 175620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 slot_idx, int err) 1757dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik{ 1758f9da3be5afc08c40e7f7a395c8935d500a6898b1Andy Yan struct mvs_device *mvi_dev = task->dev->lldd_dev; 175920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct task_status_struct *tstat = &task->task_status; 176020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct ata_task_resp *resp = (struct ata_task_resp *)tstat->buf; 176120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int stat = SAM_GOOD; 1762e9ff91b6927079307b5d481a93beac4134e923ebKe Wei 17638f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 176420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan resp->frame_len = sizeof(struct dev_to_host_fis); 176520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memcpy(&resp->ending_fis[0], 176620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan SATA_RECEIVED_D2H_FIS(mvi_dev->taskfileset), 176720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sizeof(struct dev_to_host_fis)); 176820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->buf_valid_size = sizeof(*resp); 17699dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (unlikely(err)) { 17709dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (unlikely(err & CMD_ISS_STPD)) 17719dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas stat = SAS_OPEN_REJECT; 17729dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas else 17739dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas stat = SAS_PROTO_RESPONSE; 17749dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas } 17759dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 177620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return stat; 17778f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei} 17788f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 177920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task, 178020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 slot_idx) 17818f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei{ 178220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; 178320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int stat; 178420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 err_dw0 = le32_to_cpu(*(u32 *) (slot->response)); 178520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 tfs = 0; 178620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan enum mvs_port_type type = PORT_TYPE_SAS; 17878f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 178820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (err_dw0 & CMD_ISS_STPD) 178920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->issue_stop(mvi, type, tfs); 179020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 179120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->command_active(mvi, slot_idx); 1792b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 179320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan stat = SAM_CHECK_COND; 1794dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik switch (task->task_proto) { 1795dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_SSP: 179620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan stat = SAS_ABORTED_TASK; 179720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 179820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case SAS_PROTOCOL_SMP: 179920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan stat = SAM_CHECK_COND; 1800dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 180120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 1802dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_SATA: 1803dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik case SAS_PROTOCOL_STP: 180420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: 180520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan { 180620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (err_dw0 == 0x80400002) 180720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("find reserved error, why?\n"); 180820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 180920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->ata_task.use_ncq = 0; 18109dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_sata_done(mvi, task, slot_idx, err_dw0); 1811dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 181220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 1813dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik default: 1814dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik break; 1815dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik } 1816dd4969a892ea522ecf9d7d826ba1531ce044d46fJeff Garzik 181720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return stat; 1818e9ff91b6927079307b5d481a93beac4134e923ebKe Wei} 1819e9ff91b6927079307b5d481a93beac4134e923ebKe Wei 182020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags) 1821b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 182220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 slot_idx = rx_desc & RXQ_SLOT_MASK; 182320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_slot_info *slot = &mvi->slot_info[slot_idx]; 182420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_task *task = slot->task; 182520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_device *mvi_dev = NULL; 182620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct task_status_struct *tstat; 18279dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct domain_device *dev; 18289dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas u32 aborted; 182920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 183020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan void *to; 183120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan enum exec_status sts; 183220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 183320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->exp_req) 183420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->exp_req--; 18359dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (unlikely(!task || !task->lldd_task || !task->dev)) 183620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return -1; 183720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 183820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat = &task->task_status; 18399dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas dev = task->dev; 18409dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvi_dev = dev->lldd_dev; 1841b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 184220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_hba_cq_dump(mvi); 184320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 184420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_lock(&task->task_state_lock); 184520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_state_flags &= 184620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR); 184720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_state_flags |= SAS_TASK_STATE_DONE; 184820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* race condition*/ 184920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED; 185020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_unlock(&task->task_state_lock); 185120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 185220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memset(tstat, 0, sizeof(*tstat)); 185320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->resp = SAS_TASK_COMPLETE; 185420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 185520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (unlikely(aborted)) { 185620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->stat = SAS_ABORTED_TASK; 18579dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (mvi_dev && mvi_dev->running_req) 18589dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvi_dev->running_req--; 185920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (sas_protocol_ata(task->task_proto)) 186020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_free_reg_set(mvi, mvi_dev); 186120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 186220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_slot_task_free(mvi, task, slot, slot_idx); 186320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return -1; 1864b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1865b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 18669dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (unlikely(!mvi_dev || flags)) { 18679dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (!mvi_dev) 18689dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mv_dprintk("port has not device.\n"); 186920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->stat = SAS_PHY_DOWN; 187020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto out; 187120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 1872b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 187320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* error info record present */ 187420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) { 187520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->stat = mvs_slot_err(mvi, task, slot_idx); 18769dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas tstat->resp = SAS_TASK_COMPLETE; 187720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan goto out; 1878b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 1879b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 188020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan switch (task->task_proto) { 188120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case SAS_PROTOCOL_SSP: 188220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* hw says status == 0, datapres == 0 */ 188320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rx_desc & RXQ_GOOD) { 188420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->stat = SAM_GOOD; 188520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->resp = SAS_TASK_COMPLETE; 188620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 188720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* response frame present */ 188820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else if (rx_desc & RXQ_RSP) { 188920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct ssp_response_iu *iu = slot->response + 189020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sizeof(struct mvs_err_info); 189120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_ssp_task_response(mvi->dev, task, iu); 189220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else 189320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->stat = SAM_CHECK_COND; 189420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 1895b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 189620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case SAS_PROTOCOL_SMP: { 189720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct scatterlist *sg_resp = &task->smp_task.smp_resp; 189820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->stat = SAM_GOOD; 189920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan to = kmap_atomic(sg_page(sg_resp), KM_IRQ0); 190020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan memcpy(to + sg_resp->offset, 190120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan slot->response + sizeof(struct mvs_err_info), 190220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sg_dma_len(sg_resp)); 190320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kunmap_atomic(to, KM_IRQ0); 190420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 190520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 19068f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 190720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case SAS_PROTOCOL_SATA: 190820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case SAS_PROTOCOL_STP: 190920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP: { 191020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->stat = mvs_sata_done(mvi, task, slot_idx, 0); 191120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 191220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 1913b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 191420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan default: 191520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tstat->stat = SAM_CHECK_COND; 191620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan break; 191720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 19189dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (!slot->port->port_attached) { 19199dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mv_dprintk("port %d has removed.\n", slot->port->sas_port.id); 19209dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas tstat->stat = SAS_PHY_DOWN; 19219dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas } 19229dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 1923b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 192420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanout: 19259dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (mvi_dev && mvi_dev->running_req) { 19269dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvi_dev->running_req--; 19279dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (sas_protocol_ata(task->task_proto) && !mvi_dev->running_req) 19280f980a871678b7ec143fcb45b31bf9234e4585c8Andy Yan mvs_free_reg_set(mvi, mvi_dev); 19290f980a871678b7ec143fcb45b31bf9234e4585c8Andy Yan } 193020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_slot_task_free(mvi, task, slot, slot_idx); 193120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sts = tstat->stat; 19328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 193320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_unlock(&mvi->lock); 193420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (task->task_done) 193520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task->task_done(task); 193620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 193720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("why has not task_done.\n"); 193820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_lock(&mvi->lock); 1939b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 194020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return sts; 194120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 1942b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 19439dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivasvoid mvs_do_release_task(struct mvs_info *mvi, 194420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int phy_no, struct domain_device *dev) 194520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 19469dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas u32 slot_idx; 194720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_phy *phy; 194820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_port *port; 194920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_slot_info *slot, *slot2; 1950b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 195120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy = &mvi->phy[phy_no]; 195220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan port = phy->port; 195320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!port) 195420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return; 19559dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas /* clean cmpl queue in case request is already finished */ 19569dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_int_rx(mvi, false); 19579dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 19589dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 1959b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 196020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan list_for_each_entry_safe(slot, slot2, &port->list, entry) { 196120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_task *task; 196220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan slot_idx = (u32) (slot - mvi->slot_info); 196320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan task = slot->task; 1964b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 196520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (dev && task->dev != dev) 196620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan continue; 19678f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 196820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_printk("Release slot [%x] tag[%x], task [%p]:\n", 196920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan slot_idx, slot->slot_tag, task); 19709dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas MVS_CHIP_DISP->command_active(mvi, slot_idx); 1971b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 197220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_slot_complete(mvi, slot_idx, 1); 1973b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 197420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 1975b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 19769dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivasvoid mvs_release_task(struct mvs_info *mvi, 19779dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas struct domain_device *dev) 19789dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas{ 19799dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas int i, phyno[WIDE_PORT_MAX_PHY], num; 19809dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas /* housekeeper */ 19819dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas num = mvs_find_dev_phyno(dev, phyno); 19829dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas for (i = 0; i < num; i++) 19839dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_do_release_task(mvi, phyno[i], dev); 19849dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas} 19859dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 198620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_phy_disconnected(struct mvs_phy *phy) 198720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 198820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->phy_attached = 0; 198920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->att_dev_info = 0; 199020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->att_dev_sas_addr = 0; 199120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 199220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 199320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_work_queue(struct work_struct *work) 199420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 199520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct delayed_work *dw = container_of(work, struct delayed_work, work); 199620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q); 199720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi = mwq->mvi; 199820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan unsigned long flags; 1999b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 200020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_lock_irqsave(&mvi->lock, flags); 200120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mwq->handler & PHY_PLUG_EVENT) { 200220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 phy_no = (unsigned long) mwq->data; 200320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sas_ha = mvi->sas; 200420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_phy *phy = &mvi->phy[phy_no]; 200520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_phy *sas_phy = &phy->sas_phy; 200620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 200720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy->phy_event & PHY_PLUG_OUT) { 200820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 tmp; 200920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_identify_frame *id; 201020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan id = (struct sas_identify_frame *)phy->frame_rcvd; 201120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmp = MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no); 201220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->phy_event &= ~PHY_PLUG_OUT; 201320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!(tmp & PHY_READY_MASK)) { 201420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_phy_disconnected(sas_phy); 201520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_phy_disconnected(phy); 201620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_ha->notify_phy_event(sas_phy, 201720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan PHYE_LOSS_OF_SIGNAL); 201820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("phy%d Removed Device\n", phy_no); 201920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else { 202020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->detect_porttype(mvi, phy_no); 202120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_update_phyinfo(mvi, phy_no, 1); 202220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_bytes_dmaed(mvi, phy_no); 202320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_port_notify_formed(sas_phy, 0); 202420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("phy%d Attached Device\n", phy_no); 202520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 202620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 202720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 202820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan list_del(&mwq->entry); 202920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan spin_unlock_irqrestore(&mvi->lock, flags); 203020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan kfree(mwq); 203120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 20328f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 203320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic int mvs_handle_event(struct mvs_info *mvi, void *data, int handler) 203420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 203520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_wq *mwq; 203620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int ret = 0; 203720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 203820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mwq = kmalloc(sizeof(struct mvs_wq), GFP_ATOMIC); 203920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mwq) { 204020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mwq->mvi = mvi; 204120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mwq->data = data; 204220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mwq->handler = handler; 204320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MV_INIT_DELAYED_WORK(&mwq->work_q, mvs_work_queue, mwq); 204420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan list_add_tail(&mwq->entry, &mvi->wq_list); 204520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan schedule_delayed_work(&mwq->work_q, HZ * 2); 204620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else 204720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan ret = -ENOMEM; 204820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 204920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return ret; 205020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 2051b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 205220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_sig_time_out(unsigned long tphy) 205320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 205420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_phy *phy = (struct mvs_phy *)tphy; 205520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_info *mvi = phy->mvi; 205620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u8 phy_no; 205720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 205820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan for (phy_no = 0; phy_no < mvi->chip->n_phy; phy_no++) { 205920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (&mvi->phy[phy_no] == phy) { 206020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("Get signature time out, reset phy %d\n", 206120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy_no+mvi->id*mvi->chip->n_phy); 206220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->phy_reset(mvi, phy_no, 1); 206320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 2064b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik } 206520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 2066b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 206720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanstatic void mvs_sig_remove_timer(struct mvs_phy *phy) 206820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 206920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy->timer.function) 207020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan del_timer(&phy->timer); 207120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->timer.function = NULL; 207220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan} 2073b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 207420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanvoid mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events) 207520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan{ 207620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 tmp; 207720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct sas_ha_struct *sas_ha = mvi->sas; 207820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct mvs_phy *phy = &mvi->phy[phy_no]; 207920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan struct asd_sas_phy *sas_phy = &phy->sas_phy; 20808f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 208120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->irq_status = MVS_CHIP_DISP->read_port_irq_stat(mvi, phy_no); 208220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("port %d ctrl sts=0x%X.\n", phy_no+mvi->id*mvi->chip->n_phy, 208320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->read_phy_ctl(mvi, phy_no)); 208420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("Port %d irq sts = 0x%X\n", phy_no+mvi->id*mvi->chip->n_phy, 208520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->irq_status); 20868f261aaf9be5c1246013cf6a65b98586d24832a5Ke Wei 208720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* 208820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * events is port event now , 208920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * we need check the interrupt status which belongs to per port. 209020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan */ 2091b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 20929dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (phy->irq_status & PHYEV_DCDR_ERR) { 209320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("port %d STP decoding error.\n", 20949dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas phy_no + mvi->id*mvi->chip->n_phy); 20959dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas } 209620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 209720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy->irq_status & PHYEV_POOF) { 209820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!(phy->phy_event & PHY_PLUG_OUT)) { 209920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int dev_sata = phy->phy_type & PORT_TYPE_SATA; 210020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan int ready; 21019dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mvs_do_release_task(mvi, phy_no, NULL); 210220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->phy_event |= PHY_PLUG_OUT; 21039dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas MVS_CHIP_DISP->clear_srs_irq(mvi, 0, 1); 210420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_handle_event(mvi, 210520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan (void *)(unsigned long)phy_no, 210620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan PHY_PLUG_EVENT); 210720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan ready = mvs_is_phy_ready(mvi, phy_no); 210820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!ready) 210920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("phy%d Unplug Notice\n", 211020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy_no + 211120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->id * mvi->chip->n_phy); 211220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (ready || dev_sata) { 211320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (MVS_CHIP_DISP->stp_reset) 211420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->stp_reset(mvi, 211520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy_no); 211620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan else 211720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->phy_reset(mvi, 211820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy_no, 0); 211920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return; 212020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 212120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 212220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 2123b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 212420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy->irq_status & PHYEV_COMWAKE) { 212520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmp = MVS_CHIP_DISP->read_port_irq_mask(mvi, phy_no); 212620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_irq_mask(mvi, phy_no, 212720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmp | PHYEV_SIG_FIS); 212820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy->timer.function == NULL) { 212920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->timer.data = (unsigned long)phy; 213020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->timer.function = mvs_sig_time_out; 213120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->timer.expires = jiffies + 10*HZ; 213220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan add_timer(&phy->timer); 213320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 213420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 213520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy->irq_status & (PHYEV_SIG_FIS | PHYEV_ID_DONE)) { 213620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->phy_status = mvs_is_phy_ready(mvi, phy_no); 213720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_sig_remove_timer(phy); 213820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("notify plug in on phy[%d]\n", phy_no); 213920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy->phy_status) { 214020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mdelay(10); 214120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->detect_porttype(mvi, phy_no); 214220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy->phy_type & PORT_TYPE_SATA) { 214320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmp = MVS_CHIP_DISP->read_port_irq_mask( 214420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi, phy_no); 214520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan tmp &= ~PHYEV_SIG_FIS; 214620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_irq_mask(mvi, 214720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy_no, tmp); 214820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 214920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_update_phyinfo(mvi, phy_no, 0); 21509dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas if (phy->phy_type & PORT_TYPE_SAS) { 21519dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas MVS_CHIP_DISP->phy_reset(mvi, phy_no, 2); 21529dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas mdelay(10); 21539dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas } 21549dc9fd9484c5168d23fe855e6c56543d96b6695bSrinivas 215520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_bytes_dmaed(mvi, phy_no); 215620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* whether driver is going to handle hot plug */ 215720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (phy->phy_event & PHY_PLUG_OUT) { 215820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_port_notify_formed(sas_phy, 0); 215920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy->phy_event &= ~PHY_PLUG_OUT; 216020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 216120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else { 216220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("plugin interrupt but phy%d is gone\n", 216320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy_no + mvi->id*mvi->chip->n_phy); 216420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 216520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else if (phy->irq_status & PHYEV_BROAD_CH) { 216620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mv_dprintk("port %d broadcast change.\n", 216720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan phy_no + mvi->id*mvi->chip->n_phy); 216820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* exception for Samsung disk drive*/ 216920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mdelay(1000); 217020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD); 217120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 217220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status); 2173b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2174b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 217520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yanint mvs_int_rx(struct mvs_info *mvi, bool self_clear) 2176b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik{ 217720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan u32 rx_prod_idx, rx_desc; 217820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan bool attn = false; 2179b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 218020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* the first dword in the RX ring is special: it contains 218120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * a mirror of the hardware's RX producer index, so that 218220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * we don't have to stall the CPU reading that register. 218320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * The actual RX ring is offset by one dword, due to this. 218420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan */ 218520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rx_prod_idx = mvi->rx_cons; 218620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->rx_cons = le32_to_cpu(mvi->rx[0]); 218720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->rx_cons == 0xfff) /* h/w hasn't touched RX ring yet */ 218820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return 0; 2189b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 219020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* The CMPL_Q may come late, read from register and try again 219120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * note: if coalescing is enabled, 219220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan * it will need to read from register every time for sure 219320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan */ 219420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (unlikely(mvi->rx_cons == rx_prod_idx)) 219520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvi->rx_cons = MVS_CHIP_DISP->rx_update(mvi) & RX_RING_SZ_MASK; 219620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 219720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (mvi->rx_cons == rx_prod_idx) 219820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return 0; 219920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 220020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan while (mvi->rx_cons != rx_prod_idx) { 220120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan /* increment our internal RX consumer pointer */ 220220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rx_prod_idx = (rx_prod_idx + 1) & (MVS_RX_RING_SZ - 1); 220320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan rx_desc = le32_to_cpu(mvi->rx[rx_prod_idx + 1]); 220420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 220520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (likely(rx_desc & RXQ_DONE)) 220620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_slot_complete(mvi, rx_desc, 0); 220720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (rx_desc & RXQ_ATTN) { 220820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan attn = true; 220920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else if (rx_desc & RXQ_ERR) { 221020b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (!(rx_desc & RXQ_DONE)) 221120b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_slot_complete(mvi, rx_desc, 0); 221220b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } else if (rx_desc & RXQ_SLOT_RESET) { 221320b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan mvs_slot_free(mvi, rx_desc); 221420b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 221520b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan } 221620b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan 221720b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan if (attn && self_clear) 221820b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan MVS_CHIP_DISP->int_full(mvi); 221920b09c2992fefbe78f8cede7b404fb143a413c52Andy Yan return 0; 2220b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik} 2221b5762948263dd5e9725a380e7a9626f99e40ae9dJeff Garzik 2222