* [PATCH] Marvell 6440 SAS/SATA driver (draft)
@ 2008-01-10 6:53 Ke Wei
2008-01-10 7:09 ` Jeff Garzik
2008-01-18 18:53 ` James Bottomley
0 siblings, 2 replies; 6+ messages in thread
From: Ke Wei @ 2008-01-10 6:53 UTC (permalink / raw)
To: linux-scsi; +Cc: kewei, qswang, jfeng, jeff
The 88SE6440 driver :
The driver is based on bare code from Jeff Garzik. And it can work
under linux kernel 2.6.23.
By far, Can discover and find SAS HDD, but SATA is currently
unsupported. Command queue depth can be above 1.
Most error handling, and some phy handling code is notably missing.
contains the following updates:
--- mvsas_orig.c 2007-12-06 19:21:32.000000000 -0500
+++ mvsas.c 2008-01-09 04:53:14.000000000 -0500
@@ -2,6 +2,7 @@
mvsas.c - Marvell 88SE6440 SAS/SATA support
Copyright 2007 Red Hat, Inc.
+ Copyright 2008 Marvell.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as
@@ -37,8 +38,10 @@
#include <scsi/libsas.h>
#include <asm/io.h>
-#define DRV_NAME "mvsas"
-#define DRV_VERSION "0.1"
+#define DRV_NAME "mvsas"
+#define DRV_VERSION "0.2"
+#define _MV_DUMP 0
+#define MVS_PRINTK(_x_,...) printk(KERN_NOTICE DRV_NAME ": " _x_ , ##
__VA_ARGS__)
#define mr32(reg) readl(regs + MVS_##reg)
#define mw32(reg,val) writel((val), regs + MVS_##reg)
@@ -47,9 +50,42 @@
readl(regs + MVS_##reg); \
} while (0)
+#define MVS_BIT(x) (1L << (x))
+
+#define PORT_TYPE_SATA MVS_BIT(0)
+#define PORT_TYPE_SAS MVS_BIT(1)
+
+#define READ_PORT_CONFIG_DATA(i) \
+ ((i>3)?mr32(P4_CFG_DATA+(i-4)*8):mr32(P0_CFG_DATA+i*8))
+#define WRITE_PORT_CONFIG_DATA(i,tmp) \
+ {if(i>3)mw32(P4_CFG_DATA+(i-4)*8,tmp);else mw32(P0_CFG_DATA+i*8,tmp);}
+#define WRITE_PORT_CONFIG_ADDR(i,tmp) \
+ {if(i>3)mw32(P4_CFG_ADDR+(i-4)*8,tmp);else mw32(P0_CFG_ADDR+i*8,tmp);}
+
+#define READ_PORT_PHY_CONTROL(i) \
+ ((i>3)?mr32(P4_SER_CTLSTAT+(i-4)*4):mr32(P0_SER_CTLSTAT+i*4))
+#define WRITE_PORT_PHY_CONTROL(i,tmp) \
+ {if(i>3)mw32(P4_SER_CTLSTAT+(i-4)*4,tmp);else
mw32(P0_SER_CTLSTAT+i*4,tmp);}
+
+#define READ_PORT_VSR_DATA(i) \
+ ((i>3)?mr32(P4_VSR_DATA+(i-4)*8):mr32(P0_VSR_DATA+i*8))
+#define WRITE_PORT_VSR_DATA(i,tmp) \
+ {if(i>3)mw32(P4_VSR_DATA+(i-4)*8,tmp);else mw32(P0_VSR_DATA+i*8,tmp);}
+#define WRITE_PORT_VSR_ADDR(i,tmp) \
+ {if(i>3)mw32(P4_VSR_ADDR+(i-4)*8,tmp);else mw32(P0_VSR_ADDR+i*8,tmp);}
+
+#define READ_PORT_IRQ_STAT(i) \
+ ((i>3)?mr32(P4_INT_STAT+(i-4)*8):mr32(P0_INT_STAT+i*8))
+#define WRITE_PORT_IRQ_STAT(i,tmp) \
+ {if(i>3)mw32(P4_INT_STAT+(i-4)*8,tmp);else mw32(P0_INT_STAT+i*8,tmp);}
+#define READ_PORT_IRQ_MASK(i) \
+ ((i>3)?mr32(P4_INT_MASK+(i-4)*8):mr32(P0_INT_MASK+i*8))
+#define WRITE_PORT_IRQ_MASK(i,tmp) \
+ {if(i>3)mw32(P4_INT_MASK+(i-4)*8,tmp);else mw32(P0_INT_MASK+i*8,tmp);}
+
/* driver compile-time configuration */
enum driver_configuration {
- MVS_TX_RING_SZ = 1024, /* TX ring size (12-bit) */
+ MVS_TX_RING_SZ = 512, /* TX ring size (12-bit) */
MVS_RX_RING_SZ = 1024, /* RX ring size (12-bit) */
/* software requires power-of-2
ring size */
@@ -89,7 +125,7 @@
MVS_GBL_CTL = 0x04, /* global control */
MVS_GBL_INT_STAT = 0x08, /* global irq status */
MVS_GBL_PI = 0x0C, /* ports implemented bitmask */
- MVS_GBL_PORT_TYPE = 0x00, /* port type */
+ MVS_GBL_PORT_TYPE = 0xa0, /* port type */
MVS_CTL = 0x100, /* SAS/SATA port configuration */
MVS_PCS = 0x104, /* SAS/SATA port control/status */
@@ -102,11 +138,12 @@
MVS_TX_LO = 0x124, /* TX (delivery) ring addr */
MVS_TX_HI = 0x128,
- MVS_RX_PROD_IDX = 0x12C, /* RX producer pointer */
- MVS_RX_CONS_IDX = 0x130, /* RX consumer pointer (RO) */
+ MVS_TX_PROD_IDX = 0x12C, /* TX producer pointer */
+ MVS_TX_CONS_IDX = 0x130, /* TX consumer pointer (RO) */
MVS_RX_CFG = 0x134, /* RX configuration */
MVS_RX_LO = 0x138, /* RX (completion) ring addr */
MVS_RX_HI = 0x13C,
+ MVS_RX_CONS_IDX = 0x140, /* RX consumer pointer (RO) */
MVS_INT_COAL = 0x148, /* Int coalescing config */
MVS_INT_COAL_TMOUT = 0x14C, /* Int coalescing timeout */
@@ -117,9 +154,12 @@
/* ports 1-3 follow after this */
MVS_P0_INT_STAT = 0x160, /* port0 interrupt status */
MVS_P0_INT_MASK = 0x164, /* port0 interrupt mask */
+ MVS_P4_INT_STAT = 0x200, /* Port 4 interrupt status */
+ MVS_P4_INT_MASK = 0x204, /* Port 4 interrupt enable/disable mask */
/* ports 1-3 follow after this */
MVS_P0_SER_CTLSTAT = 0x180, /* port0 serial control/status */
+ MVS_P4_SER_CTLSTAT = 0x220, /* port4 serial control/status */
MVS_CMD_ADDR = 0x1B8, /* Command register port (addr) */
MVS_CMD_DATA = 0x1BC, /* Command register port (data) */
@@ -127,6 +167,14 @@
/* ports 1-3 follow after this */
MVS_P0_CFG_ADDR = 0x1C0, /* port0 phy register address */
MVS_P0_CFG_DATA = 0x1C4, /* port0 phy register data */
+ MVS_P4_CFG_ADDR = 0x230, /* Port 4 config address */
+ MVS_P4_CFG_DATA = 0x234, /* Port 4 config data */
+
+ /* ports 1-3 follow after this */
+ MVS_P0_VSR_ADDR = 0x1E0, /* port0 vendor specific register address */
+ MVS_P0_VSR_DATA = 0x1E4, /* port0 vendor specific register data */
+ MVS_P4_VSR_ADDR = 0x250, /* port 4 Vendor Specific Register addr */
+ MVS_P4_VSR_DATA = 0x254, /* port 4 Vendor Specific Register Data */
};
enum hw_register_bits {
@@ -140,8 +188,31 @@
/* MVS_GBL_PORT_TYPE */ /* shl for ports 1-3 */
SATA_TARGET = (1U << 16), /* port0 SATA target enable */
- AUTO_DET = (1U << 8), /* port0 SAS/SATA autodetect */
- SAS_MODE = (1U << 0), /* port0 SAS(1), SATA(0) mode */
+ MODE_AUTO_DET_PORT7 = (1U << 15), /* port0 SAS/SATA autodetect */
+ MODE_AUTO_DET_PORT6 = (1U << 14),
+ MODE_AUTO_DET_PORT5 = (1U << 13),
+ MODE_AUTO_DET_PORT4 = (1U << 12),
+ MODE_AUTO_DET_PORT3 = (1U << 11),
+ MODE_AUTO_DET_PORT2 = (1U << 10),
+ MODE_AUTO_DET_PORT1 = (1U << 9),
+ MODE_AUTO_DET_PORT0 = (1U << 8),
+ MODE_AUTO_DET_EN = MODE_AUTO_DET_PORT0 | MODE_AUTO_DET_PORT1 |
+ MODE_AUTO_DET_PORT2 | MODE_AUTO_DET_PORT3 |
+ MODE_AUTO_DET_PORT4 | MODE_AUTO_DET_PORT5 |
+ MODE_AUTO_DET_PORT6 | MODE_AUTO_DET_PORT7,
+ MODE_SAS_PORT7_MASK = (1U << 7), /* port0 SAS(1), SATA(0) mode */
+ MODE_SAS_PORT6_MASK = (1U << 6),
+ MODE_SAS_PORT5_MASK = (1U << 5),
+ MODE_SAS_PORT4_MASK = (1U << 4),
+ MODE_SAS_PORT3_MASK = (1U << 3),
+ MODE_SAS_PORT2_MASK = (1U << 2),
+ MODE_SAS_PORT1_MASK = (1U << 1),
+ MODE_SAS_PORT0_MASK = (1U << 0),
+ MODE_SAS_SATA = MODE_SAS_PORT0_MASK | MODE_SAS_PORT1_MASK |
+ MODE_SAS_PORT2_MASK | MODE_SAS_PORT3_MASK |
+ MODE_SAS_PORT4_MASK | MODE_SAS_PORT5_MASK |
+ MODE_SAS_PORT6_MASK | MODE_SAS_PORT7_MASK,
+
/* SAS_MODE value may be
* dictated (in hw) by values
* of SATA_TARGET & AUTO_DET
@@ -167,12 +238,14 @@
CINT_MEM = (1U << 26), /* int mem parity err */
CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */
CINT_SRS = (1U << 3), /* SRS event */
- CINT_CI_STOP = (1U << 10), /* cmd issue stopped */
+ CINT_CI_STOP = (1U << 1), /* cmd issue stopped */
CINT_DONE = (1U << 0), /* cmd completion */
/* shl for ports 1-3 */
CINT_PORT_STOPPED = (1U << 16), /* port0 stopped */
- CINT_PORT = (1U << 8), /* port0 event */
+ CINT_PORT = (1U << 8), /* port0 event */
+ CINT_PORT_MASK_OFFSET = 8,
+ CINT_PORT_MASK = (0xFF << CINT_PORT_MASK_OFFSET),
/* TX (delivery) ring bits */
TXQ_CMD_SHIFT = 29,
@@ -236,9 +309,14 @@
/* MVS_Px_SER_CTLSTAT (per-phy control) */
PHY_SSP_RST = (1U << 3), /* reset SSP link layer */
- PHY_BCAST_CHG = (1U << 2), /* broadcast(change) notif */
- PHY_RST_HARD = (1U << 1), /* hard reset + phy reset */
+ PHY_BCAST_CHG = (1U << 2), /* broadcast(change) notif */
+ PHY_RST_HARD = (1U << 1), /* hard reset + phy reset */
PHY_RST = (1U << 0), /* phy reset */
+ PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0xF << 8),
+ PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0xF << 12),
+ PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = 16,
+ PHY_NEG_SPP_PHYS_LINK_RATE_MASK = (0xF <<
PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET),
+ PHY_READY_MASK = (1U << 20),
/* MVS_Px_INT_STAT, MVS_Px_INT_MASK (per-phy events) */
PHYEV_UNASSOC_FIS = (1U << 19), /* unassociated FIS rx'd */
@@ -260,12 +338,14 @@
PHYEV_RDY_CH = (1U << 0), /* phy ready changed state */
/* MVS_PCS */
+ PCS_EN_PORT_XMT_START = (12), /*Enable Port Transmit*/
+ PCS_EN_PORT_XMT_START2 = (8), /*For 6480*/
PCS_SATA_RETRY = (1U << 8), /* retry ctl FIS on R_ERR */
PCS_RSP_RX_EN = (1U << 7), /* raw response rx */
PCS_SELF_CLEAR = (1U << 5), /* self-clearing int mode */
PCS_FIS_RX_EN = (1U << 4), /* FIS rx enable */
PCS_CMD_STOP_ERR = (1U << 3), /* cmd stop-on-err enable */
- PCS_CMD_RST = (1U << 2), /* reset cmd issue */
+ PCS_CMD_RST = (1U << 1), /* reset cmd issue */
PCS_CMD_EN = (1U << 0), /* enable cmd issue */
};
@@ -288,7 +368,7 @@
CMD_SAS_CTL1 = 0x128, /* SAS control register 1 */
CMD_SAS_CTL2 = 0x12c, /* SAS control register 2 */
CMD_SAS_CTL3 = 0x130, /* SAS control register 3 */
- CMD_ID_TEST = 0x134, /* ID test register */
+ CMD_ID_TEST = 0x134, /* ID test register */
CMD_PL_TIMER = 0x138, /* PL timer register */
CMD_WD_TIMER = 0x13c, /* WD timer register */
CMD_PORT_SEL_COUNT = 0x140, /* port selector count register */
@@ -345,12 +425,15 @@
enum pci_cfg_registers {
PCR_PHY_CTL = 0x40,
- PCR_PHY_CTL2 = 0x90,
+ PCR_PHY_CTL2 = 0x90,
+ PCR_DEV_CTRL = 0xE8,
};
enum pci_cfg_register_bits {
PCTL_PWR_ON = (0xFU << 24),
PCTL_OFF = (0xFU << 12),
+ PRD_REQ_SIZE = (0x4000),
+ PRD_REQ_MASK = (0x00007000),
};
enum nvram_layout_offsets {
@@ -412,8 +495,20 @@
struct mvs_phy {
struct mvs_port *port;
- struct asd_sas_phy sas_phy;
-
+ struct asd_sas_phy sas_phy;
+ struct sas_identify identify;
+/* from PORT_CONFIG_ADDR0-3, PhyID/device protocol/sas_addr/SIG/wide_port */
+ __le32 DevInfo;
+ __le64 DevSASAddr;
+ __le32 AttDevInfo;
+ __le64 AttDevSASAddr;
+ u8 Type;
+ u8 WidePortPhyMap;
+ u8 Reserved0[2];
+/* from PORT_PHY_CONTROL0-3, REG_PORT_PHY_CONTROL, linkrate, current status */
+ __le32 PhyStatus;
+/* from PORT_IRQ_MASK0-3 */
+ __le32 IRQStatus;
u8 frame_rcvd[24 + 1024];
};
@@ -447,10 +542,19 @@
/* further per-slot information */
struct mvs_slot_info slot_info[MVS_SLOTS];
- unsigned long tags[(MVS_SLOTS / sizeof(unsigned long)) + 1];
-
+ unsigned long tags[MVS_SLOTS];
struct mvs_phy phy[MVS_MAX_PHYS];
struct mvs_port port[MVS_MAX_PHYS];
+
+ u32 can_queue; /* per adapter */
+ u32 tag_out; /*Get*/
+ u32 tag_in; /*Give*/
+};
+
+struct mvs_queue_task {
+ struct list_head list;
+
+ void *uldd_task;
};
static struct scsi_transport_template *mvs_stt;
@@ -464,27 +568,128 @@
static struct scsi_host_template mvs_sht = {
.module = THIS_MODULE,
.name = DRV_NAME,
- .queuecommand = sas_queuecommand,
+ .queuecommand = sas_queuecommand,
.target_alloc = sas_target_alloc,
.slave_configure = sas_slave_configure,
.slave_destroy = sas_slave_destroy,
.change_queue_depth = sas_change_queue_depth,
.change_queue_type = sas_change_queue_type,
.bios_param = sas_bios_param,
- .can_queue = 1,
+ .can_queue = 30,
.cmd_per_lun = 1,
.this_id = -1,
- .sg_tablesize = SG_ALL,
- .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
- .use_clustering = ENABLE_CLUSTERING,
+ .sg_tablesize = 32,
+ .max_sectors = (128*1024)>>9,
+ .use_clustering = DISABLE_CLUSTERING,
.eh_device_reset_handler= sas_eh_device_reset_handler,
.eh_bus_reset_handler = sas_eh_bus_reset_handler,
- .slave_alloc = sas_slave_alloc,
.target_destroy = sas_target_destroy,
.ioctl = sas_ioctl,
};
-static void mvs_int_rx(struct mvs_info *mvi, bool self_clear);
+static void mvs_hexdump (u32 size, u8 *data,u32 baseaddr)
+{
+ u32 i;
+ u32 run;
+ u32 offset;
+
+ offset = 0;
+ while (size) {
+ printk ("%08X : ", baseaddr+offset);
+ if (size >= 16)
+ run = 16;
+ else
+ run = size;
+ size -= run;
+ for (i = 0; i < 16; i++){
+ if(i<run)
+ printk ("%02X ", (unsigned int) data[i]);
+ else
+ printk (" ");
+ }
+ printk (": ");
+ for (i = 0; i < run; i++)
+ printk ("%c", isalnum (data[i]) ? data[i] : '.');
+ printk ("\n");
+ data = &data[16];
+ offset += run;
+ }
+ printk ("\n");
+}
+
+static inline void mvs_hba_sb_dump(struct mvs_info *mvi,u32 tag)
+{
+ u32 offset=MVS_SSP_CMD_SZ+MVS_OAF_SZ+sizeof(struct mvs_prd) *
mvi->slot_info[tag].n_elem;
+ MVS_PRINTK("+---->Status buffer :\n");
+ mvs_hexdump(32,(u8*)mvi->slot_info[tag].response,(u32)mvi->slot_info[tag].buf_dma+offset);
+}
+
+static void mvs_hba_memory_dump (struct mvs_info *mvi,u32 tag)
+{
+#if _MV_DUMP
+ u32 sz,w_ptr,r_ptr;
+ u64 addr;
+ void __iomem *regs = mvi->regs;
+
+ /*Delivery Queue*/
+ sz = mr32(TX_CFG) & TX_RING_SZ_MASK;
+ w_ptr = mr32(TX_PROD_IDX) & TX_RING_SZ_MASK;
+ r_ptr = mr32(TX_CONS_IDX) & TX_RING_SZ_MASK;
+ addr = mr32(TX_HI)<<16<<16 | mr32(TX_LO);
+ MVS_PRINTK("Delivery Queue Size=%04d , WRT_PTR=%04X ,
RD_PTR=%04X\n",sz,w_ptr,r_ptr);
+ MVS_PRINTK("Delivery Queue Base Address=0x%llX (PA)(tx_dma=0x%llX),
Entry=%04d\n",addr,mvi->tx_dma,w_ptr);
+ mvs_hexdump(sizeof(u32),(u8*)mvi->tx,(u32)mvi->tx_dma+sizeof(u32)*w_ptr);
+ /*Command List*/
+ addr = mr32(CMD_LIST_HI)<<16<<16 | mr32(CMD_LIST_LO);
+ MVS_PRINTK("Command List Base Address=0x%llX (PA)(slot_dma=0x%llX),
Header=%03d\n",addr,mvi->slot_dma,tag);
+ MVS_PRINTK("Command Header[%03d]:\n",tag);
+ mvs_hexdump(sizeof(struct
mvs_cmd_hdr),(u8*)mvi->slot,(u32)mvi->slot_dma+tag*sizeof(struct
mvs_cmd_hdr));/*mvs_cmd_hdr*/
+ /*1.command table area*/
+ MVS_PRINTK("+---->Command Table :\n");
+ mvs_hexdump(MVS_SSP_CMD_SZ,(u8*)mvi->slot_info[tag].buf,(u32)mvi->slot_info[tag].buf_dma);
+ /*2.open address frame area*/
+ MVS_PRINTK("+---->Open Address Frame :\n");
+ mvs_hexdump(MVS_OAF_SZ,(u8*)mvi->slot_info[tag].buf+MVS_SSP_CMD_SZ,(u32)mvi->slot_info[tag].buf_dma+MVS_SSP_CMD_SZ);
+ /*3.status buffer*/
+ mvs_hba_sb_dump(mvi,tag);
+ /*4.PRD table*/
+ MVS_PRINTK("+---->PRD table :\n");
+ mvs_hexdump(sizeof(struct mvs_prd) *
mvi->slot_info[tag].n_elem,(u8*)mvi->slot_info[tag].buf+MVS_SSP_CMD_SZ+MVS_OAF_SZ,(u32)mvi->slot_info[tag].buf_dma+MVS_SSP_CMD_SZ+MVS_OAF_SZ);
+#endif
+}
+
+static void mvs_hba_cq_dump (struct mvs_info *mvi)
+{
+#if _MV_DUMP
+ u64 addr;
+ void __iomem *regs = mvi->regs;
+ u32 entry=mvi->rx_cons+1;
+ u32 rx_desc=le32_to_cpu(mvi->rx[entry]);
+ /*Completion Queue*/
+ addr = mr32(RX_HI)<<16<<16 | mr32(RX_LO);
+ MVS_PRINTK("Completion Task = 0x%08X\n",(u32)mvi->slot_info[rx_desc
& RXQ_SLOT_MASK].task);
+ MVS_PRINTK("Completion List Base Address=0x%llX (PA), CQ_Entry=%04d,
CQ_WP=0x%08X\n",addr,entry-1,mvi->rx[0]);
+ mvs_hexdump(sizeof(u32),(u8*)&rx_desc,mvi->rx_dma+sizeof(u32)*entry);
+#endif
+}
+
+static void mvs_hba_interrupt_enable(struct mvs_info *mvi,int enable)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mvi->lock, flags);
+ tmp = mr32(GBL_CTL);
+
+ if (enable)
+ mw32(GBL_CTL ,tmp | INT_EN);
+ else
+ mw32(GBL_CTL , tmp & ~INT_EN);
+ spin_unlock_irqrestore(&mvi->lock,flags);
+}
+
+static int mvs_int_rx(struct mvs_info *mvi, bool self_clear);
/* move to PCI layer or libata core? */
static int pci_go_64(struct pci_dev *pdev)
@@ -519,36 +724,35 @@
return rc;
}
-static void mvs_tag_clear(struct mvs_info *mvi, unsigned int tag)
+static void mvs_tag_clear(struct mvs_info *mvi, u32 tag)
{
- mvi->tags[tag / sizeof(unsigned long)] &=
- ~(1UL << (tag % sizeof(unsigned long)));
+ mvi->tag_in = (mvi->tag_in+1) & (MVS_SLOTS-1);
+ mvi->tags[mvi->tag_in] = tag;
}
-static void mvs_tag_set(struct mvs_info *mvi, unsigned int tag)
+static void mvs_tag_free(struct mvs_info *mvi, u32 tag)
{
- mvi->tags[tag / sizeof(unsigned long)] |=
- (1UL << (tag % sizeof(unsigned long)));
+ mvi->tag_out = (mvi->tag_out-1) & (MVS_SLOTS-1);
+ MVS_PRINTK("clear2 tag %d\n",tag);
}
-static bool mvs_tag_test(struct mvs_info *mvi, unsigned int tag)
+static int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out)
{
- return mvi->tags[tag / sizeof(unsigned long)] &
- (1UL << (tag % sizeof(unsigned long)));
+ if (mvi->tag_out != mvi->tag_in){
+ *tag_out = mvi->tags[mvi->tag_out];
+ mvi->tag_out = (mvi->tag_out+1) & (MVS_SLOTS-1);
+ return 0;
+ }
+ return -EBUSY;
}
-static int mvs_tag_alloc(struct mvs_info *mvi, unsigned int *tag_out)
+static void mvs_tag_init(struct mvs_info *mvi)
{
- unsigned int i;
-
- for (i = 0; i < MVS_SLOTS; i++)
- if (!mvs_tag_test(mvi, i)) {
- mvs_tag_set(mvi, i);
- *tag_out = i;
- return 0;
- }
-
- return -EBUSY;
+ int i;
+ for (i = 0; i < MVS_SLOTS; ++i)
+ mvi->tags[i]=i;
+ mvi->tag_out = 0;
+ mvi->tag_in = MVS_SLOTS-1;
}
static int mvs_eep_read(void __iomem *regs, unsigned int addr, u32 *data)
@@ -627,6 +831,7 @@
static int mvs_nvram_read(struct mvs_info *mvi, unsigned int addr,
void *buf, unsigned int buflen)
{
+#if 0
void __iomem *regs = mvi->regs;
int rc, i;
unsigned int sum;
@@ -666,11 +871,16 @@
err_out:
dev_printk(KERN_ERR, &mvi->pdev->dev, "%s", msg);
return rc;
+#else
+ memcpy(buf,"\x50\x05\x04\x30\x11\xab\x00\x00",8);
+ return 0;
+#endif
}
static void mvs_int_port(struct mvs_info *mvi, int port_no, u32 events)
{
- /* FIXME */
+ /* events is port event.now ,we need check the interrupt status
which belongs to per port.*/
+
}
static void mvs_int_sata(struct mvs_info *mvi)
@@ -708,9 +918,34 @@
unsigned int slot_idx)
{
/* FIXME */
+ mvs_hba_sb_dump(mvi,slot_idx);
+}
+
+static inline int mvs_can_queue(struct mvs_info *mvi, int num)
+{
+ int res = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mvi->lock, flags);
+ if ((mvi->can_queue - num) < 0)
+ res = -EBUSY;
+ else
+ mvi->can_queue -= num;
+ spin_unlock_irqrestore(&mvi->lock, flags);
+
+ return res;
+}
+
+static inline void mvs_can_dequeue(struct mvs_info *mvi, int num)
+{
+// unsigned long flags;
+
+// spin_lock_irqsave(&mvi->lock, flags);
+ mvi->can_queue += num;
+// spin_unlock_irqrestore(&mvi->lock, flags);
}
-static void mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc)
+static int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc)
{
unsigned int slot_idx = rx_desc & RXQ_SLOT_MASK;
struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
@@ -728,13 +963,13 @@
spin_unlock(&task->task_state_lock);
if (aborted)
- return;
+ return -1;
memset(tstat, 0, sizeof(*tstat));
tstat->resp = SAS_TASK_COMPLETE;
/* error info record present */
- if (rx_desc & RXQ_ERR) {
+ if ((rx_desc & RXQ_ERR) && (*(u64*)slot->response)) {
tstat->stat = SAM_CHECK_COND;
mvs_slot_err(mvi, task, slot_idx);
goto out;
@@ -743,9 +978,10 @@
switch (task->task_proto) {
case SAS_PROTO_SSP:
/* hw says status == 0, datapres == 0 */
- if (rx_desc & RXQ_GOOD)
+ if (rx_desc & RXQ_GOOD){
tstat->stat = SAM_GOOD;
-
+ tstat->resp = SAS_TASK_COMPLETE;
+ }
/* response frame present */
else if (rx_desc & RXQ_RSP) {
struct ssp_response_iu *iu =
@@ -781,6 +1017,7 @@
out:
mvs_slot_free(mvi, task, slot, slot_idx);
task->task_done(task);
+ return tstat->stat;
}
static void mvs_int_full(struct mvs_info *mvi)
@@ -791,6 +1028,8 @@
stat = mr32(INT_STAT);
+ mvs_int_rx(mvi, false);
+
for (i = 0; i < MVS_MAX_PORTS; i++) {
tmp = (stat >> i) & (CINT_PORT | CINT_PORT_STOPPED);
if (tmp)
@@ -800,14 +1039,15 @@
if (stat & CINT_SRS)
mvs_int_sata(mvi);
- if (stat & (CINT_CI_STOP | CINT_DONE))
- mvs_int_rx(mvi, false);
+// if (stat & (CINT_CI_STOP | CINT_DONE))
+// mvs_int_rx(mvi, false);
- mw32(INT_STAT, stat);
+// mw32(INT_STAT, stat);
}
-static void mvs_int_rx(struct mvs_info *mvi, bool self_clear)
+static int mvs_int_rx(struct mvs_info *mvi, bool self_clear)
{
+ void __iomem *regs = mvi->regs;
u32 rx_prod_idx, rx_desc;
bool attn = false;
@@ -816,32 +1056,41 @@
* we don't have to stall the CPU reading that register.
* The actual RX ring is offset by one dword, due to this.
*/
- rx_prod_idx = le32_to_cpu(mvi->rx[0]) & 0xfff;
- if (rx_prod_idx == 0xfff) { /* h/w hasn't touched RX ring yet */
+ rx_prod_idx = le32_to_cpu(mr32(RX_CONS_IDX)) & RX_RING_SZ_MASK;
+ if (rx_prod_idx == 0xfff) { /* h/w hasn't touched RX ring yet */
mvi->rx_cons = 0xfff;
- return;
+ return 0;
}
+
+/* The CMPL_Q may come late, read from register and try again */
+/* note: if coalescing is enabled, it will need to read from register
every time for sure */
+ if(mvi->rx_cons == rx_prod_idx)
+ return 0;
+
if (mvi->rx_cons == 0xfff)
mvi->rx_cons = MVS_RX_RING_SZ - 1;
while (mvi->rx_cons != rx_prod_idx) {
+
/* increment our internal RX consumer pointer */
- mvi->rx_cons = (mvi->rx_cons + 1) & (MVS_RX_RING_SZ - 1);
-
- /* Read RX descriptor at offset+1, due to above */
- rx_desc = le32_to_cpu(mvi->rx[mvi->rx_cons + 1]);
+ mvi->rx_cons = (mvi->rx_cons + 1) & (MVS_RX_RING_SZ - 1);/*,then
mvi->rx_cons==rx_prod_idx==Entry No.-1*/
- if (rx_desc & RXQ_DONE)
- /* we had a completion, error or no */
- mvs_slot_complete(mvi, rx_desc);
+ /* Read RX descriptor at offset+1, due to above ,point to right entry*/
+ rx_desc = le32_to_cpu(mvi->rx[mvi->rx_cons+1]);
- if (rx_desc & RXQ_ATTN)
+ mvs_hba_cq_dump(mvi);
+ if (rx_desc & RXQ_ATTN){
attn = true;
+ MVS_PRINTK("ATTN\n");
+ }
+ else if ((rx_desc & RXQ_DONE))
+ mvs_slot_complete(mvi, rx_desc);
}
if (attn && self_clear)
mvs_int_full(mvi);
+ return 0;
}
static irqreturn_t mvs_interrupt(int irq, void *opaque)
@@ -851,6 +1100,9 @@
u32 stat;
stat = mr32(GBL_INT_STAT);
+
+ mw32_f(INT_STAT,CINT_DONE);// clear CMD_CMPLT ASAP
+
if (stat == 0 || stat == 0xffffffff)
return IRQ_NONE;
@@ -918,7 +1170,7 @@
* Fill in TX ring and command slot header
*/
- mvi->tx[tag] = cpu_to_le32(
+ mvi->tx[mvi->tx_prod] = cpu_to_le32(
(TXQ_CMD_SMP << TXQ_CMD_SHIFT) | TXQ_MODE_I | tag);
hdr->flags = 0;
@@ -959,7 +1211,7 @@
unsigned int i, req_len, resp_len;
/* FIXME: fill in SATA register set */
- mvi->tx[tag] = cpu_to_le32(TXQ_MODE_I | tag |
+ mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag |
(TXQ_CMD_STP << TXQ_CMD_SHIFT) |
(sas_port->phy_mask << TXQ_PHY_SHIFT));
@@ -1044,7 +1296,7 @@
struct mvs_cmd_hdr *hdr = tei->hdr;
struct mvs_slot_info *slot;
struct scatterlist *sg;
- unsigned int resp_len, req_len, i, tag = tei->tag;
+ u32 resp_len, req_len, i, tag = tei->tag;
struct mvs_prd *buf_prd;
struct ssp_frame_hdr *ssp_hdr;
void *buf_tmp;
@@ -1054,7 +1306,7 @@
slot = &mvi->slot_info[tag];
- mvi->tx[tag] = cpu_to_le32(TXQ_MODE_I | tag |
+ mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag |
(TXQ_CMD_SSP << TXQ_CMD_SHIFT) |
(sas_port->phy_mask << TXQ_PHY_SHIFT));
@@ -1104,10 +1356,12 @@
slot->response = buf_tmp;
hdr->status_buf = cpu_to_le64(buf_tmp_dma);
- req_len = sizeof(struct ssp_frame_hdr) + 28;
resp_len = MVS_SLOT_BUF_SZ - MVS_SSP_CMD_SZ - MVS_OAF_SZ -
- sizeof(struct mvs_err_info) - i;
+ sizeof(struct mvs_err_info) - i;
+ resp_len = min(resp_len,(u32)0x400);
+ req_len = sizeof(struct ssp_frame_hdr) + 28;
+
/* request, response lengths */
hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | (req_len / 4));
@@ -1118,7 +1372,7 @@
buf_oaf[3] = tag;
memcpy(buf_oaf + 4, task->dev->sas_addr, SAS_ADDR_SIZE);
- /* fill in SSP frame header */
+ /* fill in SSP frame header (Command Table.SSP frame header)*/
ssp_hdr = (struct ssp_frame_hdr *) buf_cmd;
ssp_hdr->frame_type = SSP_COMMAND;
memcpy(ssp_hdr->hashed_dest_addr, task->dev->hashed_sas_addr,
@@ -1133,7 +1387,7 @@
buf_cmd[9] = fburst |
task->ssp_task.task_attr |
(task->ssp_task.task_prio << 3);
- memcpy(buf_cmd + 12, &task->ssp_task.cdb, 16);
+ memcpy(buf_cmd + 12, &task->ssp_task.cdb, 16);/*CDB*/
/* fill in PRD (scatter/gather) table, if any */
sg = task->scatter;
@@ -1155,72 +1409,99 @@
void __iomem *regs = mvi->regs;
unsigned long flags;
struct mvs_task_exec_info tei;
+ struct sas_task *t = task;
+ u32 n=num,pass=0;
- /* FIXME: STP/SATA support not complete yet */
- if (task->task_proto == SATA_PROTO || task->task_proto == SAS_PROTO_STP)
- return -SAS_DEV_NO_RESPONSE;
-
- if (task->num_scatter) {
- n_elem = pci_map_sg(mvi->pdev, task->scatter,
- task->num_scatter, task->data_dir);
- if (!n_elem)
- return -ENOMEM;
- }
-
- spin_lock_irqsave(&mvi->lock, flags);
+ mvs_hba_interrupt_enable(mvi,0);
- rc = mvs_tag_alloc(mvi, &tag);
- if (rc)
- goto err_out;
-
- mvi->slot_info[tag].task = task;
- mvi->slot_info[tag].n_elem = n_elem;
- tei.task = task;
- tei.hdr = &mvi->slot[tag];
- tei.tag = tag;
- tei.n_elem = n_elem;
+ do {
+ /* FIXME: STP/SATA support not complete yet */
+ if (t->task_proto == SATA_PROTO || t->task_proto == SAS_PROTO_STP)
+ return -SAS_DEV_NO_RESPONSE;
+
+ if (t->num_scatter) {
+ n_elem = pci_map_sg(mvi->pdev, t->scatter,
+ t->num_scatter, t->data_dir);
+ if (!n_elem){
+ rc = -ENOMEM;
+ goto err_out;
+ }
+ }
- switch (task->task_proto) {
- case SAS_PROTO_SMP:
- rc = mvs_task_prep_smp(mvi, &tei);
- break;
- case SAS_PROTO_SSP:
- rc = mvs_task_prep_ssp(mvi, &tei);
- break;
- case SATA_PROTO:
- case SAS_PROTO_STP:
- rc = mvs_task_prep_ata(mvi, &tei);
- break;
- default:
- rc = -EINVAL;
- break;
- }
+ rc=mvs_tag_alloc(mvi, &tag);
+ if(rc)
+ goto err_out;
- if (rc)
- goto err_out_tag;
+ mvi->slot_info[tag].task = t;
+ mvi->slot_info[tag].n_elem = n_elem;
+ tei.task = t;
+ tei.hdr = &mvi->slot[tag];
+ tei.tag = tag;
+ tei.n_elem = n_elem;
+
+ switch (t->task_proto) {
+ case SAS_PROTO_SMP:
+ rc = mvs_task_prep_smp(mvi, &tei);
+ break;
+ case SAS_PROTO_SSP:
+ rc = mvs_task_prep_ssp(mvi, &tei);
+ break;
+ case SATA_PROTO:
+ case SAS_PROTO_STP:
+ rc = mvs_task_prep_ata(mvi, &tei);
+ break;
+ default:
+ rc = -EINVAL;
+ break;
+ }
- /* TODO: select normal or high priority */
+ if (rc)
+ goto err_out_tag;
- mw32(RX_PROD_IDX, mvi->tx_prod);
+ /* TODO: select normal or high priority */
- mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_TX_RING_SZ - 1);
+ spin_lock_irqsave(&t->task_state_lock,flags);
+ t->task_state_flags |= SAS_TASK_AT_INITIATOR;
+ spin_unlock_irqrestore(&t->task_state_lock,flags);
+
+ if( n == 1 ){
+ mvs_hba_interrupt_enable(mvi,1);
+ mw32(TX_PROD_IDX, mvi->tx_prod);
+ }
+
+ ++pass;
+ mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_TX_RING_SZ - 1);
+
+// MVS_PRINTK("task=0x%08X,proto=%d,tag=%d,num=%d,mvi->tx_prod=%d\n",(u32)t,t->task_proto,tag,n,mvi->tx_prod);
+ mvs_hba_memory_dump(mvi,tag);
+
+ if( n == 1 )
+ break;
- spin_lock(&task->task_state_lock);
- task->task_state_flags |= SAS_TASK_AT_INITIATOR;
- spin_unlock(&task->task_state_lock);
+ t = list_entry(t->list.next, struct sas_task, list);
+ }while(--n);
- spin_unlock_irqrestore(&mvi->lock, flags);
return 0;
err_out_tag:
- mvs_tag_clear(mvi, tag);
+ mvs_tag_free(mvi, tag);
err_out:
+ MVS_PRINTK("mvsas exec failed[%d]!\n",pass);
if (n_elem)
- pci_unmap_sg(mvi->pdev, task->scatter, n_elem, task->data_dir);
- spin_unlock_irqrestore(&mvi->lock, flags);
+ pci_unmap_sg(mvi->pdev, t->scatter, n_elem, t->data_dir);
+ if(pass)
+ mw32(TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_TX_RING_SZ - 1) );
+ mvs_hba_interrupt_enable(mvi,1);
return rc;
}
+static int mvs_abort_task(struct sas_task *task)
+{
+ /*FIXME*/
+ MVS_PRINTK("mvs abort task\n");
+ return TMF_RESP_FUNC_COMPLETE;
+}
+
static void mvs_free(struct mvs_info *mvi)
{
int i;
@@ -1249,10 +1530,12 @@
mvi->rx, mvi->rx_dma);
if (mvi->slot)
dma_free_coherent(&mvi->pdev->dev,
- sizeof(*mvi->slot) * MVS_RX_RING_SZ,
+ sizeof(*mvi->slot) * MVS_SLOTS,
mvi->slot, mvi->slot_dma);
+#if 0
if (mvi->peri_regs)
iounmap(mvi->peri_regs);
+#endif
if (mvi->regs)
iounmap(mvi->regs);
if (mvi->shost)
@@ -1325,7 +1608,7 @@
sas_phy->tproto = 0;
sas_phy->type = PHY_TYPE_PHYSICAL;
sas_phy->role = PHY_ROLE_INITIATOR;
- sas_phy->oob_mode = OOB_NOT_CONNECTED;
+ sas_phy->oob_mode = OOB_NOT_CONNECTED; /*TODO*/
sas_phy->linkrate = SAS_LINK_RATE_UNKNOWN;
sas_phy->id = phy_id;
@@ -1339,7 +1622,7 @@
const struct pci_device_id *ent)
{
struct mvs_info *mvi;
- unsigned long res_start, res_len;
+ unsigned long res_start, res_len,res_flag;
struct asd_sas_phy **arr_phy;
struct asd_sas_port **arr_port;
const struct mvs_chip_info *chip = &mvs_chips[ent->driver_data];
@@ -1368,22 +1651,23 @@
if (!mvi->shost)
goto err_out;
- arr_phy = kcalloc(MVS_MAX_PHYS, sizeof(void *), GFP_KERNEL);
- arr_port = kcalloc(MVS_MAX_PHYS, sizeof(void *), GFP_KERNEL);
+ arr_phy = kcalloc( MVS_MAX_PHYS , sizeof(void *), GFP_KERNEL);
+ arr_port = kcalloc(MVS_MAX_PHYS , sizeof(void *), GFP_KERNEL);
if (!arr_phy || !arr_port)
goto err_out;
for (i = 0; i < MVS_MAX_PHYS; i++) {
mvs_phy_init(mvi, i);
arr_phy[i] = &mvi->phy[i].sas_phy;
- arr_port[i] = &mvi->port[i].sas_port;
+ arr_port[i] = &mvi->port[i].sas_port;
}
SHOST_TO_SAS_HA(mvi->shost) = &mvi->sas;
mvi->shost->transportt = mvs_stt;
- mvi->shost->max_id = ~0;
- mvi->shost->max_lun = ~0;
- mvi->shost->max_cmd_len = ~0;
+ mvi->shost->max_id = 21;
+ mvi->shost->max_lun = 2;
+ mvi->shost->max_channel=0;
+ mvi->shost->max_cmd_len = 16;
mvi->sas.sas_ha_name = DRV_NAME;
mvi->sas.dev = &pdev->dev;
@@ -1392,12 +1676,14 @@
mvi->sas.sas_phy = arr_phy;
mvi->sas.sas_port = arr_port;
mvi->sas.num_phys = chip->n_phy;
- mvi->sas.lldd_max_execute_num = MVS_TX_RING_SZ - 1;/* FIXME: correct? */
- mvi->sas.lldd_queue_size = MVS_TX_RING_SZ - 1; /* FIXME: correct? */
+ mvi->sas.lldd_max_execute_num = MVS_TX_RING_SZ - 1;
+ mvi->sas.lldd_queue_size = mvi->shost->hostt->can_queue;
+ mvi->can_queue = (MVS_TX_RING_SZ>>1)-1;
mvi->sas.lldd_ha = mvi;
mvi->sas.core.shost = mvi->shost;
- mvs_tag_set(mvi, MVS_TX_RING_SZ - 1);
+// mvs_tag_set(mvi, MVS_TX_RING_SZ - 1);
+ mvs_tag_init(mvi);
/*
* ioremap main and peripheral registers
@@ -1408,16 +1694,23 @@
if (!res_start || !res_len)
goto err_out;
+#if 0
mvi->peri_regs = ioremap_nocache(res_start, res_len);
- if (!mvi->regs)
+ if (!mvi->peri_regs)
goto err_out;
+#endif
res_start = pci_resource_start(pdev, 4);
res_len = pci_resource_len(pdev, 4);
if (!res_start || !res_len)
goto err_out;
- mvi->regs = ioremap_nocache(res_start, res_len);
+ res_flag = pci_resource_flags(pdev, 4);
+ if (res_flag & IORESOURCE_CACHEABLE)
+ mvi->regs = ioremap(res_start, res_len);
+ else
+ mvi->regs = ioremap_nocache(res_start, res_len);
+
if (!mvi->regs)
goto err_out;
@@ -1468,7 +1761,6 @@
/* finally, read NVRAM to get our SAS address */
if (mvs_nvram_read(mvi, NVR_SAS_ADDR, &mvi->sas_addr, 8))
goto err_out;
-
return mvi;
err_out:
@@ -1547,6 +1839,111 @@
tmp &= 0x1fffffff;
tmp |= (2U << 29); /* 8 ms retry */
mvs_cw32(regs, CMD_PHY_TIMER, tmp);
+
+ /* TEST - for phy decoding error, adjust voltage levels */
+ mw32(P0_VSR_ADDR+0, 0x8);
+ mw32(P0_VSR_DATA+0, 0x2F0);
+
+ mw32(P0_VSR_ADDR+8, 0x8);
+ mw32(P0_VSR_DATA+8, 0x2F0);
+
+ mw32(P0_VSR_ADDR+16, 0x8);
+ mw32(P0_VSR_DATA+16, 0x2F0);
+
+ mw32(P0_VSR_ADDR+24, 0x8);
+ mw32(P0_VSR_DATA+24, 0x2F0);
+
+}
+
+static void mvs_enable_xmt(struct mvs_info *mvi, int PhyId)
+{
+ void __iomem *regs = mvi->regs;
+ u32 tmp;
+
+ tmp=mr32(PCS);
+ if( mvi->chip->n_phy <= 4 )
+ tmp |= 1<<(PhyId + PCS_EN_PORT_XMT_START);
+ else
+ tmp |= 1<<(PhyId + PCS_EN_PORT_XMT_START2);
+ mw32(PCS , tmp);
+}
+
+static void mvs_detect_porttype(struct mvs_info *mvi, int i)
+{
+ void __iomem *regs = mvi->regs;
+ u32 reg;
+ struct mvs_phy *phy=&mvi->phy[i];
+
+ /* enable auto port detection */
+ mw32(GBL_PORT_TYPE, MODE_AUTO_DET_EN);
+ msleep(100);
+
+ /* TODO check & save device type*/
+ reg = mr32(GBL_PORT_TYPE);
+
+ if (reg & MODE_SAS_SATA & (1 << i)){
+ phy->Type=PORT_TYPE_SAS;
+ phy->identify.target_port_protocols = SAS_PROTOCOL_SSP;
+ phy->identify.device_type = SAS_END_DEVICE;
+ }
+ else{
+ phy->Type=PORT_TYPE_SATA;
+ phy->identify.target_port_protocols = SAS_PROTOCOL_STP;
+ phy->identify.device_type = SAS_PHY_UNUSED;
+ }
+
+}
+
+static void mvs_update_phyinfo(struct mvs_info *mvi, int i)
+{
+ void __iomem *regs = mvi->regs;
+ struct mvs_phy *phy=&mvi->phy[i];
+ u32 tmp;
+ __le64 tmp64;
+
+ WRITE_PORT_CONFIG_ADDR(i,PHYR_IDENTIFY);
+ phy->DevInfo = READ_PORT_CONFIG_DATA(i);
+
+ WRITE_PORT_CONFIG_ADDR(i,PHYR_ADDR_HI);
+ phy->DevSASAddr = (__le64)READ_PORT_CONFIG_DATA(i) << 32;
+
+ WRITE_PORT_CONFIG_ADDR(i,PHYR_ADDR_LO);
+ phy->DevSASAddr |= READ_PORT_CONFIG_DATA(i);/*le*/
+
+ phy->PhyStatus = READ_PORT_PHY_CONTROL(i);
+
+// MVS_PRINTK("PhyStatus=%X\n",phy->PhyStatus);
+ if (phy->PhyStatus & PHY_READY_MASK){
+ if (phy->Type&PORT_TYPE_SAS){
+ WRITE_PORT_CONFIG_ADDR(i,PHYR_ATT_DEV_INFO);
+ phy->AttDevInfo = READ_PORT_CONFIG_DATA(i);
+
+ WRITE_PORT_CONFIG_ADDR(i,PHYR_ATT_ADDR_HI);
+ phy->AttDevSASAddr = (__le64)READ_PORT_CONFIG_DATA(i)<<32;
+
+ WRITE_PORT_CONFIG_ADDR(i,PHYR_ATT_ADDR_LO);
+ phy->AttDevSASAddr |= READ_PORT_CONFIG_DATA(i);
+
+ /*Updated attached_sas_addr*/
+ tmp64=phy->AttDevSASAddr;
+ MVS_PRINTK("phy[%d] Get Attached Address 0x%llX ",i,tmp64);
+ tmp64=cpu_to_be64(tmp64);
+ memcpy(mvi->sas.sas_phy[i]->attached_sas_addr,&tmp64,SAS_ADDR_SIZE);
+ /**/
+ mvi->sas.sas_phy[i]->linkrate=(phy->PhyStatus &
PHY_NEG_SPP_PHYS_LINK_RATE_MASK)>>PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET;
+// mvi->sas.sas_phy[i]->tproto=phy->identify.target_port_protocols;
+ }
+ /* workaround for HW phy decoding error on 1.5g disk drive */
+ WRITE_PORT_VSR_ADDR(i,0x06);
+ tmp=READ_PORT_VSR_DATA(i);
+ if( ((phy->PhyStatus & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >>
PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET) == SAS_LINK_RATE_1_5_GBPS)
+ tmp&=~0x20000000;
+ else
+ tmp|=0x20000000;
+ WRITE_PORT_VSR_DATA(i,tmp);
+
+ }
+ phy->IRQStatus = READ_PORT_IRQ_STAT(i);
}
static int __devinit mvs_hw_init(struct mvs_info *mvi)
@@ -1559,6 +1956,7 @@
mw32(GBL_CTL, 0);
tmp = mr32(GBL_CTL);
+ /*ResetController*/
if (!(tmp & HBA_RST)) {
if (mvi->flags & MVF_PHY_PWR_FIX) {
pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp);
@@ -1590,13 +1988,23 @@
return -EBUSY;
}
+ /*InitChip*/
/* make sure RST is set; HBA_RST /should/ have done that for us */
- cctl = mr32(CTL);
+ cctl = mr32(CTL); /*MVS_CTL*/
if (cctl & CCTL_RST)
cctl &= ~CCTL_RST;
else
mw32_f(CTL, cctl | CCTL_RST);
+ pci_read_config_dword(mvi->pdev, PCI_COMMAND, &tmp);
+ tmp |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER; /*MV_PCI_DEV_EN*/
+ pci_write_config_dword(mvi->pdev, PCI_COMMAND, tmp);
+ /* write to device control _AND_ device status register? - A.C. */
+ pci_read_config_dword(mvi->pdev, PCR_DEV_CTRL, &tmp);
+ tmp &= ~PRD_REQ_MASK;
+ tmp |= PRD_REQ_SIZE;
+ pci_write_config_dword(mvi->pdev, PCR_DEV_CTRL, tmp);
+
pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &tmp);
tmp |= PCTL_PWR_ON;
tmp &= ~PCTL_OFF;
@@ -1609,6 +2017,9 @@
mw32_f(CTL, cctl);
+ /* reset control */
+ mw32(PCS, 0); /*MVS_PCS*/
+
mvs_phy_hacks(mvi);
mw32(CMD_LIST_LO, mvi->slot_dma);
@@ -1631,6 +2042,8 @@
u32 lo = *((u32 *) &mvi->sas_addr[0]);
u32 hi = *((u32 *) &mvi->sas_addr[4]);
+ mvs_detect_porttype(mvi,i);
+
/* set phy local SAS address */
mvs_phy_write(mvi, i, PHYR_ADDR_LO, lo);
mvs_phy_write(mvi, i, PHYR_ADDR_HI, hi);
@@ -1651,19 +2064,51 @@
/* clear phy int status */
tmp = readl(regs + MVS_P0_INT_STAT + (i * 8));
writel(tmp, regs + MVS_P0_INT_STAT + (i * 8));
+ mvs_update_phyinfo(mvi, i);
+ mvs_enable_xmt(mvi, i);
}
/* FIXME: update wide port bitmaps */
+ /* little endian for open address and command table, etc. */
+ /* A.C.
+ * it seems that ( from the spec ) turning on big-endian won't
+ * do us any good on big-endian machines, need further confirmation
+ */
+ cctl = mr32(CTL);
+ cctl |= CCTL_ENDIAN_CMD;
+ cctl |= CCTL_ENDIAN_DATA;
+ cctl &= ~CCTL_ENDIAN_OPEN;
+ cctl |= CCTL_ENDIAN_RSP;
+ mw32_f(CTL, cctl);
+
+ /* reset CMD queue */
+ tmp = mr32(PCS);
+ tmp |= PCS_CMD_RST;
+ mw32(PCS, tmp);
+ /* interrupt coalescing may cause missing HW interrput in some case */
+ /* and the max count is 0x1ff, while our max slot is 0x200, it will
make count 0 */
+ tmp = 0;
+ mw32(INT_COAL, tmp);
+
+ tmp = 0x100;
+ mw32(INT_COAL_TMOUT, tmp);
+
/* ladies and gentlemen, start your engines */
+ mw32(TX_CFG,0);
mw32(TX_CFG, MVS_TX_RING_SZ | TX_EN);
mw32(RX_CFG, MVS_RX_RING_SZ | RX_EN);
+ /* enable CMD/CMPL_Q/RESP mode */
mw32(PCS, PCS_SATA_RETRY | PCS_FIS_RX_EN | PCS_CMD_EN |
((mvi->flags & MVF_MSI) ? PCS_SELF_CLEAR : 0));
/* re-enable interrupts globally */
mw32(GBL_CTL, INT_EN);
+ /* enable completion queue interrupt */
+ tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM);
+ mw32(INT_MASK, tmp);
+
return 0;
}
@@ -1731,7 +2176,25 @@
mvs_print_info(mvi);
+#if 0 /*For debugging*/
scsi_scan_host(mvi->shost);
+#else
+{
+ int i;
+ static struct sas_identify_frame id[4];/*sas_get_port_device*/
+// id=kcalloc(mvi->chip->n_phy * sizeof(struct sas_identify_frame),
sizeof(void *), GFP_KERNEL);
+ for (i = 0; i < mvi->chip->n_phy; ++i) {
+ struct mvs_phy *phy=&mvi->phy[i];
+ id[i].dev_type=phy->identify.device_type;
+ id[i].initiator_bits=SAS_PROTO_ALL;
+ id[i].target_bits=phy->identify.target_port_protocols;
+ mvi->sas.sas_phy[i]->frame_rcvd=(u8*)&(id[i]);/*SAS_END_DEV,sas_identify_frame*/
+ mvi->sas.sas_phy[i]->frame_rcvd_size=32;
+ mvi->sas.notify_port_event(mvi->sas.sas_phy[i], PORTE_BYTES_DMAED);
+ }
+}
+#endif
+
return 0;
err_out_shost:
@@ -1771,6 +2234,7 @@
static struct sas_domain_function_template mvs_transport_ops = {
.lldd_execute_task = mvs_task_exec,
.lldd_control_phy = mvs_phy_control,
+ .lldd_abort_task = mvs_abort_task,
};
static struct pci_device_id __devinitdata mvs_pci_table[] = {
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Marvell 6440 SAS/SATA driver (draft)
2008-01-10 6:53 [PATCH] Marvell 6440 SAS/SATA driver (draft) Ke Wei
@ 2008-01-10 7:09 ` Jeff Garzik
2008-01-10 7:21 ` Jeff Garzik
2008-01-18 18:53 ` James Bottomley
1 sibling, 1 reply; 6+ messages in thread
From: Jeff Garzik @ 2008-01-10 7:09 UTC (permalink / raw)
To: Ke Wei; +Cc: linux-scsi, kewei, qswang, jfeng, IDE/ATA development list
Ke Wei wrote:
> The 88SE6440 driver :
>
> The driver is based on bare code from Jeff Garzik. And it can work
> under linux kernel 2.6.23.
> By far, Can discover and find SAS HDD, but SATA is currently
> unsupported. Command queue depth can be above 1.
> Most error handling, and some phy handling code is notably missing.
>
>
> contains the following updates:
>
> --- mvsas_orig.c 2007-12-06 19:21:32.000000000 -0500
> +++ mvsas.c 2008-01-09 04:53:14.000000000 -0500
Fantastic! I'm delighted to see this is moving, and thanks much for
getting the driver to that critical "it works" milestone.
We should note for the linux-scsi audience and potential testers that
the base driver upon which this is based is available on the "sas" branch of
git://git.kernel.org:/pub/scm/linux/kernel/git/jgarzik/misc-2.6.git
I will give some substantive comments tomorrow (just got back from long
trip). Two quick suggestions:
1) To make it easier for people to review and test the driver, I would
suggest posting a diff against 2.6.24-rc7 (or 2.6.23), ignoring my
original code. Thus, it would result in a patch
2) In future patches, include a Signed-off-by: line when you are ready
for your patch to be included in the kernel.
Thanks!
Jeff
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Marvell 6440 SAS/SATA driver (draft)
2008-01-10 7:09 ` Jeff Garzik
@ 2008-01-10 7:21 ` Jeff Garzik
2008-01-18 17:58 ` James Bottomley
0 siblings, 1 reply; 6+ messages in thread
From: Jeff Garzik @ 2008-01-10 7:21 UTC (permalink / raw)
To: Ke Wei; +Cc: linux-scsi, kewei, qswang, jfeng, IDE/ATA development list
Jeff Garzik wrote:
> 1) To make it easier for people to review and test the driver, I would
> suggest posting a diff against 2.6.24-rc7 (or 2.6.23), ignoring my
> original code. Thus, it would result in a patch
Er, that sentence was incomplete. Continuing...
Thus it would result in a patch that adds a new file
drivers/scsi/mvsas.c to the 2.6.24-rc7 kernel, and modifies
drivers/scsi/Makefile and drivers/scsi/Kconfig to enable this new driver.
That is the format that developers and users are most familiar with,
when reviewing (and testing) a new driver.
But of course this is a draft, so these guidelines are certainly loose...
Jeff
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Marvell 6440 SAS/SATA driver (draft)
2008-01-10 7:21 ` Jeff Garzik
@ 2008-01-18 17:58 ` James Bottomley
0 siblings, 0 replies; 6+ messages in thread
From: James Bottomley @ 2008-01-18 17:58 UTC (permalink / raw)
To: Jeff Garzik
Cc: Ke Wei, linux-scsi, kewei, qswang, jfeng,
IDE/ATA development list
On Thu, 2008-01-10 at 02:21 -0500, Jeff Garzik wrote:
> Jeff Garzik wrote:
> > 1) To make it easier for people to review and test the driver, I would
> > suggest posting a diff against 2.6.24-rc7 (or 2.6.23), ignoring my
> > original code. Thus, it would result in a patch
>
> Er, that sentence was incomplete. Continuing...
>
>
> Thus it would result in a patch that adds a new file
> drivers/scsi/mvsas.c to the 2.6.24-rc7 kernel, and modifies
> drivers/scsi/Makefile and drivers/scsi/Kconfig to enable this new driver.
>
> That is the format that developers and users are most familiar with,
> when reviewing (and testing) a new driver.
>
> But of course this is a draft, so these guidelines are certainly loose...
OK, in order to try to expedite this, I've created a mvsas branch in
git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git
I think the first patch (the infrastructure change) is safe to go in
immediately. Unfortunately, I can't put the marvell update in because
the emailed patch is corrupt (it looks like the mailer has added line
breaks).
Ke, If you can't get your email tool to insert plain text (as a lot of
microsoft based one's can't), you can add the patch as an attachment; I
can apply it from that (Although in line plain text is by far the
preferred method for review if you can do it, we have a bunch of other
driver writers who have problematic email tools, so we're reasonably
used to this).
Thanks,
James
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Marvell 6440 SAS/SATA driver (draft)
2008-01-10 6:53 [PATCH] Marvell 6440 SAS/SATA driver (draft) Ke Wei
2008-01-10 7:09 ` Jeff Garzik
@ 2008-01-18 18:53 ` James Bottomley
2008-01-21 2:43 ` Ke Wei
1 sibling, 1 reply; 6+ messages in thread
From: James Bottomley @ 2008-01-18 18:53 UTC (permalink / raw)
To: Ke Wei; +Cc: linux-scsi, kewei, qswang, jfeng, jeff
On Thu, 2008-01-10 at 14:53 +0800, Ke Wei wrote:
> The 88SE6440 driver :
>
> The driver is based on bare code from Jeff Garzik. And it can work
> under linux kernel 2.6.23.
> By far, Can discover and find SAS HDD, but SATA is currently
> unsupported. Command queue depth can be above 1.
> Most error handling, and some phy handling code is notably missing.
>
>
> contains the following updates:
>
> --- mvsas_orig.c 2007-12-06 19:21:32.000000000 -0500
> +++ mvsas.c 2008-01-09 04:53:14.000000000 -0500
[...]
> +#define MVS_BIT(x) (1L << (x))
> +
> +#define PORT_TYPE_SATA MVS_BIT(0)
> +#define PORT_TYPE_SAS MVS_BIT(1)
> +
> +#define READ_PORT_CONFIG_DATA(i) \
> + ((i>3)?mr32(P4_CFG_DATA+(i-4)*8):mr32(P0_CFG_DATA+i*8))
> +#define WRITE_PORT_CONFIG_DATA(i,tmp) \
> + {if(i>3)mw32(P4_CFG_DATA+(i-4)*8,tmp);else mw32(P0_CFG_DATA+i*8,tmp);}
> +#define WRITE_PORT_CONFIG_ADDR(i,tmp) \
> + {if(i>3)mw32(P4_CFG_ADDR+(i-4)*8,tmp);else mw32(P0_CFG_ADDR+i*8,tmp);}
> +
> +#define READ_PORT_PHY_CONTROL(i) \
> + ((i>3)?mr32(P4_SER_CTLSTAT+(i-4)*4):mr32(P0_SER_CTLSTAT+i*4))
> +#define WRITE_PORT_PHY_CONTROL(i,tmp) \
> + {if(i>3)mw32(P4_SER_CTLSTAT+(i-4)*4,tmp);else
> mw32(P0_SER_CTLSTAT+i*4,tmp);}
This is an example of where you mailer has broken a line (which causes
the patch not to apply).
> +
> +#define READ_PORT_VSR_DATA(i) \
> + ((i>3)?mr32(P4_VSR_DATA+(i-4)*8):mr32(P0_VSR_DATA+i*8))
> +#define WRITE_PORT_VSR_DATA(i,tmp) \
> + {if(i>3)mw32(P4_VSR_DATA+(i-4)*8,tmp);else mw32(P0_VSR_DATA+i*8,tmp);}
> +#define WRITE_PORT_VSR_ADDR(i,tmp) \
> + {if(i>3)mw32(P4_VSR_ADDR+(i-4)*8,tmp);else mw32(P0_VSR_ADDR+i*8,tmp);}
> +
> +#define READ_PORT_IRQ_STAT(i) \
> + ((i>3)?mr32(P4_INT_STAT+(i-4)*8):mr32(P0_INT_STAT+i*8))
> +#define WRITE_PORT_IRQ_STAT(i,tmp) \
> + {if(i>3)mw32(P4_INT_STAT+(i-4)*8,tmp);else mw32(P0_INT_STAT+i*8,tmp);}
> +#define READ_PORT_IRQ_MASK(i) \
> + ((i>3)?mr32(P4_INT_MASK+(i-4)*8):mr32(P0_INT_MASK+i*8))
> +#define WRITE_PORT_IRQ_MASK(i,tmp) \
> + {if(i>3)mw32(P4_INT_MASK+(i-4)*8,tmp);else mw32(P0_INT_MASK+i*8,tmp);}
> +
> /* driver compile-time configuration */
> enum driver_configuration {
> - MVS_TX_RING_SZ = 1024, /* TX ring size (12-bit) */
> + MVS_TX_RING_SZ = 512, /* TX ring size (12-bit) */
> MVS_RX_RING_SZ = 1024, /* RX ring size (12-bit) */
> /* software requires power-of-2
> ring size */
> @@ -89,7 +125,7 @@
> MVS_GBL_CTL = 0x04, /* global control */
> MVS_GBL_INT_STAT = 0x08, /* global irq status */
> MVS_GBL_PI = 0x0C, /* ports implemented bitmask */
> - MVS_GBL_PORT_TYPE = 0x00, /* port type */
> + MVS_GBL_PORT_TYPE = 0xa0, /* port type */
>
> MVS_CTL = 0x100, /* SAS/SATA port configuration */
> MVS_PCS = 0x104, /* SAS/SATA port control/status */
> @@ -102,11 +138,12 @@
> MVS_TX_LO = 0x124, /* TX (delivery) ring addr */
> MVS_TX_HI = 0x128,
>
> - MVS_RX_PROD_IDX = 0x12C, /* RX producer pointer */
> - MVS_RX_CONS_IDX = 0x130, /* RX consumer pointer (RO) */
> + MVS_TX_PROD_IDX = 0x12C, /* TX producer pointer */
> + MVS_TX_CONS_IDX = 0x130, /* TX consumer pointer (RO) */
> MVS_RX_CFG = 0x134, /* RX configuration */
> MVS_RX_LO = 0x138, /* RX (completion) ring addr */
> MVS_RX_HI = 0x13C,
> + MVS_RX_CONS_IDX = 0x140, /* RX consumer pointer (RO) */
>
> MVS_INT_COAL = 0x148, /* Int coalescing config */
> MVS_INT_COAL_TMOUT = 0x14C, /* Int coalescing timeout */
> @@ -117,9 +154,12 @@
> /* ports 1-3 follow after this */
> MVS_P0_INT_STAT = 0x160, /* port0 interrupt status */
> MVS_P0_INT_MASK = 0x164, /* port0 interrupt mask */
> + MVS_P4_INT_STAT = 0x200, /* Port 4 interrupt status */
> + MVS_P4_INT_MASK = 0x204, /* Port 4 interrupt enable/disable mask */
>
> /* ports 1-3 follow after this */
> MVS_P0_SER_CTLSTAT = 0x180, /* port0 serial control/status */
> + MVS_P4_SER_CTLSTAT = 0x220, /* port4 serial control/status */
>
> MVS_CMD_ADDR = 0x1B8, /* Command register port (addr) */
> MVS_CMD_DATA = 0x1BC, /* Command register port (data) */
> @@ -127,6 +167,14 @@
> /* ports 1-3 follow after this */
> MVS_P0_CFG_ADDR = 0x1C0, /* port0 phy register address */
> MVS_P0_CFG_DATA = 0x1C4, /* port0 phy register data */
> + MVS_P4_CFG_ADDR = 0x230, /* Port 4 config address */
> + MVS_P4_CFG_DATA = 0x234, /* Port 4 config data */
> +
> + /* ports 1-3 follow after this */
> + MVS_P0_VSR_ADDR = 0x1E0, /* port0 vendor specific register address */
> + MVS_P0_VSR_DATA = 0x1E4, /* port0 vendor specific register data */
> + MVS_P4_VSR_ADDR = 0x250, /* port 4 Vendor Specific Register addr */
> + MVS_P4_VSR_DATA = 0x254, /* port 4 Vendor Specific Register Data */
> };
>
> enum hw_register_bits {
> @@ -140,8 +188,31 @@
>
> /* MVS_GBL_PORT_TYPE */ /* shl for ports 1-3 */
> SATA_TARGET = (1U << 16), /* port0 SATA target enable */
> - AUTO_DET = (1U << 8), /* port0 SAS/SATA autodetect */
> - SAS_MODE = (1U << 0), /* port0 SAS(1), SATA(0) mode */
> + MODE_AUTO_DET_PORT7 = (1U << 15), /* port0 SAS/SATA autodetect */
> + MODE_AUTO_DET_PORT6 = (1U << 14),
> + MODE_AUTO_DET_PORT5 = (1U << 13),
> + MODE_AUTO_DET_PORT4 = (1U << 12),
> + MODE_AUTO_DET_PORT3 = (1U << 11),
> + MODE_AUTO_DET_PORT2 = (1U << 10),
> + MODE_AUTO_DET_PORT1 = (1U << 9),
> + MODE_AUTO_DET_PORT0 = (1U << 8),
> + MODE_AUTO_DET_EN = MODE_AUTO_DET_PORT0 | MODE_AUTO_DET_PORT1 |
> + MODE_AUTO_DET_PORT2 | MODE_AUTO_DET_PORT3 |
> + MODE_AUTO_DET_PORT4 | MODE_AUTO_DET_PORT5 |
> + MODE_AUTO_DET_PORT6 | MODE_AUTO_DET_PORT7,
> + MODE_SAS_PORT7_MASK = (1U << 7), /* port0 SAS(1), SATA(0) mode */
> + MODE_SAS_PORT6_MASK = (1U << 6),
> + MODE_SAS_PORT5_MASK = (1U << 5),
> + MODE_SAS_PORT4_MASK = (1U << 4),
> + MODE_SAS_PORT3_MASK = (1U << 3),
> + MODE_SAS_PORT2_MASK = (1U << 2),
> + MODE_SAS_PORT1_MASK = (1U << 1),
> + MODE_SAS_PORT0_MASK = (1U << 0),
> + MODE_SAS_SATA = MODE_SAS_PORT0_MASK | MODE_SAS_PORT1_MASK |
> + MODE_SAS_PORT2_MASK | MODE_SAS_PORT3_MASK |
> + MODE_SAS_PORT4_MASK | MODE_SAS_PORT5_MASK |
> + MODE_SAS_PORT6_MASK | MODE_SAS_PORT7_MASK,
> +
> /* SAS_MODE value may be
> * dictated (in hw) by values
> * of SATA_TARGET & AUTO_DET
> @@ -167,12 +238,14 @@
> CINT_MEM = (1U << 26), /* int mem parity err */
> CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */
> CINT_SRS = (1U << 3), /* SRS event */
> - CINT_CI_STOP = (1U << 10), /* cmd issue stopped */
> + CINT_CI_STOP = (1U << 1), /* cmd issue stopped */
> CINT_DONE = (1U << 0), /* cmd completion */
>
> /* shl for ports 1-3 */
> CINT_PORT_STOPPED = (1U << 16), /* port0 stopped */
> - CINT_PORT = (1U << 8), /* port0 event */
> + CINT_PORT = (1U << 8), /* port0 event */
> + CINT_PORT_MASK_OFFSET = 8,
> + CINT_PORT_MASK = (0xFF << CINT_PORT_MASK_OFFSET),
>
> /* TX (delivery) ring bits */
> TXQ_CMD_SHIFT = 29,
> @@ -236,9 +309,14 @@
>
> /* MVS_Px_SER_CTLSTAT (per-phy control) */
> PHY_SSP_RST = (1U << 3), /* reset SSP link layer */
> - PHY_BCAST_CHG = (1U << 2), /* broadcast(change) notif */
> - PHY_RST_HARD = (1U << 1), /* hard reset + phy reset */
> + PHY_BCAST_CHG = (1U << 2), /* broadcast(change) notif */
> + PHY_RST_HARD = (1U << 1), /* hard reset + phy reset */
> PHY_RST = (1U << 0), /* phy reset */
> + PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0xF << 8),
> + PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0xF << 12),
> + PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = 16,
> + PHY_NEG_SPP_PHYS_LINK_RATE_MASK = (0xF <<
> PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET),
> + PHY_READY_MASK = (1U << 20),
>
> /* MVS_Px_INT_STAT, MVS_Px_INT_MASK (per-phy events) */
> PHYEV_UNASSOC_FIS = (1U << 19), /* unassociated FIS rx'd */
> @@ -260,12 +338,14 @@
> PHYEV_RDY_CH = (1U << 0), /* phy ready changed state */
>
> /* MVS_PCS */
> + PCS_EN_PORT_XMT_START = (12), /*Enable Port Transmit*/
> + PCS_EN_PORT_XMT_START2 = (8), /*For 6480*/
> PCS_SATA_RETRY = (1U << 8), /* retry ctl FIS on R_ERR */
> PCS_RSP_RX_EN = (1U << 7), /* raw response rx */
> PCS_SELF_CLEAR = (1U << 5), /* self-clearing int mode */
> PCS_FIS_RX_EN = (1U << 4), /* FIS rx enable */
> PCS_CMD_STOP_ERR = (1U << 3), /* cmd stop-on-err enable */
> - PCS_CMD_RST = (1U << 2), /* reset cmd issue */
> + PCS_CMD_RST = (1U << 1), /* reset cmd issue */
> PCS_CMD_EN = (1U << 0), /* enable cmd issue */
> };
>
> @@ -288,7 +368,7 @@
> CMD_SAS_CTL1 = 0x128, /* SAS control register 1 */
> CMD_SAS_CTL2 = 0x12c, /* SAS control register 2 */
> CMD_SAS_CTL3 = 0x130, /* SAS control register 3 */
> - CMD_ID_TEST = 0x134, /* ID test register */
> + CMD_ID_TEST = 0x134, /* ID test register */
> CMD_PL_TIMER = 0x138, /* PL timer register */
> CMD_WD_TIMER = 0x13c, /* WD timer register */
> CMD_PORT_SEL_COUNT = 0x140, /* port selector count register */
> @@ -345,12 +425,15 @@
>
> enum pci_cfg_registers {
> PCR_PHY_CTL = 0x40,
> - PCR_PHY_CTL2 = 0x90,
> + PCR_PHY_CTL2 = 0x90,
> + PCR_DEV_CTRL = 0xE8,
> };
>
> enum pci_cfg_register_bits {
> PCTL_PWR_ON = (0xFU << 24),
> PCTL_OFF = (0xFU << 12),
> + PRD_REQ_SIZE = (0x4000),
> + PRD_REQ_MASK = (0x00007000),
> };
>
> enum nvram_layout_offsets {
> @@ -412,8 +495,20 @@
>
> struct mvs_phy {
> struct mvs_port *port;
> - struct asd_sas_phy sas_phy;
> -
> + struct asd_sas_phy sas_phy;
>
> + struct sas_identify identify;
> +/* from PORT_CONFIG_ADDR0-3, PhyID/device protocol/sas_addr/SIG/wide_port */
> + __le32 DevInfo;
> + __le64 DevSASAddr;
> + __le32 AttDevInfo;
> + __le64 AttDevSASAddr;
> + u8 Type;
> + u8 WidePortPhyMap;
> + u8 Reserved0[2];
> +/* from PORT_PHY_CONTROL0-3, REG_PORT_PHY_CONTROL, linkrate, current status */
> + __le32 PhyStatus;
> +/* from PORT_IRQ_MASK0-3 */
> + __le32 IRQStatus;
> u8 frame_rcvd[24 + 1024];
> };
>
> @@ -447,10 +542,19 @@
>
> /* further per-slot information */
> struct mvs_slot_info slot_info[MVS_SLOTS];
> - unsigned long tags[(MVS_SLOTS / sizeof(unsigned long)) + 1];
> -
> + unsigned long tags[MVS_SLOTS];
> struct mvs_phy phy[MVS_MAX_PHYS];
> struct mvs_port port[MVS_MAX_PHYS];
> +
> + u32 can_queue; /* per adapter */
> + u32 tag_out; /*Get*/
> + u32 tag_in; /*Give*/
> +};
> +
> +struct mvs_queue_task {
> + struct list_head list;
> +
> + void *uldd_task;
> };
>
> static struct scsi_transport_template *mvs_stt;
> @@ -464,27 +568,128 @@
> static struct scsi_host_template mvs_sht = {
> .module = THIS_MODULE,
> .name = DRV_NAME,
> - .queuecommand = sas_queuecommand,
> + .queuecommand = sas_queuecommand,
This change is just adding whitespace at the end, which is unnecessary.
If you run your patch through scripts/checkpatch.pl in the linux kernel
directory, it will pick up things like this.
> .target_alloc = sas_target_alloc,
> .slave_configure = sas_slave_configure,
> .slave_destroy = sas_slave_destroy,
> .change_queue_depth = sas_change_queue_depth,
> .change_queue_type = sas_change_queue_type,
> .bios_param = sas_bios_param,
> - .can_queue = 1,
> + .can_queue = 30,
I don't think you want to do this. It starts sending multiple commands
at once. The design use of libsas is to start off at 1 and then up the
limit in slave configure once we know what type of device we're dealing
with. The current sas_slave_configure has a limitation in that the
depth is hard coded to 32, so if you need it smaller, we'll have to find
a way of allowing this? Is 30 your max queue depth?
> .cmd_per_lun = 1,
> .this_id = -1,
> - .sg_tablesize = SG_ALL,
> - .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
> - .use_clustering = ENABLE_CLUSTERING,
> + .sg_tablesize = 32,
32 looks a little small. My reading of the code is that the PRD table
has to fit with the command header, OAF area and status area into an 8k
segment of memory, so at 16 bytes per PRD entry, it looks like a page
worth at least (256) isn't unreasonable. You should probably have some
type of macro for this though.
> + .max_sectors = (128*1024)>>9,
I didn't see any sector length limitations on the transfers in this
driver ... is 256 really the max number of sectors per command?
> + .use_clustering = DISABLE_CLUSTERING,
I think this is wrong ... there should be no modern device that disables
clustering (otherwise they fall over badly on iommu platforms).
> .eh_device_reset_handler= sas_eh_device_reset_handler,
> .eh_bus_reset_handler = sas_eh_bus_reset_handler,
> - .slave_alloc = sas_slave_alloc,
Please don't remove this ... it's a standard callback, and it's required
for the day you support SATA.
I'll look more into the rest later.
Thanks,
James
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] Marvell 6440 SAS/SATA driver (draft)
2008-01-18 18:53 ` James Bottomley
@ 2008-01-21 2:43 ` Ke Wei
0 siblings, 0 replies; 6+ messages in thread
From: Ke Wei @ 2008-01-21 2:43 UTC (permalink / raw)
To: James Bottomley; +Cc: linux-scsi, kewei, qswang, jfeng, jeff, qzhao
Hello James:
I read your comments.
> > .target_alloc = sas_target_alloc,
> > .slave_configure = sas_slave_configure,
> > .slave_destroy = sas_slave_destroy,
> > .change_queue_depth = sas_change_queue_depth,
> > .change_queue_type = sas_change_queue_type,
> > .bios_param = sas_bios_param,
> > - .can_queue = 1,
> > + .can_queue = 30,
>
> I don't think you want to do this. It starts sending multiple commands
> at once. The design use of libsas is to start off at 1 and then up the
> limit in slave configure once we know what type of device we're dealing
> with. The current sas_slave_configure has a limitation in that the
> depth is hard coded to 32, so if you need it smaller, we'll have to find
> a way of allowing this? Is 30 your max queue depth?
Yes , I may not do this. But I need to set
sas_ha_struct.lldd_queue_size to suitable value.
Because sas_queue sends multiple commands according to lldd_queue_size
before calling lldd_execute_task function which supports queue depth ,
30 is suitable.
> > .cmd_per_lun = 1,
> > .this_id = -1,
> > - .sg_tablesize = SG_ALL,
> > - .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
> > - .use_clustering = ENABLE_CLUSTERING,
> > + .sg_tablesize = 32,
>
> 32 looks a little small. My reading of the code is that the PRD table
> has to fit with the command header, OAF area and status area into an 8k
> segment of memory, so at 16 bytes per PRD entry, it looks like a page
> worth at least (256) isn't unreasonable. You should probably have some
> type of macro for this though.
>
> > + .max_sectors = (128*1024)>>9,
Yes , It's demo code . And I need to test device to find a good value
according to performance and reliability.
> > + .use_clustering = DISABLE_CLUSTERING,
>
> I think this is wrong ... there should be no modern device that disables
> clustering (otherwise they fall over badly on iommu platforms).
>
> > .eh_device_reset_handler= sas_eh_device_reset_handler,
> > .eh_bus_reset_handler = sas_eh_bus_reset_handler,
> > - .slave_alloc = sas_slave_alloc,
>
> Please don't remove this ... it's a standard callback, and it's required
> for the day you support SATA.
You are right. I forgot to recover these codes when I debuged.
And Driver has support for SATA devices . I will commit the patches in
this weeks.
Thank you for your help.
Ke Wei.
On Jan 19, 2008 2:53 AM, James Bottomley
<James.Bottomley@hansenpartnership.com> wrote:
> On Thu, 2008-01-10 at 14:53 +0800, Ke Wei wrote:
> > The 88SE6440 driver :
> >
> > The driver is based on bare code from Jeff Garzik. And it can work
> > under linux kernel 2.6.23.
> > By far, Can discover and find SAS HDD, but SATA is currently
> > unsupported. Command queue depth can be above 1.
> > Most error handling, and some phy handling code is notably missing.
> >
> >
> > contains the following updates:
> >
> > --- mvsas_orig.c 2007-12-06 19:21:32.000000000 -0500
> > +++ mvsas.c 2008-01-09 04:53:14.000000000 -0500
> [...]
> > +#define MVS_BIT(x) (1L << (x))
> > +
> > +#define PORT_TYPE_SATA MVS_BIT(0)
> > +#define PORT_TYPE_SAS MVS_BIT(1)
> > +
> > +#define READ_PORT_CONFIG_DATA(i) \
> > + ((i>3)?mr32(P4_CFG_DATA+(i-4)*8):mr32(P0_CFG_DATA+i*8))
> > +#define WRITE_PORT_CONFIG_DATA(i,tmp) \
> > + {if(i>3)mw32(P4_CFG_DATA+(i-4)*8,tmp);else mw32(P0_CFG_DATA+i*8,tmp);}
> > +#define WRITE_PORT_CONFIG_ADDR(i,tmp) \
> > + {if(i>3)mw32(P4_CFG_ADDR+(i-4)*8,tmp);else mw32(P0_CFG_ADDR+i*8,tmp);}
> > +
> > +#define READ_PORT_PHY_CONTROL(i) \
> > + ((i>3)?mr32(P4_SER_CTLSTAT+(i-4)*4):mr32(P0_SER_CTLSTAT+i*4))
> > +#define WRITE_PORT_PHY_CONTROL(i,tmp) \
> > + {if(i>3)mw32(P4_SER_CTLSTAT+(i-4)*4,tmp);else
> > mw32(P0_SER_CTLSTAT+i*4,tmp);}
>
> This is an example of where you mailer has broken a line (which causes
> the patch not to apply).
>
>
> > +
> > +#define READ_PORT_VSR_DATA(i) \
> > + ((i>3)?mr32(P4_VSR_DATA+(i-4)*8):mr32(P0_VSR_DATA+i*8))
> > +#define WRITE_PORT_VSR_DATA(i,tmp) \
> > + {if(i>3)mw32(P4_VSR_DATA+(i-4)*8,tmp);else mw32(P0_VSR_DATA+i*8,tmp);}
> > +#define WRITE_PORT_VSR_ADDR(i,tmp) \
> > + {if(i>3)mw32(P4_VSR_ADDR+(i-4)*8,tmp);else mw32(P0_VSR_ADDR+i*8,tmp);}
> > +
> > +#define READ_PORT_IRQ_STAT(i) \
> > + ((i>3)?mr32(P4_INT_STAT+(i-4)*8):mr32(P0_INT_STAT+i*8))
> > +#define WRITE_PORT_IRQ_STAT(i,tmp) \
> > + {if(i>3)mw32(P4_INT_STAT+(i-4)*8,tmp);else mw32(P0_INT_STAT+i*8,tmp);}
> > +#define READ_PORT_IRQ_MASK(i) \
> > + ((i>3)?mr32(P4_INT_MASK+(i-4)*8):mr32(P0_INT_MASK+i*8))
> > +#define WRITE_PORT_IRQ_MASK(i,tmp) \
> > + {if(i>3)mw32(P4_INT_MASK+(i-4)*8,tmp);else mw32(P0_INT_MASK+i*8,tmp);}
> > +
> > /* driver compile-time configuration */
> > enum driver_configuration {
> > - MVS_TX_RING_SZ = 1024, /* TX ring size (12-bit) */
> > + MVS_TX_RING_SZ = 512, /* TX ring size (12-bit) */
> > MVS_RX_RING_SZ = 1024, /* RX ring size (12-bit) */
> > /* software requires power-of-2
> > ring size */
> > @@ -89,7 +125,7 @@
> > MVS_GBL_CTL = 0x04, /* global control */
> > MVS_GBL_INT_STAT = 0x08, /* global irq status */
> > MVS_GBL_PI = 0x0C, /* ports implemented bitmask */
> > - MVS_GBL_PORT_TYPE = 0x00, /* port type */
> > + MVS_GBL_PORT_TYPE = 0xa0, /* port type */
> >
> > MVS_CTL = 0x100, /* SAS/SATA port configuration */
> > MVS_PCS = 0x104, /* SAS/SATA port control/status */
> > @@ -102,11 +138,12 @@
> > MVS_TX_LO = 0x124, /* TX (delivery) ring addr */
> > MVS_TX_HI = 0x128,
> >
> > - MVS_RX_PROD_IDX = 0x12C, /* RX producer pointer */
> > - MVS_RX_CONS_IDX = 0x130, /* RX consumer pointer (RO) */
> > + MVS_TX_PROD_IDX = 0x12C, /* TX producer pointer */
> > + MVS_TX_CONS_IDX = 0x130, /* TX consumer pointer (RO) */
> > MVS_RX_CFG = 0x134, /* RX configuration */
> > MVS_RX_LO = 0x138, /* RX (completion) ring addr */
> > MVS_RX_HI = 0x13C,
> > + MVS_RX_CONS_IDX = 0x140, /* RX consumer pointer (RO) */
> >
> > MVS_INT_COAL = 0x148, /* Int coalescing config */
> > MVS_INT_COAL_TMOUT = 0x14C, /* Int coalescing timeout */
> > @@ -117,9 +154,12 @@
> > /* ports 1-3 follow after this */
> > MVS_P0_INT_STAT = 0x160, /* port0 interrupt status */
> > MVS_P0_INT_MASK = 0x164, /* port0 interrupt mask */
> > + MVS_P4_INT_STAT = 0x200, /* Port 4 interrupt status */
> > + MVS_P4_INT_MASK = 0x204, /* Port 4 interrupt enable/disable mask */
> >
> > /* ports 1-3 follow after this */
> > MVS_P0_SER_CTLSTAT = 0x180, /* port0 serial control/status */
> > + MVS_P4_SER_CTLSTAT = 0x220, /* port4 serial control/status */
> >
> > MVS_CMD_ADDR = 0x1B8, /* Command register port (addr) */
> > MVS_CMD_DATA = 0x1BC, /* Command register port (data) */
> > @@ -127,6 +167,14 @@
> > /* ports 1-3 follow after this */
> > MVS_P0_CFG_ADDR = 0x1C0, /* port0 phy register address */
> > MVS_P0_CFG_DATA = 0x1C4, /* port0 phy register data */
> > + MVS_P4_CFG_ADDR = 0x230, /* Port 4 config address */
> > + MVS_P4_CFG_DATA = 0x234, /* Port 4 config data */
> > +
> > + /* ports 1-3 follow after this */
> > + MVS_P0_VSR_ADDR = 0x1E0, /* port0 vendor specific register address */
> > + MVS_P0_VSR_DATA = 0x1E4, /* port0 vendor specific register data */
> > + MVS_P4_VSR_ADDR = 0x250, /* port 4 Vendor Specific Register addr */
> > + MVS_P4_VSR_DATA = 0x254, /* port 4 Vendor Specific Register Data */
> > };
> >
> > enum hw_register_bits {
> > @@ -140,8 +188,31 @@
> >
> > /* MVS_GBL_PORT_TYPE */ /* shl for ports 1-3 */
> > SATA_TARGET = (1U << 16), /* port0 SATA target enable */
> > - AUTO_DET = (1U << 8), /* port0 SAS/SATA autodetect */
> > - SAS_MODE = (1U << 0), /* port0 SAS(1), SATA(0) mode */
> > + MODE_AUTO_DET_PORT7 = (1U << 15), /* port0 SAS/SATA autodetect */
> > + MODE_AUTO_DET_PORT6 = (1U << 14),
> > + MODE_AUTO_DET_PORT5 = (1U << 13),
> > + MODE_AUTO_DET_PORT4 = (1U << 12),
> > + MODE_AUTO_DET_PORT3 = (1U << 11),
> > + MODE_AUTO_DET_PORT2 = (1U << 10),
> > + MODE_AUTO_DET_PORT1 = (1U << 9),
> > + MODE_AUTO_DET_PORT0 = (1U << 8),
> > + MODE_AUTO_DET_EN = MODE_AUTO_DET_PORT0 | MODE_AUTO_DET_PORT1 |
> > + MODE_AUTO_DET_PORT2 | MODE_AUTO_DET_PORT3 |
> > + MODE_AUTO_DET_PORT4 | MODE_AUTO_DET_PORT5 |
> > + MODE_AUTO_DET_PORT6 | MODE_AUTO_DET_PORT7,
> > + MODE_SAS_PORT7_MASK = (1U << 7), /* port0 SAS(1), SATA(0) mode */
> > + MODE_SAS_PORT6_MASK = (1U << 6),
> > + MODE_SAS_PORT5_MASK = (1U << 5),
> > + MODE_SAS_PORT4_MASK = (1U << 4),
> > + MODE_SAS_PORT3_MASK = (1U << 3),
> > + MODE_SAS_PORT2_MASK = (1U << 2),
> > + MODE_SAS_PORT1_MASK = (1U << 1),
> > + MODE_SAS_PORT0_MASK = (1U << 0),
> > + MODE_SAS_SATA = MODE_SAS_PORT0_MASK | MODE_SAS_PORT1_MASK |
> > + MODE_SAS_PORT2_MASK | MODE_SAS_PORT3_MASK |
> > + MODE_SAS_PORT4_MASK | MODE_SAS_PORT5_MASK |
> > + MODE_SAS_PORT6_MASK | MODE_SAS_PORT7_MASK,
> > +
> > /* SAS_MODE value may be
> > * dictated (in hw) by values
> > * of SATA_TARGET & AUTO_DET
> > @@ -167,12 +238,14 @@
> > CINT_MEM = (1U << 26), /* int mem parity err */
> > CINT_I2C_SLAVE = (1U << 25), /* slave I2C event */
> > CINT_SRS = (1U << 3), /* SRS event */
> > - CINT_CI_STOP = (1U << 10), /* cmd issue stopped */
> > + CINT_CI_STOP = (1U << 1), /* cmd issue stopped */
> > CINT_DONE = (1U << 0), /* cmd completion */
> >
> > /* shl for ports 1-3 */
> > CINT_PORT_STOPPED = (1U << 16), /* port0 stopped */
> > - CINT_PORT = (1U << 8), /* port0 event */
> > + CINT_PORT = (1U << 8), /* port0 event */
> > + CINT_PORT_MASK_OFFSET = 8,
> > + CINT_PORT_MASK = (0xFF << CINT_PORT_MASK_OFFSET),
> >
> > /* TX (delivery) ring bits */
> > TXQ_CMD_SHIFT = 29,
> > @@ -236,9 +309,14 @@
> >
> > /* MVS_Px_SER_CTLSTAT (per-phy control) */
> > PHY_SSP_RST = (1U << 3), /* reset SSP link layer */
> > - PHY_BCAST_CHG = (1U << 2), /* broadcast(change) notif */
> > - PHY_RST_HARD = (1U << 1), /* hard reset + phy reset */
> > + PHY_BCAST_CHG = (1U << 2), /* broadcast(change) notif */
> > + PHY_RST_HARD = (1U << 1), /* hard reset + phy reset */
> > PHY_RST = (1U << 0), /* phy reset */
> > + PHY_MIN_SPP_PHYS_LINK_RATE_MASK = (0xF << 8),
> > + PHY_MAX_SPP_PHYS_LINK_RATE_MASK = (0xF << 12),
> > + PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET = 16,
> > + PHY_NEG_SPP_PHYS_LINK_RATE_MASK = (0xF <<
> > PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET),
> > + PHY_READY_MASK = (1U << 20),
> >
> > /* MVS_Px_INT_STAT, MVS_Px_INT_MASK (per-phy events) */
> > PHYEV_UNASSOC_FIS = (1U << 19), /* unassociated FIS rx'd */
> > @@ -260,12 +338,14 @@
> > PHYEV_RDY_CH = (1U << 0), /* phy ready changed state */
> >
> > /* MVS_PCS */
> > + PCS_EN_PORT_XMT_START = (12), /*Enable Port Transmit*/
> > + PCS_EN_PORT_XMT_START2 = (8), /*For 6480*/
> > PCS_SATA_RETRY = (1U << 8), /* retry ctl FIS on R_ERR */
> > PCS_RSP_RX_EN = (1U << 7), /* raw response rx */
> > PCS_SELF_CLEAR = (1U << 5), /* self-clearing int mode */
> > PCS_FIS_RX_EN = (1U << 4), /* FIS rx enable */
> > PCS_CMD_STOP_ERR = (1U << 3), /* cmd stop-on-err enable */
> > - PCS_CMD_RST = (1U << 2), /* reset cmd issue */
> > + PCS_CMD_RST = (1U << 1), /* reset cmd issue */
> > PCS_CMD_EN = (1U << 0), /* enable cmd issue */
> > };
> >
> > @@ -288,7 +368,7 @@
> > CMD_SAS_CTL1 = 0x128, /* SAS control register 1 */
> > CMD_SAS_CTL2 = 0x12c, /* SAS control register 2 */
> > CMD_SAS_CTL3 = 0x130, /* SAS control register 3 */
> > - CMD_ID_TEST = 0x134, /* ID test register */
> > + CMD_ID_TEST = 0x134, /* ID test register */
> > CMD_PL_TIMER = 0x138, /* PL timer register */
> > CMD_WD_TIMER = 0x13c, /* WD timer register */
> > CMD_PORT_SEL_COUNT = 0x140, /* port selector count register */
> > @@ -345,12 +425,15 @@
> >
> > enum pci_cfg_registers {
> > PCR_PHY_CTL = 0x40,
> > - PCR_PHY_CTL2 = 0x90,
> > + PCR_PHY_CTL2 = 0x90,
> > + PCR_DEV_CTRL = 0xE8,
> > };
> >
> > enum pci_cfg_register_bits {
> > PCTL_PWR_ON = (0xFU << 24),
> > PCTL_OFF = (0xFU << 12),
> > + PRD_REQ_SIZE = (0x4000),
> > + PRD_REQ_MASK = (0x00007000),
> > };
> >
> > enum nvram_layout_offsets {
> > @@ -412,8 +495,20 @@
> >
> > struct mvs_phy {
> > struct mvs_port *port;
> > - struct asd_sas_phy sas_phy;
> > -
> > + struct asd_sas_phy sas_phy;
> >
> > + struct sas_identify identify;
> > +/* from PORT_CONFIG_ADDR0-3, PhyID/device protocol/sas_addr/SIG/wide_port */
> > + __le32 DevInfo;
> > + __le64 DevSASAddr;
> > + __le32 AttDevInfo;
> > + __le64 AttDevSASAddr;
> > + u8 Type;
> > + u8 WidePortPhyMap;
> > + u8 Reserved0[2];
> > +/* from PORT_PHY_CONTROL0-3, REG_PORT_PHY_CONTROL, linkrate, current status */
> > + __le32 PhyStatus;
> > +/* from PORT_IRQ_MASK0-3 */
> > + __le32 IRQStatus;
> > u8 frame_rcvd[24 + 1024];
> > };
> >
> > @@ -447,10 +542,19 @@
> >
> > /* further per-slot information */
> > struct mvs_slot_info slot_info[MVS_SLOTS];
> > - unsigned long tags[(MVS_SLOTS / sizeof(unsigned long)) + 1];
> > -
> > + unsigned long tags[MVS_SLOTS];
> > struct mvs_phy phy[MVS_MAX_PHYS];
> > struct mvs_port port[MVS_MAX_PHYS];
> > +
> > + u32 can_queue; /* per adapter */
> > + u32 tag_out; /*Get*/
> > + u32 tag_in; /*Give*/
> > +};
> > +
> > +struct mvs_queue_task {
> > + struct list_head list;
> > +
> > + void *uldd_task;
> > };
> >
> > static struct scsi_transport_template *mvs_stt;
> > @@ -464,27 +568,128 @@
> > static struct scsi_host_template mvs_sht = {
> > .module = THIS_MODULE,
> > .name = DRV_NAME,
> > - .queuecommand = sas_queuecommand,
> > + .queuecommand = sas_queuecommand,
>
> This change is just adding whitespace at the end, which is unnecessary.
> If you run your patch through scripts/checkpatch.pl in the linux kernel
> directory, it will pick up things like this.
>
> > .target_alloc = sas_target_alloc,
> > .slave_configure = sas_slave_configure,
> > .slave_destroy = sas_slave_destroy,
> > .change_queue_depth = sas_change_queue_depth,
> > .change_queue_type = sas_change_queue_type,
> > .bios_param = sas_bios_param,
> > - .can_queue = 1,
> > + .can_queue = 30,
>
> I don't think you want to do this. It starts sending multiple commands
> at once. The design use of libsas is to start off at 1 and then up the
> limit in slave configure once we know what type of device we're dealing
> with. The current sas_slave_configure has a limitation in that the
> depth is hard coded to 32, so if you need it smaller, we'll have to find
> a way of allowing this? Is 30 your max queue depth?
>
> > .cmd_per_lun = 1,
> > .this_id = -1,
> > - .sg_tablesize = SG_ALL,
> > - .max_sectors = SCSI_DEFAULT_MAX_SECTORS,
> > - .use_clustering = ENABLE_CLUSTERING,
> > + .sg_tablesize = 32,
>
> 32 looks a little small. My reading of the code is that the PRD table
> has to fit with the command header, OAF area and status area into an 8k
> segment of memory, so at 16 bytes per PRD entry, it looks like a page
> worth at least (256) isn't unreasonable. You should probably have some
> type of macro for this though.
>
> > + .max_sectors = (128*1024)>>9,
>
> I didn't see any sector length limitations on the transfers in this
> driver ... is 256 really the max number of sectors per command?
>
> > + .use_clustering = DISABLE_CLUSTERING,
>
> I think this is wrong ... there should be no modern device that disables
> clustering (otherwise they fall over badly on iommu platforms).
>
> > .eh_device_reset_handler= sas_eh_device_reset_handler,
> > .eh_bus_reset_handler = sas_eh_bus_reset_handler,
> > - .slave_alloc = sas_slave_alloc,
>
> Please don't remove this ... it's a standard callback, and it's required
> for the day you support SATA.
>
>
> I'll look more into the rest later.
>
> Thanks,
>
> James
>
>
>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2008-01-21 2:43 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-01-10 6:53 [PATCH] Marvell 6440 SAS/SATA driver (draft) Ke Wei
2008-01-10 7:09 ` Jeff Garzik
2008-01-10 7:21 ` Jeff Garzik
2008-01-18 17:58 ` James Bottomley
2008-01-18 18:53 ` James Bottomley
2008-01-21 2:43 ` Ke Wei
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox