1. Fixed deadlock issue.

2. Update code to support adaptable feature set according chip type.
3. Add support new B0 chip of 9480.
4. Add change log file and README

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@912 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Andy Yan
2009-06-18 09:12:44 +00:00
parent b81357d452
commit be0eb86e2f
13 changed files with 481 additions and 151 deletions

61
mvsas_tgt/ChangeLog Normal file
View File

@@ -0,0 +1,61 @@
Summary of changes between versions 0.8.4 and 0.8.3
- Fixed issue with working on big endian platform.
- Adjust code of supporting hardware feature accoring to chip type.
- Add supporting Vanir B0 chip.
----------------------------------------------------
Summary of changes between versions 0.8.3 and 0.8.2
- Add code to balance sata disk io stress on expander.
- Update scst to 1.0.1 and enhance task management function of target driver.
- Change wide port load balance scheme.
- Enable interrupt coalescing.
----------------------------------------------------
Summary of changes between versions 0.8.2 and 0.8.1
- Fixed issue - Wrong return value with smart control test.
- Add patch for libsas on port selector
- Fixed issue with error handling.
----------------------------------------------------
Summary of changes between versions 0.8.1 and 0.7.10
- Fixed issue -- Detecting SATA disk with hotplug in.
- Enhance error hanlding.
----------------------------------------------------
Summary of changes between versions 0.7.10 and 0.7.9
- Fixed issue -- System hang when stress test with SATA disk.
----------------------------------------------------
Summary of changes between versions 0.7.9 and 0.7.8
- Fixed issue -- Changed the code to report one scsi host for Vanir chip.
----------------------------------------------------
Summary of changes between versions 0.7.8 and 0.7.7
- Fixed issue -- Set max sg entry count according to chip specific for DMA fix.
- Fixed Libsas issue -- memory corruption issue.
---------------------------------------------------
Summary of changes between versions 0.7.7 and 0.7.6
- Fixed issue: Kernel panic with 64bit OS, structure change.
- Fixed issue: Kernel panic if hot plug any disk when run stress.
- Fixed issue: Add multiple LUN fail with some controller.
- Changed the interface for target mode enable.
- Add supporting target mode for new controller 91xx.
---------------------------------------------------
Summary of changes between versions 0.7.6 and 0.7.5
- Fixed issue -- Because of the different SAS address of HBA's phys, wide
port mode doesn't work.
- Fixed issue -- failed to discover SATA drive when plug out/in SATA disk which run
DD test.
Summary of changes between versions 0.7.5 and 0.7.4
---------------------------------------------------
- Fixed issue -- PDs connected expander still can be detected after plug out the expander .
- Fixed issue -- PDs connected expander can not be detected after plug in the expander.
Summary of changes between versions 0.7.4 and 0.7.3
---------------------------------------------------
- Fixed issue -- can not find SATA disk connected Vanir directly.
Summary of changes between versions 0.7.3 and 0.7.2
---------------------------------------------------
- Support device id 11AB/9480.
- Update for 2.6.27
- Fixed issue -- can not find SATA disk behind expander.
- Support read/write flash ROM for 9480/9180.
- Minor fixes and cleanups

View File

@@ -45,7 +45,7 @@ SCST_DIR := $(shell pwd)/scst/src
EXTRA_CFLAGS += -I$(SCST_INC_DIR)
EXTRA_CFLAGS += #-DSUPPORT_TARGET
EXTRA_CFLAGS += -DSUPPORT_TARGET
MODULE_NAME = mvsas_tgt
EXTRA_CFLAGS += -DMV_DEBUG

132
mvsas_tgt/README Normal file
View File

@@ -0,0 +1,132 @@
LIBSAS driver for Marvell 88SE63xx/64xx/68xx/94xx SAS controller
======================================================
This driver consists from two parts: the target mode driver itself and
the changed initiator driver from Linux kernel, which is particularly
intended to perform all the initialization and shutdown tasks. This
driver was changed to provide the target mode support and all necessary
callbacks, but it's still capable to work as initiator mode only,
when a host acts as the initiator and the target simultaneously, is
supported as well.
This version is compatible with SCST core version 1.0.0 and higher and
Linux kernel 2.6.25 and higher, which must include libsas module.
The original initiator driver was taken from the kernel 2.6.25.
See also "ToDo" for list of known issues and unimplemented
features.
Installation:
------------
Only vanilla kernels from kernel.org are supported, but it should work
on vendors' kernels, if you manage to successfully compile on them. The
main problem with vendor's kernels is that they often contain patches,
which will appear only in the next version of the vanilla kernel,
therefore it's quite hard to track such changes. Thus, if during
compilation for some vendor kernel your compiler complains about
redefinition of some symbol, you should either switch to vanilla kernel,
or change as necessary the corresponding to that symbol "#if
LINUX_VERSION_CODE" statement.
At first, make sure that the link "/lib/modules/`you_kernel_version`/build"
points to the source code for your currently running kernel.
Second, patch the libsas and then make libsas module to install in in your
currently running kernel, also you should add ATA support for libsas in the
kerenl if you want to support SATA device.
The codes have included the SCST code for supportting target, you need patch
the kernel use the patch file in ./scst/kernel. To compile the target driver,
at first, build scst in scst directory, then insmod scst_disk.ko to support
real disk, insmod scst_vdisk.ko to support vdisk, etc.
then, you should make sure the make option SUPPORT_TARGET has been enabled
in Makefile of mvsas, and then type 'make' in mvsas/ subdirectory. It will build
mvsas.ko module.
To install the target driver, type 'make install' in mvsas/
subdirectory. The target driver will be installed in
/lib/modules/`you_kernel_version`/extra. To uninstall it, type 'make
uninstall'.
After the drivers are loaded and adapters are successfully initialized by
the initiator driver, including firmware image load, you can type following
command to show the detailed phy info,
cat /sys/class/scsi_host/hostX/target_mode
X is the host number of the controller, then you can get the info like
phy dev sas address attach dev type attach sas address target mode
0 5005043011ab004b SAS END DEVICE 5000c50008424415 0
1 5005043011ab004b SAS END DEVICE 5000c500064c363d 0
2 5005043011ab004b 0 0
3 5005043011ab004b SAS END DEVICE 500000e0192a37e2 0
4 5005043011ab0000 SAS EXPANDER 5000155d220bc23f 0
5 5005043011ab0000 SAS EXPANDER 5000155d220bc23f 0
6 5005043011ab0000 SAS EXPANDER 5000155d220bc23f 0
7 5005043011ab0000 SAS EXPANDER 5000155d220bc23f 0
then you can choose the one phy to enable the target mode of it.The target
mode should be enabled/disable via a sysfs interface on a per card basis. Under
the appropriate scsi_host there is an entry 'target_mode', where you should
type command like:
echo "enable X" >/sys/class/scsi_host/hostY/target_mode
echo "disable X" >/sys/class/scsi_host/hostY/target_mode
X is the phy number, Y is the host number of controller.
eg: echo "disable 1" >/sys/class/scsi_host/host4/target_mode
when you try to enale one phy of the controller, driver will enable all the
phys which have the same SAS address.
Then you should configure exported devices using the corresponding
interface of SCST core. you can configure the target group
as README file of SCST described, like:
echo "add 1:0:1:0 0" >/proc/scsi_tgt/groups/Default/devices
also you can delete a LUN from target, like:
echo "del 1:0:1:0 0" >/proc/scsi_tgt/groups/Default/devices
for details of configure target disk group, pleae refer to README of SCST.
note:
1. Appropriate phy should be setted to target mode for initiator to detect
disks by this phy.
2. In example "add 2:0:0:0 1" the '1' is the LUN in the target, LUN 0 must
exist with a target.
3. When one device is added to target disk group, target driver will notify
initator the changing of the phy mode and arriving of the disk, but some
initiator driver don't support phy mode changing well, so 'rmmod' and
'modprobe'/'insmod' the initiator driver is neccessary.
following is an example for configuring the target driver.
> modprobe libsas
> insmod mvsas.ko
> echo 1 >/sys/class/scsi_host/host4/target_mode
> echo "add 4:0:0:0 0" >/proc/scsi_tgt/groups/Default/devices
Compilation options
-------------------
There are the following compilation options, that could be commented
in/out in Makefile:
- CONFIG_SCST_DEBUG - turns on some debugging code, including some logging.
Makes the driver considerably bigger and slower, producing large amount of
log data.
- CONFIG_SCST_TRACING - turns on ability to log events. Makes the driver
considerably bigger and leads to some performance loss.
- MV_DEBUG - turns on some debugging code for target driver itself.

View File

@@ -379,10 +379,10 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
* it will make count 0.
*/
tmp = 0;
if (MVS_SLOTS > 0x1ff)
if (MVS_CHIP_SLOT_SZ > 0x1ff)
mw32(MVS_INT_COAL, 0x1ff|COAL_EN);
else
mw32(MVS_INT_COAL, MVS_SLOTS|COAL_EN);
mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN);
tmp = 0x10400;
mw32(MVS_INT_COAL_TMOUT, tmp);

View File

@@ -57,6 +57,43 @@ static void __devinit mvs_94xx_enable_xmt(struct mvs_info *mvi, int phy_id)
mw32(MVS_PCS, tmp);
}
static void mvs_94xx_stp_reset(struct mvs_info *mvi, u32 phy_id)
{
void __iomem *regs = mvi->regs;
u32 reg, tmp;
if (!(mvi->flags & MVF_FLAG_SOC)) {
if (phy_id < 4)
pci_read_config_dword(mvi->pdev, PCR_PHY_CTL, &reg);
else
pci_read_config_dword(mvi->pdev, PCR_PHY_CTL2, &reg);
} else
reg = mr32(MVS_PHY_CTL);
tmp = reg;
if (phy_id < 4)
tmp |= (1U << phy_id) << PCTL_LINK_OFFS;
else
tmp |= (1U << (phy_id - 4)) << PCTL_LINK_OFFS;
if (!(mvi->flags & MVF_FLAG_SOC)) {
if (phy_id < 4) {
pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, tmp);
mdelay(10);
pci_write_config_dword(mvi->pdev, PCR_PHY_CTL, reg);
} else {
pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, tmp);
mdelay(10);
pci_write_config_dword(mvi->pdev, PCR_PHY_CTL2, reg);
}
} else {
mw32(MVS_PHY_CTL, tmp);
mdelay(10);
mw32(MVS_PHY_CTL, reg);
}
}
static void mvs_94xx_phy_reset(struct mvs_info *mvi, u32 phy_id, int hard)
{
u32 tmp;
@@ -89,12 +126,24 @@ static void mvs_94xx_phy_disable(struct mvs_info *mvi, u32 phy_id)
static void mvs_94xx_phy_enable(struct mvs_info *mvi, u32 phy_id)
{
mvs_write_port_vsr_addr(mvi, phy_id, 0x1B4);
mvs_write_port_vsr_data(mvi, phy_id, 0x8300ffc1);
mvs_write_port_vsr_addr(mvi, phy_id, 0x104);
mvs_write_port_vsr_data(mvi, phy_id, 0x00018080);
u32 tmp;
if (mvi->pdev->revision == 0xa0) {
mvs_write_port_vsr_addr(mvi, phy_id, 0x000001b4);
mvs_write_port_vsr_data(mvi, phy_id, 0x8300ffc1);
}
if (mvi->pdev->revision == 0x01) {
mvs_write_port_vsr_addr(mvi, phy_id, 0x00000144);
mvs_write_port_vsr_data(mvi, phy_id, 0x08001006);
mvs_write_port_vsr_addr(mvi, phy_id, 0x000001b4);
mvs_write_port_vsr_data(mvi, phy_id, 0x0000705f);
}
/*
mvs_write_port_vsr_addr(mvi, phy_id, VSR_PHY_MODE2);
mvs_write_port_vsr_data(mvi, phy_id, 0x00207fff);
*/
mvs_write_port_vsr_addr(mvi, phy_id, 0x00000008);
tmp = 0x4ffff;
mvs_write_port_vsr_data(mvi, phy_id, tmp & 0xfd7fffff);
}
static int __devinit mvs_94xx_init(struct mvs_info *mvi)
@@ -132,6 +181,21 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
msleep(100);
}
/* disable Multiplexing, enable phy implemented */
mw32(MVS_PORTS_IMP, 0xFF);
if (mvi->pdev->revision == 0xa0) {
mw32(MVS_PA_VSR_ADDR, 0x00000104);
mw32(MVS_PA_VSR_PORT, 0x00018080);
}
mw32(MVS_PA_VSR_ADDR, VSR_PHY_MODE8);
mw32(MVS_PA_VSR_PORT, 0x0084ffff);
if (mvi->pdev->revision == 0x01) {
mw32(MVS_PA_VSR_ADDR, 0x00000144);
mw32(MVS_PA_VSR_PORT, 0x08001006);
mw32(MVS_PA_VSR_ADDR, 0x000001b4);
mw32(MVS_PA_VSR_PORT, 0x0000705f);
}
/* reset control */
mw32(MVS_PCS, 0); /* MVS_PCS */
mw32(MVS_STP_REG_SET_0, 0);
@@ -140,15 +204,6 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
/* init phys */
mvs_phy_hacks(mvi);
/* disable Multiplexing, enable phy implemented */
mw32(MVS_PORTS_IMP, 0xFF);
mw32(MVS_PA_VSR_ADDR, 0x00000104);
mw32(MVS_PA_VSR_PORT, 0x00018080);
mw32(MVS_PA_VSR_ADDR, VSR_PHY_MODE8);
mw32(MVS_PA_VSR_PORT, 0x0084ffff);
/* set LED blink when IO*/
mw32(MVS_PA_VSR_ADDR, 0x00000030);
tmp = mr32(MVS_PA_VSR_PORT);
@@ -174,7 +229,7 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
mvs_94xx_phy_disable(mvi, i);
/* set phy local SAS address */
mvs_set_sas_addr(mvi, i, CONFIG_ID_FRAME3, CONFIG_ID_FRAME4,
(mvi->phy[i].dev_sas_addr));
cpu_to_le64(mvi->phy[i].dev_sas_addr));
mvs_94xx_enable_xmt(mvi, i);
mvs_94xx_phy_enable(mvi, i);
@@ -219,7 +274,6 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
*/
cctl = mr32(MVS_CTL);
cctl |= CCTL_ENDIAN_CMD;
cctl |= CCTL_ENDIAN_DATA;
cctl &= ~CCTL_ENDIAN_OPEN;
cctl |= CCTL_ENDIAN_RSP;
mw32_f(MVS_CTL, cctl);
@@ -233,10 +287,10 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
* it will make count 0.
*/
tmp = 0;
if (MVS_SLOTS > 0x1ff)
if (MVS_CHIP_SLOT_SZ > 0x1ff)
mw32(MVS_INT_COAL, 0x1ff|COAL_EN);
else
mw32(MVS_INT_COAL, MVS_SLOTS|COAL_EN);
mw32(MVS_INT_COAL, MVS_CHIP_SLOT_SZ|COAL_EN);
tmp = 0x10400;
mw32(MVS_INT_COAL_TMOUT, tmp);
@@ -424,9 +478,13 @@ static void mvs_94xx_make_prd(struct scatterlist *scatter, int nr, void *prd)
int i;
struct scatterlist *sg;
struct mvs_prd *buf_prd = prd;
struct mvs_prd_imt im_len;
*(u32 *)&im_len = 0;
for_each_sg(scatter, sg, nr, i) {
buf_prd->addr = cpu_to_le64(sg_dma_address(sg));
buf_prd->im_len.len = cpu_to_le32(sg_dma_len(sg));
im_len.len = sg_dma_len(sg);
buf_prd->im_len =
cpu_to_le32(*(u32 *)&im_len);
buf_prd++;
}
}
@@ -449,7 +507,7 @@ static void mvs_94xx_get_dev_identify_frame(struct mvs_info *mvi, int port_id,
for (i = 0; i < 7; i++) {
mvs_write_port_cfg_addr(mvi, port_id,
CONFIG_ID_FRAME0 + i * 4);
id_frame[i] = mvs_read_port_cfg_data(mvi, port_id);
id_frame[i] = cpu_to_le32(mvs_read_port_cfg_data(mvi, port_id));
}
memcpy(id, id_frame, 28);
}
@@ -464,7 +522,7 @@ static void mvs_94xx_get_att_identify_frame(struct mvs_info *mvi, int port_id,
for (i = 0; i < 7; i++) {
mvs_write_port_cfg_addr(mvi, port_id,
CONFIG_ATT_ID_FRAME0 + i * 4);
id_frame[i] = mvs_read_port_cfg_data(mvi, port_id);
id_frame[i] = cpu_to_le32(mvs_read_port_cfg_data(mvi, port_id));
mv_dprintk("94xx phy %d atta frame %d %x.\n",
port_id + mvi->id * mvi->chip->n_phy, i, id_frame[i]);
}
@@ -525,12 +583,40 @@ static void mvs_94xx_fix_phy_info(struct mvs_info *mvi, int i,
}
static void mvs_94xx_phy_work_around(struct mvs_info *mvi, int i)
{
u32 tmp;
struct mvs_phy *phy = &mvi->phy[i];
/* workaround for HW phy decoding error on 1.5g disk drive */
mvs_write_port_vsr_addr(mvi, i, VSR_PHY_MODE6);
tmp = mvs_read_port_vsr_data(mvi, i);
if (((phy->phy_status & PHY_NEG_SPP_PHYS_LINK_RATE_MASK) >>
PHY_NEG_SPP_PHYS_LINK_RATE_MASK_OFFSET) ==
SAS_LINK_RATE_1_5_GBPS)
tmp &= ~PHY_MODE6_LATECLK;
else
tmp |= PHY_MODE6_LATECLK;
mvs_write_port_vsr_data(mvi, i, tmp);
}
void mvs_94xx_phy_set_link_rate(struct mvs_info *mvi, u32 phy_id,
struct sas_phy_linkrates *rates)
{
/* TODO */
u32 lrmax = 0;
u32 tmp;
tmp = mvs_read_phy_ctl(mvi, phy_id);
lrmax = (rates->maximum_linkrate - SAS_LINK_RATE_1_5_GBPS) << 12;
if (lrmax) {
tmp &= ~(0x3 << 12);
tmp |= lrmax;
}
mvs_write_phy_ctl(mvi, phy_id, tmp);
mvs_94xx_phy_reset(mvi, phy_id, 1);
}
#ifdef SUPPORT_TARGET
static void
mvs_91xx_enable_ssp_target(struct mvs_info *mvi, u32 phy_id)
@@ -636,10 +722,14 @@ void mvs_94xx_fix_dma(dma_addr_t buf_dma, int buf_len, int from, void *prd)
{
int i;
struct mvs_prd *buf_prd = prd;
struct mvs_prd_imt im_len;
*(u32 *)&im_len = 0;
buf_prd += from;
for (i = 0; i < MAX_SG_ENTRY - from; i++) {
buf_prd->addr = cpu_to_le64(buf_dma);
buf_prd->im_len.len = cpu_to_le32(buf_len);
im_len.len = buf_len;
buf_prd->im_len =
cpu_to_le32(*(u32 *)&im_len);
++buf_prd;
}
}
@@ -681,13 +771,13 @@ const struct mvs_dispatch mvs_94xx_dispatch = {
mvs_94xx_detect_porttype,
mvs_94xx_oob_done,
mvs_94xx_fix_phy_info,
NULL,
mvs_94xx_phy_work_around,
mvs_94xx_phy_set_link_rate,
mvs_hw_max_link_rate,
mvs_94xx_phy_disable,
mvs_94xx_phy_enable,
mvs_94xx_phy_reset,
NULL,
mvs_94xx_stp_reset,
#ifdef SUPPORT_TARGET
mvs_91xx_enable_ssp_target,
mvs_91xx_disable_ssp_target,

View File

@@ -171,17 +171,24 @@ enum pci_interrupt_cause {
#define MAX_SG_ENTRY 255
struct mvs_prd_imt {
#ifndef __BIG_ENDIAN
__le32 len:22;
u8 _r_a:2;
u8 misc_ctl:4;
u8 inter_sel:4;
#else
u32 inter_sel:4;
u32 misc_ctl:4;
u32 _r_a:2;
u32 len:22;
#endif
};
struct mvs_prd {
/* 64-bit buffer address */
__le64 addr;
/* 22-bit length */
struct mvs_prd_imt im_len;
__le32 im_len;
} __attribute__ ((packed));
#define SPI_CTRL_REG_94XX 0xc800

View File

@@ -190,11 +190,12 @@ static inline void __devinit mvs_phy_hacks(struct mvs_info *mvi)
tmp &= 0x0000ffff;
tmp |= 0x00fa0000;
mvs_cw32(mvi, CMD_PHY_MODE_21, tmp);
#if 0
tmp = mvs_cr32(mvi, CMD_PHY_TIMER);
tmp &= 0x1fffffff;
tmp |= (2U << 29); /* 8 ms retry */
mvs_cw32(mvi, CMD_PHY_TIMER, tmp);
#endif
}
static inline void mvs_int_sata(struct mvs_info *mvi)

View File

@@ -36,7 +36,6 @@ enum chip_flavors {
/* driver compile-time configuration */
enum driver_configuration {
MVS_SLOTS = 512, /* command slots */
MVS_TX_RING_SZ = 1024, /* TX ring size (12-bit) */
MVS_RX_RING_SZ = 1024, /* RX ring size (12-bit) */
/* software requires power-of-2
@@ -50,10 +49,9 @@ enum driver_configuration {
MVS_ATA_CMD_SZ = 96, /* SATA command table buffer size */
MVS_OAF_SZ = 64, /* Open address frame buffer size */
#ifdef SUPPORT_TARGET
MVS_TARGET_QUEUE = 32,
MVS_TARGET_QUEUE = 64,
#endif
MVS_QUEUE_SIZE = 32, /* Support Queue depth */
MVS_CAN_QUEUE = MVS_SLOTS - 2, /* SCSI Queue depth */
MVS_QUEUE_SIZE = 64, /* Support Queue depth */
MVS_SOC_CAN_QUEUE = MVS_SOC_SLOTS - 2,
#ifdef SUPPORT_TARGET
MVS_MAX_STP_FRAME = 0x10,
@@ -405,6 +403,7 @@ enum mvs_event_flags {
PHY_PLUG_EVENT = (3U),
PHY_PLUG_IN = (1U << 0), /* phy plug in */
PHY_PLUG_OUT = (1U << 1), /* phy plug out */
EXP_BRCT_CHG = (1U << 2), /* broadcast change */
};
enum mvs_port_type {

View File

@@ -33,8 +33,8 @@ static const struct mvs_chip_info mvs_chips[] = {
[chip_6320] = { 1, 2, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
[chip_6440] = { 1, 4, 0x400, 17, 16, 6, 9, &mvs_64xx_dispatch, },
[chip_6485] = { 1, 8, 0x800, 33, 32, 6, 10, &mvs_64xx_dispatch, },
[chip_9180] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
[chip_9480] = { 2, 4, 0x800, 17, 64, 8, 9, &mvs_94xx_dispatch, },
[chip_9180] = { 2, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
[chip_9480] = { 2, 4, 0x800, 17, 64, 8, 11, &mvs_94xx_dispatch, },
};
#ifdef SUPPORT_TARGET
@@ -90,14 +90,13 @@ static struct sas_domain_function_template mvs_transport_ops = {
.lldd_abort_task = mvs_abort_task,
.lldd_abort_task_set = mvs_abort_task_set,
.lldd_clear_aca = mvs_clear_aca,
.lldd_clear_task_set = mvs_clear_task_set,
.lldd_clear_task_set = mvs_clear_task_set,
.lldd_I_T_nexus_reset = mvs_I_T_nexus_reset,
.lldd_lu_reset = mvs_lu_reset,
.lldd_query_task = mvs_query_task,
.lldd_port_formed = mvs_port_formed,
.lldd_port_deformed = mvs_port_deformed,
};
static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
@@ -106,6 +105,7 @@ static void __devinit mvs_phy_init(struct mvs_info *mvi, int phy_id)
struct asd_sas_phy *sas_phy = &phy->sas_phy;
phy->mvi = mvi;
phy->port = NULL;
init_timer(&phy->timer);
sas_phy->enabled = (phy_id < mvi->chip->n_phy) ? 1 : 0;
sas_phy->class = SAS;
@@ -135,7 +135,7 @@ static void mvs_free(struct mvs_info *mvi)
if (mvi->flags & MVF_FLAG_SOC)
slot_nr = MVS_SOC_SLOTS;
else
slot_nr = MVS_SLOTS;
slot_nr = MVS_CHIP_SLOT_SZ;
for (i = 0; i < mvi->tags_num; i++) {
struct mvs_slot_info *slot = &mvi->slot_info[i];
@@ -170,6 +170,7 @@ static void mvs_free(struct mvs_info *mvi)
scsi_host_put(mvi->shost);
list_for_each_entry(mwq, &mvi->wq_list, entry)
cancel_delayed_work(&mwq->work_q);
kfree(mvi->tags);
kfree(mvi);
}
@@ -230,12 +231,16 @@ static irqreturn_t mvs_interrupt(int irq, void *opaque)
static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
{
int i, slot_nr;
int i = 0, j = 0, slot_nr;
unsigned long buf_size;
void *buf;
dma_addr_t buf_dma;
struct mvs_slot_info *slot = 0;
if (mvi->flags & MVF_FLAG_SOC)
slot_nr = MVS_SOC_SLOTS;
else
slot_nr = MVS_SLOTS;
slot_nr = MVS_CHIP_SLOT_SZ;
spin_lock_init(&mvi->lock);
for (i = 0; i < mvi->chip->n_phy; i++) {
@@ -289,17 +294,26 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
if (!mvi->bulk_buffer)
goto err_out;
#endif
for (i = 0; i < slot_nr; i++) {
struct mvs_slot_info *slot = &mvi->slot_info[i];
slot->buf = dma_alloc_coherent(mvi->dev, MVS_SLOT_BUF_SZ,
&slot->buf_dma, GFP_KERNEL);
if (!slot->buf) {
i = 0;
while (i < slot_nr) {
buf_size = PAGE_SIZE > MVS_SLOT_BUF_SZ ?
PAGE_SIZE : MVS_SLOT_BUF_SZ;
buf = dma_alloc_coherent(mvi->dev, buf_size,
&buf_dma, GFP_KERNEL);
if (!buf) {
printk(KERN_DEBUG"failed to allocate slot->buf.\n");
goto err_out;
}
memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
++mvi->tags_num;
j = 0;
do {
slot = &mvi->slot_info[i + j];
slot->buf = buf + MVS_SLOT_BUF_SZ * j;
slot->buf_dma = buf_dma + MVS_SLOT_BUF_SZ * j;
memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
++mvi->tags_num;
j++;
} while (j < PAGE_SIZE/MVS_SLOT_BUF_SZ);
i += j;
}
/* Initialize tags */
mvs_tag_init(mvi);
@@ -367,11 +381,12 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
const struct pci_device_id *ent,
struct Scsi_Host *shost, unsigned int id)
{
struct mvs_info *mvi;
struct mvs_info *mvi = NULL;
struct sas_ha_struct *sha = SHOST_TO_SAS_HA(shost);
mvi = kzalloc(sizeof(*mvi) + MVS_SLOTS * sizeof(struct mvs_slot_info),
GFP_KERNEL);
mvi = kzalloc(sizeof(*mvi) +
(1L << mvs_chips[ent->driver_data].slot_width)
* sizeof(struct mvs_slot_info), GFP_KERNEL);
if (!mvi)
return NULL;
@@ -388,6 +403,10 @@ static struct mvs_info *__devinit mvs_pci_alloc(struct pci_dev *pdev,
mvi->id = id;
mvi->sas = sha;
mvi->shost = shost;
mvi->tags = kzalloc(MVS_CHIP_SLOT_SZ>>3, GFP_KERNEL);
if (!mvi->tags)
goto err_out;
#ifdef MVS_USE_TASKLET
tasklet_init(&mv_tasklet, mvs_tasklet, (unsigned long)sha);
#endif
@@ -462,7 +481,7 @@ static int __devinit mvs_prep_sas_ha_init(struct Scsi_Host *shost,
((struct mvs_prv_info *)sha->lldd_ha)->n_host = core_nr;
shost->transportt = mvs_stt;
shost->max_id = 128;
shost->max_id = MVS_MAX_DEVICES;
shost->max_lun = ~0;
shost->max_channel = 1;
shost->max_cmd_len = 16;
@@ -505,12 +524,12 @@ static void __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost,
if (mvi->flags & MVF_FLAG_SOC)
can_queue = MVS_SOC_CAN_QUEUE;
else
can_queue = MVS_CAN_QUEUE;
can_queue = MVS_CHIP_SLOT_SZ;
sha->lldd_queue_size = can_queue;
shost->sg_tablesize = MVS_MAX_SG;
shost->can_queue = can_queue;
mvi->shost->cmd_per_lun = MVS_SLOTS/sha->num_phys;
mvi->shost->cmd_per_lun = MVS_QUEUE_SIZE;
sha->core.shost = mvi->shost;
}
@@ -519,7 +538,9 @@ static void mvs_init_sas_add(struct mvs_info *mvi)
{
u8 i;
for (i = 0; i < mvi->chip->n_phy; i++) {
mvi->phy[i].dev_sas_addr = 0x5005043011ab0000ULL;
mvi->phy[i].dev_sas_addr = 0x5005043011ab0000ULL;
if (mvi->id == 1)
mvi->phy[i].dev_sas_addr = 0x5005043011ab0001ULL;
mvi->phy[i].dev_sas_addr =
cpu_to_be64((u64)(*(u64 *)&mvi->phy[i].dev_sas_addr));
}
@@ -713,7 +734,15 @@ static struct pci_device_id __devinitdata mvs_pci_table[] = {
{ PCI_VDEVICE(MARVELL, 0x6485), chip_6485 },
{ PCI_VDEVICE(MARVELL, 0x9480), chip_9480 },
{ PCI_VDEVICE(MARVELL, 0x9180), chip_9180 },
{
.vendor = 0x1b4b,
.device = 0x9480,
.subvendor = PCI_ANY_ID,
.subdevice = 0x9480,
.class = 0,
.class_mask = 0,
.driver_data = chip_9480,
},
{ } /* terminate list */
};
@@ -947,11 +976,18 @@ struct device_attribute *mvst_host_attrs[] = {
#endif /* #ifdef SUPPORT_TARGET */
/* task handler */
struct task_struct *mvs_th;
static int __init mvs_init(void)
{
int rc;
#ifdef SUPPORT_EXP_LB
mvs_th = kthread_run(mvs_ex_task_scheduler, NULL, "mvs_work");
if (mvs_th == ERR_PTR(-ENOMEM)) {
mv_printk("mvsas kernel thread creation failed\n");
return -ENOMEM;
}
#endif
mvs_stt = sas_domain_attach_transport(&mvs_transport_ops);
if (!mvs_stt)
return -ENOMEM;
@@ -972,6 +1008,10 @@ static void __exit mvs_exit(void)
{
pci_unregister_driver(&mvs_pci_driver);
sas_release_transport(mvs_stt);
#ifdef SUPPORT_EXP_LB
if (mvs_th != NULL)
kthread_stop(mvs_th);
#endif
}
module_init(mvs_init);

View File

@@ -32,7 +32,7 @@ static int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag)
{
if (task->lldd_task) {
struct mvs_slot_info *slot;
slot = (struct mvs_slot_info *) task->lldd_task;
slot = task->lldd_task;
*tag = slot->slot_tag;
return 1;
}
@@ -41,7 +41,7 @@ static int mvs_find_tag(struct mvs_info *mvi, struct sas_task *task, u32 *tag)
void mvs_tag_clear(struct mvs_info *mvi, u32 tag)
{
void *bitmap = (void *) &mvi->tags;
void *bitmap = mvi->tags;
clear_bit(tag, bitmap);
}
@@ -52,14 +52,14 @@ void mvs_tag_free(struct mvs_info *mvi, u32 tag)
void mvs_tag_set(struct mvs_info *mvi, unsigned int tag)
{
void *bitmap = (void *) &mvi->tags;
void *bitmap = mvi->tags;
set_bit(tag, bitmap);
}
inline int mvs_tag_alloc(struct mvs_info *mvi, u32 *tag_out)
{
unsigned int index, tag;
void *bitmap = (void *) &mvi->tags;
void *bitmap = mvi->tags;
index = find_first_zero_bit(bitmap, mvi->tags_num);
tag = index;
@@ -229,7 +229,7 @@ struct mvs_info *mvs_find_dev_mvi(struct domain_device *dev)
int mvs_find_dev_phyno(struct domain_device *dev, int *phyno)
{
unsigned long i = 0, j = 0, n = 0, num = 0;
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
struct sas_ha_struct *sha = dev->port->ha;
@@ -263,7 +263,7 @@ static inline void mvs_free_reg_set(struct mvs_info *mvi,
mv_printk("device has been free.\n");
return;
}
if (dev->runing_req != 0)
if (dev->running_req != 0)
return;
if (dev->taskfileset == MVS_ID_NOT_MAPPED)
return;
@@ -419,7 +419,9 @@ int mvs_slave_configure(struct scsi_device *sdev)
adev->flags |= ATA_DFLAG_NCQ_OFF;
scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, 1);
#endif
}
} else
sas_change_queue_depth(sdev, MVS_QUEUE_SIZE);
return 0;
}
@@ -596,8 +598,7 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
{
struct sas_task *task = tei->task;
struct domain_device *dev = task->dev;
struct mvs_device *mvi_dev =
(struct mvs_device *)dev->lldd_dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_cmd_hdr *hdr = tei->hdr;
struct asd_sas_port *sas_port = dev->port;
struct mvs_slot_info *slot;
@@ -740,8 +741,7 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
struct mvs_cmd_hdr *hdr = tei->hdr;
struct mvs_port *port = tei->port;
struct domain_device *dev = task->dev;
struct mvs_device *mvi_dev =
(struct mvs_device *)dev->lldd_dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct asd_sas_port *sas_port = dev->port;
struct mvs_slot_info *slot;
void *buf_prd;
@@ -833,17 +833,17 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
/* fill in SSP frame header (Command Table.SSP frame header) */
ssp_hdr = (struct ssp_frame_hdr *)buf_cmd;
if (is_tmf)
ssp_hdr->frame_type = SSP_TASK;
else
ssp_hdr->frame_type = SSP_COMMAND;
memcpy(ssp_hdr->hashed_dest_addr, dev->hashed_sas_addr,
HASHED_SAS_ADDR_SIZE);
memcpy(ssp_hdr->hashed_src_addr,
dev->hashed_sas_addr, HASHED_SAS_ADDR_SIZE);
ssp_hdr->tag = cpu_to_be16(tag);
if (is_tmf)
ssp_hdr->frame_type = SSP_TASK;
else
ssp_hdr->frame_type = SSP_COMMAND;
/* fill in IU for TASK and Command Frame */
buf_cmd += sizeof(*ssp_hdr);
memcpy(buf_cmd, &task->ssp_task.LUN, 8);
@@ -877,7 +877,7 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
struct mvs_tmf_task *tmf)
{
struct domain_device *dev = task->dev;
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
struct mvs_task_exec_info tei;
struct sas_task *t = task;
@@ -904,7 +904,7 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
spin_lock_irqsave(&mvi->lock, flags);
do {
dev = t->dev;
mvi_dev = (struct mvs_device *)dev->lldd_dev;
mvi_dev = dev->lldd_dev;
if (DEV_IS_GONE(mvi_dev)) {
if (mvi_dev)
mv_dprintk("device %d not ready.\n",
@@ -925,7 +925,7 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
if (!tei.port->port_attached) {
if (sas_protocol_ata(t->task_proto)) {
mv_dprintk("port %d does not"
"attached device.\n", dev->port->id);
" attach device.\n", dev->port->id);
rc = SAS_PHY_DOWN;
goto out_done;
} else {
@@ -995,7 +995,7 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
}
slot->task = t;
slot->port = tei.port;
t->lldd_task = (void *) slot;
t->lldd_task = slot;
list_add_tail(&slot->entry, &tei.port->list);
/* TODO: select normal or high priority */
spin_lock(&t->task_state_lock);
@@ -1003,7 +1003,7 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
spin_unlock(&t->task_state_lock);
mvs_hba_memory_dump(mvi, tag, t->task_proto);
mvi_dev->runing_req++;
mvi_dev->running_req++;
++pass;
mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
if (n > 1)
@@ -1143,7 +1143,7 @@ static void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf)
MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3);
s[3] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG2);
s[2] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
@@ -1157,7 +1157,7 @@ static void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf)
if (((s[1] & 0x00FFFFFF) == 0x00EB1401) && (*(u8 *)&s[3] == 0x01))
s[1] = 0x00EB1401 | (*((u8 *)&s[1] + 3) & 0x10);
return (void *)s;
return s;
}
static u32 mvs_is_sig_fis_received(u32 irq_status)
@@ -1194,7 +1194,7 @@ void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st)
sas_phy->oob_mode = SATA_OOB_MODE;
phy->frame_rcvd_size =
sizeof(struct dev_to_host_fis);
mvs_get_d2h_reg(mvi, i, (void *)id);
mvs_get_d2h_reg(mvi, i, id);
} else {
u32 tmp;
dev_printk(KERN_DEBUG, mvi->dev,
@@ -1289,7 +1289,7 @@ static void mvs_port_notify_formed(struct asd_sas_phy *sas_phy, int lock)
static void mvs_port_notify_deformed(struct asd_sas_phy *sas_phy, int lock)
{
struct domain_device *dev;
struct mvs_phy *phy = (struct mvs_phy *)sas_phy->lldd_phy;
struct mvs_phy *phy = sas_phy->lldd_phy;
struct mvs_info *mvi = phy->mvi;
struct asd_sas_port *port = sas_phy->port;
int phy_no = 0;
@@ -1358,7 +1358,7 @@ int mvs_dev_found_notify(struct domain_device *dev, int lock)
res = -1;
goto found_out;
}
dev->lldd_dev = (void *)mvi_device;
dev->lldd_dev = mvi_device;
mvi_device->dev_type = dev->dev_type;
mvi_device->mvi_info = mvi;
if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) {
@@ -1394,15 +1394,13 @@ int mvs_dev_found(struct domain_device *dev)
return mvs_dev_found_notify(dev, 1);
}
void mvs_dev_gone_notify(struct domain_device *dev, int lock)
void mvs_dev_gone_notify(struct domain_device *dev)
{
unsigned long flags = 0;
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
if (lock)
spin_lock_irqsave(&mvi->lock, flags);
spin_lock_irqsave(&mvi->lock, flags);
if (mvi_dev) {
mv_dprintk("found dev[%d:%x] is gone.\n",
mvi_dev->device_id, mvi_dev->dev_type);
@@ -1413,15 +1411,13 @@ void mvs_dev_gone_notify(struct domain_device *dev, int lock)
mv_dprintk("found dev has gone.\n");
}
dev->lldd_dev = NULL;
if (lock)
spin_unlock_irqrestore(&mvi->lock, flags);
spin_unlock_irqrestore(&mvi->lock, flags);
}
void mvs_dev_gone(struct domain_device *dev)
{
mvs_dev_gone_notify(dev, 1);
mvs_dev_gone_notify(dev);
}
static struct sas_task *mvs_alloc_task(void)
@@ -1574,7 +1570,7 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun)
unsigned long flags;
int rc = TMF_RESP_FUNC_FAILED;
struct mvs_tmf_task tmf_task;
struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
tmf_task.tmf = TMF_LU_RESET;
@@ -1595,7 +1591,7 @@ int mvs_I_T_nexus_reset(struct domain_device *dev)
{
unsigned long flags;
int rc = TMF_RESP_FUNC_FAILED;
struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
if (mvi_dev->dev_status != MVS_DEV_EH)
@@ -1623,7 +1619,7 @@ int mvs_query_task(struct sas_task *task)
if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task;
struct domain_device *dev = task->dev;
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
int_to_scsilun(cmnd->device->lun, &lun);
@@ -1656,19 +1652,16 @@ int mvs_abort_task(struct sas_task *task)
struct scsi_lun lun;
struct mvs_tmf_task tmf_task;
struct domain_device *dev = task->dev;
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_device *mvi_dev = dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
int rc = TMF_RESP_FUNC_FAILED;
unsigned long flags;
u32 tag;
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
spin_unlock_irqrestore(&task->task_state_lock, flags);
rc = TMF_RESP_FUNC_COMPLETE;
goto out;
}
spin_unlock_irqrestore(&task->task_state_lock, flags);
if (task->lldd_task && task->task_proto & SAS_PROTOCOL_SSP) {
struct scsi_cmnd * cmnd = (struct scsi_cmnd *)task->uldd_task;
@@ -1679,7 +1672,6 @@ int mvs_abort_task(struct sas_task *task)
rc = TMF_RESP_FUNC_FAILED;
return rc;
}
tmf_task.tmf = TMF_ABORT_TASK;
tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag);
@@ -1689,11 +1681,13 @@ int mvs_abort_task(struct sas_task *task)
if (rc == TMF_RESP_FUNC_COMPLETE) {
u32 slot_no;
struct mvs_slot_info *slot;
unsigned long flags;
if (task->lldd_task) {
slot = (struct mvs_slot_info *)task->lldd_task;
slot = task->lldd_task;
slot_no = (u32) (slot - mvi->slot_info);
spin_lock_irqsave(&mvi->lock, flags);
mvs_slot_complete(mvi, slot_no, 1);
spin_unlock_irqrestore(&mvi->lock, flags);
}
}
} else if (task->task_proto & SAS_PROTOCOL_SATA ||
@@ -1744,12 +1738,11 @@ int mvs_clear_task_set(struct domain_device *dev, u8 *lun)
static int mvs_sata_done(struct mvs_info *mvi, struct sas_task *task,
u32 slot_idx, int err)
{
struct mvs_device *mvi_dev = (struct mvs_device *)task->dev->lldd_dev;
struct mvs_device *mvi_dev = task->dev->lldd_dev;
struct task_status_struct *tstat = &task->task_status;
struct ata_task_resp *resp = (struct ata_task_resp *)tstat->buf;
int stat = SAM_GOOD;
resp->frame_len = sizeof(struct dev_to_host_fis);
memcpy(&resp->ending_fis[0],
SATA_RECEIVED_D2H_FIS(mvi_dev->taskfileset),
@@ -1787,13 +1780,9 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
case SAS_PROTOCOL_STP:
case SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP:
{
if (err_dw0 == 0x80400002)
mv_printk("find reserved error, why?\n");
task->ata_task.use_ncq = 0;
stat = SAS_PROTO_RESPONSE;
mvs_sata_done(mvi, task, slot_idx, 1);
}
break;
default:
@@ -1803,6 +1792,7 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
return stat;
}
int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
{
u32 slot_idx = rx_desc & RXQ_SLOT_MASK;
@@ -1839,7 +1829,7 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
if (unlikely(aborted)) {
tstat->stat = SAS_ABORTED_TASK;
if (mvi_dev)
mvi_dev->runing_req--;
mvi_dev->running_req--;
if (sas_protocol_ata(task->task_proto))
mvs_free_reg_set(mvi, mvi_dev);
@@ -1864,6 +1854,8 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
/* error info record present */
if (unlikely((rx_desc & RXQ_ERR) && (*(u64 *) slot->response))) {
if (task->task_proto & (SAS_PROTOCOL_SATA | SAS_PROTOCOL_STP))
mvs_sata_done(mvi, task, slot_idx, 0);
tstat->stat = mvs_slot_err(mvi, task, slot_idx);
goto out;
}
@@ -1885,14 +1877,17 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
break;
case SAS_PROTOCOL_SMP: {
struct scatterlist *sg_resp = &task->smp_task.smp_resp;
tstat->stat = SAM_GOOD;
to = kmap_atomic(sg_page(sg_resp), KM_IRQ0);
memcpy(to + sg_resp->offset,
slot->response + sizeof(struct mvs_err_info),
sg_dma_len(sg_resp));
kunmap_atomic(to, KM_IRQ0);
break;
struct scatterlist *sg_resp = &task->smp_task.smp_resp;
tstat->stat = SAM_GOOD;
to = kmap_atomic(sg_page(sg_resp), KM_IRQ0);
memcpy(to + sg_resp->offset,
slot->response + sizeof(struct mvs_err_info),
sg_dma_len(sg_resp));
memcpy(to + sg_resp->offset,
slot->response + sizeof(struct mvs_err_info),
sg_resp->length);
kunmap_atomic(to, KM_IRQ0);
break;
}
case SAS_PROTOCOL_SATA:
@@ -1909,7 +1904,7 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
out:
if (mvi_dev) {
mvi_dev->runing_req--;
mvi_dev->running_req--;
if (sas_protocol_ata(task->task_proto))
mvs_free_reg_set(mvi, mvi_dev);
}
@@ -1983,15 +1978,14 @@ static void mvs_work_queue(void *arg)
#endif
struct mvs_wq *mwq = container_of(dw, struct mvs_wq, work_q);
struct mvs_info *mvi = mwq->mvi;
u32 phy_no = (unsigned long) mwq->data;
struct sas_ha_struct *sas_ha = mvi->sas;
struct mvs_phy *phy = &mvi->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
unsigned long flags;
spin_lock_irqsave(&mvi->lock, flags);
if (mwq->handler & PHY_PLUG_EVENT) {
u32 phy_no = (unsigned long) mwq->data;
struct sas_ha_struct *sas_ha = mvi->sas;
struct mvs_phy *phy = &mvi->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
if (phy->phy_event & PHY_PLUG_OUT) {
u32 tmp;
struct sas_identify_frame *id;
@@ -2012,6 +2006,11 @@ static void mvs_work_queue(void *arg)
mv_dprintk("phy%d Attached Device\n", phy_no);
}
}
} else if (mwq->handler & EXP_BRCT_CHG) {
phy->phy_event &= ~EXP_BRCT_CHG;
sas_ha->notify_port_event(sas_phy,
PORTE_BROADCAST_RCVD);
mv_dprintk("phy%d Got Broadcast Change\n", phy_no);
}
list_del(&mwq->entry);
spin_unlock_irqrestore(&mvi->lock, flags);
@@ -2030,7 +2029,7 @@ static int mvs_handle_event(struct mvs_info *mvi, void *data, int handler)
mwq->handler = handler;
MV_INIT_DELAYED_WORK(&mwq->work_q, mvs_work_queue, mwq);
list_add_tail(&mwq->entry, &mvi->wq_list);
schedule_delayed_work(&mwq->work_q, HZ * 2);
schedule_delayed_work(&mwq->work_q, HZ * DISK_FLASH_HOLD_TIME);
} else
ret = -ENOMEM;
@@ -2062,7 +2061,6 @@ static void mvs_sig_remove_timer(struct mvs_phy *phy)
void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
{
u32 tmp;
struct sas_ha_struct *sas_ha = mvi->sas;
struct mvs_phy *phy = &mvi->phy[phy_no];
struct asd_sas_phy *sas_phy = &phy->sas_phy;
@@ -2078,21 +2076,21 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
*/
if (phy->irq_status & PHYEV_DCDR_ERR) {
mvs_do_release_task(mvi, phy_no, NULL);
mv_dprintk("port %d STP decoding error.\n",
phy_no+mvi->id*mvi->chip->n_phy);
phy_no + mvi->id*mvi->chip->n_phy);
}
if (phy->irq_status & PHYEV_POOF) {
#ifdef SUPPORT_TARGET
/*if initiator plug out*/
mv_dprintk("port %d attr is %x\n", phy_no,
mv_dprintk("port %d attr is %x\n",
phy_no + mvi->id*mvi->chip->n_phy,
mvi->tgt_port[phy_no].port_attr);
if (mvi->tgt_port[phy_no].port_attr == MVST_TGT_PORT
|| mvi->tgt_port[phy_no].port_attr ==
MVST_INIT_TGT_PORT) {
struct sas_ha_struct *sas_ha = mvi->sas;
phy->phy_event |= PHY_PLUG_OUT;
mvs_do_release_task(mvi, phy_no, NULL);
sas_phy_disconnected(sas_phy);
mvs_phy_disconnected(phy);
mv_dprintk("notify plug out on phy[%d]\n", phy_no +
@@ -2164,11 +2162,13 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
phy_no + mvi->id*mvi->chip->n_phy);
}
} else if (phy->irq_status & PHYEV_BROAD_CH) {
mv_dprintk("port %d broadcast change.\n",
phy_no + mvi->id*mvi->chip->n_phy);
/* exception for Samsung disk drive*/
mdelay(1000);
sas_ha->notify_port_event(sas_phy, PORTE_BROADCAST_RCVD);
mv_dprintk("port %d broadcast change.\n",
phy_no + mvi->id*mvi->chip->n_phy);
#ifdef SUPPORT_EXP_LB
mvi->exp_brct = 1;
#endif
mvs_handle_event(mvi, (void *)(unsigned long)phy_no,
EXP_BRCT_CHG);
}
MVS_CHIP_DISP->write_port_irq_stat(mvi, phy_no, phy->irq_status);
}

View File

@@ -47,10 +47,11 @@
#endif
#define DRV_NAME "mvsas"
#define DRV_VERSION "0.8.3"
#define DRV_VERSION "0.8.4"
#define _MV_DUMP 0
#define MVS_ID_NOT_MAPPED 0x7f
/* #define DISABLE_HOTPLUG_DMA_FIX */
#define DISK_FLASH_HOLD_TIME 10
#define WIDE_PORT_MAX_PHY 4
#define MV_DISABLE_NCQ 0
#define mv_printk(fmt, arg ...) \
@@ -259,7 +260,7 @@ struct mvs_device {
struct domain_device *sas_device;
u32 attached_phy;
u32 device_id;
u32 runing_req;
u32 running_req;
u8 taskfileset;
u8 dev_status;
u16 reserved;
@@ -343,7 +344,7 @@ struct mvs_info {
const struct mvs_chip_info *chip;
int tags_num;
DECLARE_BITMAP(tags, MVS_SLOTS);
unsigned long *tags;
/* further per-slot information */
struct mvs_phy phy[MVS_MAX_PHYS];
struct mvs_port port[MVS_MAX_PHYS];

View File

@@ -514,6 +514,8 @@ u8 mvs_spi_init(struct mvs_info *mvi)
if (!mvui_init_param(mvi, &hba_info_para)) {
for (i = 0; i < mvi->chip->n_phy; i++) {
sas_addr = 0x5005043011ab0000ULL;
if (mvi->id == 1)
sas_addr = 0x5005043011ab0001ULL;
mvi->phy[i].dev_sas_addr =
cpu_to_be64((u64)(*(u64 *)&sas_addr));
}

View File

@@ -379,7 +379,6 @@ mvst_get_slot(struct mvs_info *mvi, struct mvst_port *tgt_port)
slot->tx = mvi->tx_prod;
list_add_tail(&slot->entry, &slot->slot_tgt_port->slot_list);
return slot;
}
static int mvst_prep_resp_frame(struct mvst_prm *prm,
@@ -760,7 +759,7 @@ static int mvst_xmit_response(struct scst_cmd *scst_cmd)
TRACE_ENTRY();
TRACE(TRACE_SCSI, "xmit_respons scmd[0x%p] tag=%ld, sg_cnt=%d",
TRACE(TRACE_SCSI, "xmit_respons scmd[0x%p] tag=%lld, sg_cnt=%d",
scst_cmd, scst_cmd_get_tag(scst_cmd), scst_cmd->sg_cnt);
#ifdef DEBUG_WORK_IN_THREAD
@@ -774,9 +773,9 @@ static int mvst_xmit_response(struct scst_cmd *scst_cmd)
scst_sess_get_tgt_priv(scst_cmd_get_session(scst_cmd));
if (unlikely(scst_cmd_aborted(scst_cmd))) {
TRACE(TRACE_MGMT_MINOR, "mvst tgt(%ld): terminating exchange "
"for aborted scst_cmd=%p (tag=%ld)",
mvi->instance, scst_cmd, scst_cmd_get_tag(scst_cmd));
TRACE(TRACE_MGMT_MINOR, "mvst tgt: terminating exchange "
"for aborted scst_cmd=%p (tag=%lld)",
scst_cmd, scst_cmd_get_tag(scst_cmd));
scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_ABORTED);
@@ -1187,7 +1186,6 @@ static void mvst_do_cmd_completion(struct mvs_info *mvi,
(struct open_address_frame *)slot->open_frame;
struct ssp_frame_header *ssp_hdr;
struct mvst_sess *sess;
TRACE_BUFFER("SSP Header", ssp_hdr, sizeof(*ssp_hdr));
TRACE_BUFFER("SSP open_frame", open_frame, sizeof(*open_frame));
dest_sas_addr = (open_frame->dest_sas_addr);
sess = mvst_find_sess_by_lid(mvi->tgt,
@@ -1373,7 +1371,7 @@ static int mvst_do_send_cmd_to_scst(struct mvs_info *mvi, struct mvst_cmd *cmd)
context = SCST_CONTEXT_TASKLET;
#endif
TRACE_DBG("Context %x", context);
TRACE(TRACE_SCSI, "START Command (tag %ld)",
TRACE(TRACE_SCSI, "START Command (tag %lld)",
scst_cmd_get_tag(cmd->scst_cmd));
scst_cmd_init_done(cmd->scst_cmd, context);
out:
@@ -1502,7 +1500,7 @@ int mvst_build_cmd(struct mvs_info *mvi,
if (mvi->tgt->tgt_shutdown) {
TRACE_DBG("New command while device %p is shutting "
"down", tgt);
"down", tgt_port);
res = -EFAULT;
goto out;
}
@@ -2288,8 +2286,8 @@ static void mvst_host_action(struct mvs_info *mvi,
(mvi->tgt_port[target_port].sas_addr),
mvi->tgt_port[target_port].wide_port_phymap,
target_port);
if (target_port * (MVS_SLOTS/mvi->chip->n_phy)
> MVS_CAN_QUEUE) {
if (target_port * (MVS_CHIP_SLOT_SZ/mvi->chip->n_phy)
> MVS_CHIP_SLOT_SZ) {
mv_dprintk("Warning: No sufficient slots"
"for target port[%d].\n", target_port);
break;
@@ -2504,8 +2502,7 @@ mvst_start_sas_target(struct mvs_info *mvi, u8 id)
goto err_out_tag;
++pass;
mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1);
} while (++slot_id < MVS_SLOTS/mvi->chip->n_phy);
} while (++slot_id < MVS_TARGET_QUEUE);
rc = 0;
goto out_done;