1. Fixed some issues with initiator driver.

2. Clean up code.
3. Fixed issue with supporting task management function.
4. Fixed issue with checking and sending sense data.
5. update version to 0.8.3.

git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@849 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Andy Yan
2009-05-12 06:54:54 +00:00
parent 0a76a2b21a
commit 899450e0cd
10 changed files with 531 additions and 406 deletions

View File

@@ -379,9 +379,12 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
* it will make count 0.
*/
tmp = 0;
mw32(MVS_INT_COAL, tmp);
if (MVS_SLOTS > 0x1ff)
mw32(MVS_INT_COAL, 0x1ff|COAL_EN);
else
mw32(MVS_INT_COAL, MVS_SLOTS|COAL_EN);
tmp = 0x100;
tmp = 0x10400;
mw32(MVS_INT_COAL_TMOUT, tmp);
/* ladies and gentlemen, start your engines */
@@ -393,8 +396,8 @@ static int __devinit mvs_64xx_init(struct mvs_info *mvi)
PCS_CMD_EN | PCS_CMD_STOP_ERR);
/* enable completion queue interrupt */
tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP |
CINT_DMA_PCIE);
tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM |
CINT_SRS | CINT_CI_STOP | CINT_DMA_PCIE);
mw32(MVS_INT_MASK, tmp);

View File

@@ -233,9 +233,12 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
* it will make count 0.
*/
tmp = 0;
mw32(MVS_INT_COAL, tmp);
if (MVS_SLOTS > 0x1ff)
mw32(MVS_INT_COAL, 0x1ff|COAL_EN);
else
mw32(MVS_INT_COAL, MVS_SLOTS|COAL_EN);
tmp = 0x100;
tmp = 0x10400;
mw32(MVS_INT_COAL_TMOUT, tmp);
/* ladies and gentlemen, start your engines */
@@ -247,8 +250,8 @@ static int __devinit mvs_94xx_init(struct mvs_info *mvi)
PCS_CMD_EN | PCS_CMD_STOP_ERR);
/* enable completion queue interrupt */
tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM | CINT_SRS | CINT_CI_STOP |
CINT_DMA_PCIE);
tmp = (CINT_PORT_MASK | CINT_DONE | CINT_MEM |
CINT_SRS | CINT_CI_STOP | CINT_DMA_PCIE);
tmp |= CINT_PHY_MASK;
mw32(MVS_INT_MASK, tmp);

View File

@@ -159,11 +159,11 @@ enum hw_register_bits {
/* TX (delivery) ring bits */
TXQ_CMD_SHIFT = 29,
TXQ_CMD_SSP = 1, /* SSP protocol */
TXQ_CMD_SMP = 2, /* SMP protocol */
TXQ_CMD_STP = 3, /* STP/SATA protocol */
TXQ_CMD_SSP_FREE_LIST = 4, /* add to SSP targ free list */
TXQ_CMD_SLOT_RESET = 7, /* reset command slot */
TXQ_CMD_SSP = 1, /* SSP protocol */
TXQ_CMD_SMP = 2, /* SMP protocol */
TXQ_CMD_STP = 3, /* STP/SATA protocol */
TXQ_CMD_SSP_FREE_LIST = 4, /* add to SSP target free list */
TXQ_CMD_SLOT_RESET = 7, /* reset command slot */
TXQ_MODE_I = (1U << 28), /* mode: 0=target,1=initiator */
TXQ_MODE_TARGET = 0,
TXQ_MODE_INITIATOR = 1,

View File

@@ -24,15 +24,17 @@
#include "mv_sas.h"
#ifdef SUPPORT_TARGET
#include "mv_spi.h"
#endif
static struct scsi_transport_template *mvs_stt;
static const struct mvs_chip_info mvs_chips[] = {
[chip_6320] = { 1, 2, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
[chip_6440] = { 1, 4, 0x400, 17, 16, 9, &mvs_64xx_dispatch, },
[chip_6485] = { 1, 8, 0x800, 33, 32, 10, &mvs_64xx_dispatch, },
[chip_9180] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
[chip_9480] = { 2, 4, 0x800, 17, 64, 9, &mvs_94xx_dispatch, },
[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, },
};
#ifdef SUPPORT_TARGET
@@ -246,6 +248,7 @@ static int __devinit mvs_alloc(struct mvs_info *mvi, struct Scsi_Host *shost)
mvi->devices[i].taskfileset = MVS_ID_NOT_MAPPED;
mvi->devices[i].dev_type = NO_DEVICE;
mvi->devices[i].device_id = i;
mvi->devices[i].dev_status = MVS_DEV_NORMAL;
}
/*
@@ -505,6 +508,7 @@ static void __devinit mvs_post_sas_ha_init(struct Scsi_Host *shost,
can_queue = MVS_CAN_QUEUE;
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;
sha->core.shost = mvi->shost;

View File

@@ -229,7 +229,8 @@ 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_info *mvi = mvs_find_dev_mvi(dev);
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
struct sas_ha_struct *sha = dev->port->ha;
while (sha->sas_port[i]) {
@@ -458,7 +459,7 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
struct domain_device *dev = task->dev;
struct asd_sas_port *sas_port = dev->port;
struct scatterlist *sg_req, *sg_resp;
u32 req_len, resp_len, tag = tei->tag;
u32 req_len, phy_mask, resp_len, tag = tei->tag;
void *buf_tmp;
u8 *buf_oaf;
dma_addr_t buf_tmp_dma;
@@ -538,9 +539,10 @@ static int mvs_task_prep_smp(struct mvs_info *mvi,
* Fill in TX ring and command slot header
*/
slot->tx = mvi->tx_prod;
phy_mask = sas_port->phy_mask;
mvi->tx[mvi->tx_prod] = cpu_to_le32((TXQ_CMD_SMP << TXQ_CMD_SHIFT) |
TXQ_MODE_I | tag |
(sas_port->phy_mask << TXQ_PHY_SHIFT));
(phy_mask << TXQ_PHY_SHIFT));
hdr->flags |= flags;
hdr->lens = cpu_to_le32(((resp_len / 4) << 16) | ((req_len - 4) / 4));
@@ -601,7 +603,7 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
struct mvs_slot_info *slot;
void *buf_prd;
u32 tag = tei->tag, hdr_tag;
u32 flags, del_q;
u32 flags, del_q, phy_mask;
void *buf_tmp;
u8 *buf_cmd, *buf_oaf;
dma_addr_t buf_tmp_dma;
@@ -616,9 +618,10 @@ static int mvs_task_prep_ata(struct mvs_info *mvi,
slot = &mvi->slot_info[tag];
slot->tx = mvi->tx_prod;
phy_mask = sas_port->phy_mask;
del_q = TXQ_MODE_I | tag |
(TXQ_CMD_STP << TXQ_CMD_SHIFT) |
(sas_port->phy_mask << TXQ_PHY_SHIFT) |
(phy_mask << TXQ_PHY_SHIFT) |
(mvi_dev->taskfileset << TXQ_SRS_SHIFT);
mvi->tx[mvi->tx_prod] = cpu_to_le32(del_q);
@@ -752,15 +755,14 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
u32 phy_mask;
slot = &mvi->slot_info[tag];
slot->tx = mvi->tx_prod;
phy_mask = ((port->wide_port_phymap) ? port->wide_port_phymap :
sas_port->phy_mask) & TXQ_PHY_MASK;
slot->tx = mvi->tx_prod;
mvi->tx[mvi->tx_prod] = cpu_to_le32(TXQ_MODE_I | tag |
(TXQ_CMD_SSP << TXQ_CMD_SHIFT) |
(phy_mask << TXQ_PHY_SHIFT));
flags = MCH_RETRY;
if (task->ssp_task.enable_first_burst) {
flags |= MCH_FBURST;
@@ -871,12 +873,12 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
#define DEV_IS_GONE(mvi_dev) ((!mvi_dev || (mvi_dev->dev_type == NO_DEVICE)))
static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
struct completion *completion, int lock,
int is_tmf, struct mvs_tmf_task *tmf)
struct completion *completion, int is_tmf,
struct mvs_tmf_task *tmf)
{
struct domain_device *dev = task->dev;
struct mvs_info *mvi;
struct mvs_device *mvi_dev;
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
struct mvs_task_exec_info tei;
struct sas_task *t = task;
struct mvs_slot_info *slot;
@@ -889,14 +891,17 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
tsm->resp = SAS_TASK_UNDELIVERED;
tsm->stat = SAS_PHY_DOWN;
t->task_done(t);
/*
* libsas will use dev->port, should
* not call task_done for sata
*/
if (dev->dev_type != SATA_DEV)
t->task_done(t);
return 0;
}
mvi = mvs_find_dev_mvi(task->dev);
if (lock)
spin_lock_irqsave(&mvi->lock, flags);
spin_lock_irqsave(&mvi->lock, flags);
do {
dev = t->dev;
mvi_dev = (struct mvs_device *)dev->lldd_dev;
@@ -955,8 +960,6 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
goto err_out;
slot = &mvi->slot_info[tag];
t->lldd_task = NULL;
slot->n_elem = n_elem;
slot->slot_tag = tag;
@@ -1011,8 +1014,8 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
err_out_tag:
mvs_tag_free(mvi, tag);
err_out:
err_out:
dev_printk(KERN_ERR, mvi->dev, "mvsas exec failed[%d]!\n", rc);
if (!sas_protocol_ata(t->task_proto))
if (n_elem)
@@ -1023,15 +1026,15 @@ out_done:
MVS_CHIP_DISP->start_delivery(mvi,
(mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1));
}
if (lock)
spin_unlock_irqrestore(&mvi->lock, flags);
spin_unlock_irqrestore(&mvi->lock, flags);
return rc;
}
int mvs_queue_command(struct sas_task *task, const int num,
gfp_t gfp_flags)
{
return mvs_task_exec(task, num, gfp_flags, NULL, 1, 0, NULL);
return mvs_task_exec(task, num, gfp_flags, NULL, 0, NULL);
}
static void mvs_slot_free(struct mvs_info *mvi, u32 rx_desc)
@@ -1073,9 +1076,9 @@ static void mvs_slot_task_free(struct mvs_info *mvi, struct sas_task *task,
mvs_slot_free(mvi, slot_idx);
}
static void mvs_update_wideport(struct mvs_info *mvi, int i)
static void mvs_update_wideport(struct mvs_info *mvi, int phy_no)
{
struct mvs_phy *phy = &mvi->phy[i];
struct mvs_phy *phy = &mvi->phy[phy_no];
struct mvs_port *port = phy->port;
int j, no;
@@ -1139,16 +1142,16 @@ static void *mvs_get_d2h_reg(struct mvs_info *mvi, int i, void *buf)
return NULL;
MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG3);
s[3] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
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] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
s[2] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG1);
s[1] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
s[1] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
MVS_CHIP_DISP->write_port_cfg_addr(mvi, i, PHYR_SATA_SIG0);
s[0] = MVS_CHIP_DISP->read_port_cfg_data(mvi, i);
s[0] = cpu_to_le32(MVS_CHIP_DISP->read_port_cfg_data(mvi, i));
/* Workaround: take some ATAPI devices for ATA */
if (((s[1] & 0x00FFFFFF) == 0x00EB1401) && (*(u8 *)&s[3] == 0x01))
@@ -1285,9 +1288,20 @@ 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)
{
/*Nothing*/
}
struct domain_device *dev;
struct mvs_phy *phy = (struct mvs_phy *)sas_phy->lldd_phy;
struct mvs_info *mvi = phy->mvi;
struct asd_sas_port *port = sas_phy->port;
int phy_no = 0;
while (phy != &mvi->phy[phy_no]) {
phy_no++;
if (phy_no >= MVS_MAX_PHYS)
return;
}
list_for_each_entry(dev, &port->dev_list, dev_list_node)
mvs_do_release_task(phy->mvi, phy_no, NULL);
}
void mvs_port_formed(struct asd_sas_phy *sas_phy)
{
@@ -1322,11 +1336,10 @@ void mvs_free_dev(struct mvs_device *mvi_dev)
memset(mvi_dev, 0, sizeof(*mvi_dev));
mvi_dev->device_id = id;
mvi_dev->dev_type = NO_DEVICE;
mvi_dev->dev_status = MVS_DEV_NORMAL;
mvi_dev->taskfileset = MVS_ID_NOT_MAPPED;
}
#define DEV_IS_EXPANDER(type) ((type == EDGE_DEV) || (type == FANOUT_DEV))
int mvs_dev_found_notify(struct domain_device *dev, int lock)
{
unsigned long flags = 0;
@@ -1347,7 +1360,7 @@ int mvs_dev_found_notify(struct domain_device *dev, int lock)
}
dev->lldd_dev = (void *)mvi_device;
mvi_device->dev_type = dev->dev_type;
mvi_device->mvi_info = mvi;
if (parent_dev && DEV_IS_EXPANDER(parent_dev->dev_type)) {
int phy_id;
u8 phy_num = parent_dev->ex_dev.num_phys;
@@ -1384,10 +1397,8 @@ int mvs_dev_found(struct domain_device *dev)
void mvs_dev_gone_notify(struct domain_device *dev, int lock)
{
unsigned long flags = 0;
struct mvs_info *mvi;
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
mvi = mvs_find_dev_mvi(dev);
struct mvs_info *mvi = mvi_dev->mvi_info;
if (lock)
spin_lock_irqsave(&mvi->lock, flags);
@@ -1395,6 +1406,7 @@ void mvs_dev_gone_notify(struct domain_device *dev, int lock)
if (mvi_dev) {
mv_dprintk("found dev[%d:%x] is gone.\n",
mvi_dev->device_id, mvi_dev->dev_type);
mvs_release_task(mvi, dev);
mvs_free_reg_set(mvi, mvi_dev);
mvs_free_dev(mvi_dev);
} else {
@@ -1473,7 +1485,7 @@ static int mvs_exec_internal_tmf_task(struct domain_device *dev,
task->timer.expires = jiffies + MVS_TASK_TIMEOUT*HZ;
add_timer(&task->timer);
res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 1, 1, tmf);
res = mvs_task_exec(task, 1, GFP_KERNEL, NULL, 1, tmf);
if (res) {
del_timer(&task->timer);
@@ -1560,19 +1572,17 @@ static int mvs_debug_I_T_nexus_reset(struct domain_device *dev)
int mvs_lu_reset(struct domain_device *dev, u8 *lun)
{
unsigned long flags;
int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED;
int rc = TMF_RESP_FUNC_FAILED;
struct mvs_tmf_task tmf_task;
struct mvs_info *mvi = mvs_find_dev_mvi(dev);
struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
tmf_task.tmf = TMF_LU_RESET;
mvi_dev->dev_status = MVS_DEV_EH;
rc = mvs_debug_issue_ssp_tmf(dev, lun, &tmf_task);
if (rc == TMF_RESP_FUNC_COMPLETE) {
num = mvs_find_dev_phyno(dev, phyno);
spin_lock_irqsave(&mvi->lock, flags);
for (i = 0; i < num; i++)
mvs_release_task(mvi, phyno[i], dev);
mvs_release_task(mvi, dev);
spin_unlock_irqrestore(&mvi->lock, flags);
}
/* If failed, fall-through I_T_Nexus reset */
@@ -1584,19 +1594,20 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun)
int mvs_I_T_nexus_reset(struct domain_device *dev)
{
unsigned long flags;
int i, phyno[WIDE_PORT_MAX_PHY], num , rc = TMF_RESP_FUNC_FAILED;
struct mvs_info *mvi = mvs_find_dev_mvi(dev);
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
int rc = TMF_RESP_FUNC_FAILED;
struct mvs_device * mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
if (mvi_dev->dev_status != MVS_DEV_EH)
return TMF_RESP_FUNC_COMPLETE;
else
mvi_dev->dev_status = MVS_DEV_NORMAL;
rc = mvs_debug_I_T_nexus_reset(dev);
mv_printk("%s for device[%x]:rc= %d\n",
__func__, mvi_dev->device_id, rc);
/* housekeeper */
num = mvs_find_dev_phyno(dev, phyno);
spin_lock_irqsave(&mvi->lock, flags);
for (i = 0; i < num; i++)
mvs_release_task(mvi, phyno[i], dev);
mvs_release_task(mvi, dev);
spin_unlock_irqrestore(&mvi->lock, flags);
return rc;
@@ -1612,7 +1623,8 @@ 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_info *mvi = mvs_find_dev_mvi(dev);
struct mvs_device *mvi_dev = (struct mvs_device *)dev->lldd_dev;
struct mvs_info *mvi = mvi_dev->mvi_info;
int_to_scsilun(cmnd->device->lun, &lun);
rc = mvs_find_tag(mvi, task, &tag);
@@ -1621,7 +1633,7 @@ int mvs_query_task(struct sas_task *task)
return rc;
}
tmf_task.tmf = TMF_QUERY_TASK;
tmf_task.tmf = TMF_QUERY_TASK;
tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag);
rc = mvs_debug_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task);
@@ -1641,12 +1653,14 @@ int mvs_query_task(struct sas_task *task)
/* mandatory SAM-3, still need free task/slot info */
int mvs_abort_task(struct sas_task *task)
{
unsigned long flags;
u32 tag;
int i;
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_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) {
@@ -1657,8 +1671,6 @@ int mvs_abort_task(struct sas_task *task)
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;
struct domain_device *dev = task->dev;
struct mvs_info *mvi = mvs_find_dev_mvi(dev);
int_to_scsilun(cmnd->device->lun, &lun);
rc = mvs_find_tag(mvi, task, &tag);
@@ -1667,12 +1679,8 @@ int mvs_abort_task(struct sas_task *task)
rc = TMF_RESP_FUNC_FAILED;
return rc;
}
mv_printk("Abort tag[%x]:[", tag);
for (i = 0; i < 16; i++)
mv_printk("%02x ", cmnd->cmnd[i]);
mv_printk("]\n");
tmf_task.tmf = TMF_ABORT_TASK;
tmf_task.tmf = TMF_ABORT_TASK;
tmf_task.tag_of_task_to_be_managed = cpu_to_le16(tag);
rc = mvs_debug_issue_ssp_tmf(dev, lun.scsi_lun, &tmf_task);
@@ -1681,7 +1689,6 @@ int mvs_abort_task(struct sas_task *task)
if (rc == TMF_RESP_FUNC_COMPLETE) {
u32 slot_no;
struct mvs_slot_info *slot;
struct mvs_info *mvi = mvs_find_dev_mvi(dev);
if (task->lldd_task) {
slot = (struct mvs_slot_info *)task->lldd_task;
@@ -1694,7 +1701,6 @@ int mvs_abort_task(struct sas_task *task)
/* to do free register_set */
} else {
/* SMP */
}
out:
if (rc != TMF_RESP_FUNC_COMPLETE)
@@ -1804,16 +1810,18 @@ int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
struct sas_task *task = slot->task;
struct mvs_device *mvi_dev = NULL;
struct task_status_struct *tstat;
struct domain_device *dev;
bool aborted;
void *to;
enum exec_status sts;
if (unlikely(!task || !task->lldd_task))
if (unlikely(!task || !task->lldd_task || !task->dev))
return -1;
tstat = &task->task_status;
mvi_dev = (struct mvs_device *)task->dev->lldd_dev;
dev = task->dev;
mvi_dev = dev->lldd_dev;
mvs_hba_cq_dump(mvi);
@@ -1905,6 +1913,7 @@ out:
if (sas_protocol_ata(task->task_proto))
mvs_free_reg_set(mvi, mvi_dev);
}
mvs_slot_task_free(mvi, task, slot, slot_idx);
sts = tstat->stat;
@@ -1918,10 +1927,10 @@ out:
return sts;
}
void mvs_release_task(struct mvs_info *mvi,
void mvs_do_release_task(struct mvs_info *mvi,
int phy_no, struct domain_device *dev)
{
int i = 0; u32 slot_idx;
u32 slot_idx;
struct mvs_phy *phy;
struct mvs_port *port;
struct mvs_slot_info *slot, *slot2;
@@ -1942,17 +1951,20 @@ void mvs_release_task(struct mvs_info *mvi,
mv_printk("Release slot [%x] tag[%x], task [%p]:\n",
slot_idx, slot->slot_tag, task);
if (task->task_proto & SAS_PROTOCOL_SSP) {
mv_printk("attached with SSP task CDB[");
for (i = 0; i < 16; i++)
mv_printk(" %02x", task->ssp_task.cdb[i]);
mv_printk(" ]\n");
}
mvs_slot_complete(mvi, slot_idx, 1);
}
}
void mvs_release_task(struct mvs_info *mvi,
struct domain_device *dev)
{
int i, phyno[WIDE_PORT_MAX_PHY], num;
/* housekeeper */
num = mvs_find_dev_phyno(dev, phyno);
for (i = 0; i < num; i++)
mvs_do_release_task(mvi, phyno[i], dev);
}
static void mvs_phy_disconnected(struct mvs_phy *phy)
{
phy->phy_attached = 0;
@@ -2065,9 +2077,11 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
* we need check the interrupt status which belongs to per port.
*/
if (phy->irq_status & PHYEV_DCDR_ERR)
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);
}
if (phy->irq_status & PHYEV_POOF) {
#ifdef SUPPORT_TARGET
@@ -2078,7 +2092,7 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
|| mvi->tgt_port[phy_no].port_attr ==
MVST_INIT_TGT_PORT) {
phy->phy_event |= PHY_PLUG_OUT;
mvs_release_task(mvi, phy_no, NULL);
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 +
@@ -2090,7 +2104,7 @@ void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events)
if (!(phy->phy_event & PHY_PLUG_OUT)) {
int dev_sata = phy->phy_type & PORT_TYPE_SATA;
int ready;
mvs_release_task(mvi, phy_no, NULL);
mvs_do_release_task(mvi, phy_no, NULL);
phy->phy_event |= PHY_PLUG_OUT;
mvs_handle_event(mvi,
(void *)(unsigned long)phy_no,
@@ -2193,7 +2207,9 @@ int mvs_int_rx(struct mvs_info *mvi, bool self_clear)
u8 rc = 0;
u32 slot_idx = rx_desc & RXQ_SLOT_MASK;
struct mvs_slot_info *slot = &mvi->slot_info[slot_idx];
if ((!slot->slot_scst_cmd) && (rx_desc & RXQ_CMD_RX)) {
if (((!slot->slot_scst_mgmt_cmd) ||
(!slot->slot_scst_cmd)) &&
(rx_desc & RXQ_CMD_RX)) {
/* target command */
mvi->rx[rx_prod_idx + 1] = 0;
rc = mvs_tgt.tgt_rsp_ssp_cmd(mvi, rx_desc);

View File

@@ -47,11 +47,10 @@
#endif
#define DRV_NAME "mvsas"
#define DRV_VERSION "0.8.2"
#define DRV_VERSION "0.8.3"
#define _MV_DUMP 0
#define MVS_ID_NOT_MAPPED 0x7f
/* #define DISABLE_HOTPLUG_DMA_FIX */
#define WIDE_PORT_MAX_PHY 4
#define MV_DISABLE_NCQ 0
#define mv_printk(fmt, arg ...) \
@@ -68,6 +67,8 @@ extern struct mvs_tgt_initiator mvs_tgt;
extern struct mvs_info *tgt_mvi;
extern const struct mvs_dispatch mvs_64xx_dispatch;
extern const struct mvs_dispatch mvs_94xx_dispatch;
#define DEV_IS_EXPANDER(type) \
((type == EDGE_DEV) || (type == FANOUT_DEV))
#define bit(n) ((u32)1 << n)
@@ -104,6 +105,12 @@ extern const struct mvs_dispatch mvs_94xx_dispatch;
#define SATA_RECEIVED_DMA_FIS(reg_set) \
(SATA_RECEIVED_FIS_LIST(reg_set) + 0x00)
enum dev_status {
MVS_DEV_NORMAL = 0x0,
MVS_DEV_EH = 0x1,
};
struct mvs_info;
struct mvs_dispatch {
@@ -186,9 +193,12 @@ struct mvs_chip_info {
u32 fis_offs;
u32 fis_count;
u32 srs_sz;
u32 sg_width;
u32 slot_width;
const struct mvs_dispatch *dispatch;
};
#define MVS_MAX_SG (1U << mvi->chip->sg_width)
#define MVS_CHIP_SLOT_SZ (1U << mvi->chip->slot_width)
#define MVS_RX_FISL_SZ \
(mvi->chip->fis_offs + (mvi->chip->fis_count * 0x100))
@@ -243,13 +253,16 @@ struct mvs_phy {
};
struct mvs_device {
struct list_head dev_entry;
enum sas_dev_type dev_type;
struct mvs_info *mvi_info;
struct domain_device *sas_device;
u32 attached_phy;
u32 device_id;
u32 runing_req;
u8 taskfileset;
struct list_head dev_entry;
u8 dev_status;
u16 reserved;
};
struct mvs_slot_info {
@@ -274,6 +287,7 @@ struct mvs_slot_info {
u32 target_cmd_tag;
/* interrnal command if NULL */
void *slot_scst_cmd;
void *slot_scst_mgmt_cmd;
struct mvst_port *slot_tgt_port;
#endif
void *response;
@@ -329,8 +343,7 @@ struct mvs_info {
const struct mvs_chip_info *chip;
int tags_num;
u32 tags[MVS_SLOTS >> 5];
DECLARE_BITMAP(tags, MVS_SLOTS);
/* further per-slot information */
struct mvs_phy phy[MVS_MAX_PHYS];
struct mvs_port port[MVS_MAX_PHYS];
@@ -417,7 +430,9 @@ int mvs_lu_reset(struct domain_device *dev, u8 *lun);
int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags);
int mvs_I_T_nexus_reset(struct domain_device *dev);
int mvs_query_task(struct sas_task *task);
void mvs_release_task(struct mvs_info *mvi, int phy_no,
void mvs_do_release_task(struct mvs_info *mvi,
int phy_no, struct domain_device *dev);
void mvs_release_task(struct mvs_info *mvi,
struct domain_device *dev);
void mvs_int_port(struct mvs_info *mvi, int phy_no, u32 events);
void mvs_update_phyinfo(struct mvs_info *mvi, int i, int get_st);

View File

@@ -1,3 +1,28 @@
/*
* Marvell 88SE64xx/88SE94xx main function
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
*
* This file is licensed under GPLv2.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of the
* License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifdef SUPPORT_TARGET
#include "mv_sas.h"
#include "mv_spi.h"

View File

@@ -1,3 +1,27 @@
/*
* Marvell 88SE64xx/88SE94xx main function
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
*
* This file is licensed under GPLv2.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of the
* License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifdef SUPPORT_TARGET
#ifndef _MV_SPI_H_
#define _MV_SPI_H_

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,27 @@
/*
* Marvell 88SE64xx/88SE94xx main function
*
* Copyright 2007 Red Hat, Inc.
* Copyright 2008 Marvell. <kewei@marvell.com>
*
* This file is licensed under GPLv2.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; version 2 of the
* License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*/
#ifdef SUPPORT_TARGET
#ifndef _MVSAST_H
#define _MVSAST_H
@@ -5,8 +29,6 @@
#include "scst_debug.h"
#include "mv_sas.h"
#define SUPPORT_AEN
struct mvs_info;
#ifdef MV_DEBUG
#ifdef CONFIG_SCST_DEBUG
@@ -69,6 +91,10 @@ extern unsigned long mvst_trace_flag;
#define PROTOCOL_SSP 0x1
#define PROTOCOL_STP 0x2
/* cmd type for build cmd */
#define MVST_CMD 0x0
#define MVST_TMF 0x1
/* defines for address frame types */
#define ADDRESS_IDENTIFY_FRAME 0x00
#define ADDRESS_OPEN_FRAME 0x01
@@ -91,6 +117,15 @@ extern unsigned long mvst_trace_flag;
#define MVST_STATE_SEND_STATUS 6 /*Target sending status */
#define MVST_STATE_SEND_DATA_RETRY 7 /*Command failed,retry sending data */
/* TM failed */
#define MVST_TM_COMPL 0x00
#define MVST_TM_INVALID_FR 0x02
#define MVST_TM_NOT_SUPPORT 0x04
#define MVST_TM_FAILED 0x05
#define MVST_TM_SUCCEED 0x08
#define MVST_TM_INCRT_LUN 0x09
#define MVST_TM_OVLAP_TAG 0x0a
#define MVST_MAX_CDB_LEN 16
#define MVST_TIMEOUT 10 /* in seconds */
@@ -441,10 +476,8 @@ struct mvs_tgt_initiator {
/* Callbacks */
u8 (*tgt_rsp_ssp_cmd)(struct mvs_info *mvi, u32 rx_desc);
void (*tgt_cmd_cmpl)(struct mvs_info *mvi, u32 rx_desc);
void (*tgt_async_event)(u16 code, struct mvs_info *mvi, u16 *mailbox);
void (*tgt_host_action)(struct mvs_info *mvi,
enum mvst_tgt_host_action_t action, u8 phyid);
int (*tgt_send_cmd)(struct mvs_info *mvi);
};
/*
@@ -499,12 +532,20 @@ struct mvst_cmd {
struct list_head cmd_entry;
struct mvst_sess *sess;
struct scst_cmd *scst_cmd;
struct scst_mgmt_cmd *scst_mcmd;
int cmd_state;
struct ssp_frame_header *ssp_hdr;
struct ssp_command_iu *command_iu;
union {
struct ssp_command_iu *command_iu;
struct ssp_task_iu *task_iu;
};
struct open_address_frame *open_frame;
struct ssp_frame_header save_ssp_hdr;
struct ssp_command_iu save_command_iu;
union {
struct ssp_command_iu save_command_iu;
struct ssp_task_iu save_task_iu;
};
struct open_address_frame save_open_frame;
dma_addr_t dma_handle;
struct mvst_port *cmd_tgt_port;
@@ -526,11 +567,6 @@ struct mvst_tgt {
struct list_head sess_list;
};
struct mvst_mgmt_cmd {
struct mvst_sess *sess;
struct ssp_task_iu task_iu;
};
struct mvst_prm {
struct mvst_tgt *tgt;
uint16_t req_cnt;