From 899450e0cdab97b01d0187859c07e2e791e31140 Mon Sep 17 00:00:00 2001 From: Andy Yan Date: Tue, 12 May 2009 06:54:54 +0000 Subject: [PATCH] 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 --- mvsas_tgt/mv_64xx.c | 11 +- mvsas_tgt/mv_94xx.c | 11 +- mvsas_tgt/mv_defs.h | 10 +- mvsas_tgt/mv_init.c | 14 +- mvsas_tgt/mv_sas.c | 174 +++++++------ mvsas_tgt/mv_sas.h | 27 +- mvsas_tgt/mv_spi.c | 25 ++ mvsas_tgt/mv_spi.h | 24 ++ mvsas_tgt/mv_tgt.c | 583 ++++++++++++++++++++++---------------------- mvsas_tgt/mv_tgt.h | 58 ++++- 10 files changed, 531 insertions(+), 406 deletions(-) diff --git a/mvsas_tgt/mv_64xx.c b/mvsas_tgt/mv_64xx.c index 48c14791e..90f168e63 100644 --- a/mvsas_tgt/mv_64xx.c +++ b/mvsas_tgt/mv_64xx.c @@ -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); diff --git a/mvsas_tgt/mv_94xx.c b/mvsas_tgt/mv_94xx.c index 5eb5f664b..53a5f1999 100644 --- a/mvsas_tgt/mv_94xx.c +++ b/mvsas_tgt/mv_94xx.c @@ -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); diff --git a/mvsas_tgt/mv_defs.h b/mvsas_tgt/mv_defs.h index 6f8e90833..e5d054d23 100644 --- a/mvsas_tgt/mv_defs.h +++ b/mvsas_tgt/mv_defs.h @@ -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, diff --git a/mvsas_tgt/mv_init.c b/mvsas_tgt/mv_init.c index e81c955cc..e9724f175 100644 --- a/mvsas_tgt/mv_init.c +++ b/mvsas_tgt/mv_init.c @@ -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; diff --git a/mvsas_tgt/mv_sas.c b/mvsas_tgt/mv_sas.c index 4a5d9c860..503c95fda 100644 --- a/mvsas_tgt/mv_sas.c +++ b/mvsas_tgt/mv_sas.c @@ -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); diff --git a/mvsas_tgt/mv_sas.h b/mvsas_tgt/mv_sas.h index 4ab5ad937..c09b47825 100644 --- a/mvsas_tgt/mv_sas.h +++ b/mvsas_tgt/mv_sas.h @@ -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); diff --git a/mvsas_tgt/mv_spi.c b/mvsas_tgt/mv_spi.c index 9c5d8311b..4057cc4c4 100644 --- a/mvsas_tgt/mv_spi.c +++ b/mvsas_tgt/mv_spi.c @@ -1,3 +1,28 @@ +/* + * Marvell 88SE64xx/88SE94xx main function + * + * Copyright 2007 Red Hat, Inc. + * Copyright 2008 Marvell. + * + * 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" diff --git a/mvsas_tgt/mv_spi.h b/mvsas_tgt/mv_spi.h index a201bfaa2..b72106ec8 100644 --- a/mvsas_tgt/mv_spi.h +++ b/mvsas_tgt/mv_spi.h @@ -1,3 +1,27 @@ +/* + * Marvell 88SE64xx/88SE94xx main function + * + * Copyright 2007 Red Hat, Inc. + * Copyright 2008 Marvell. + * + * 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_ diff --git a/mvsas_tgt/mv_tgt.c b/mvsas_tgt/mv_tgt.c index e66c15767..cf16ac408 100644 --- a/mvsas_tgt/mv_tgt.c +++ b/mvsas_tgt/mv_tgt.c @@ -1,3 +1,27 @@ +/* + * Marvell 88SE64xx/88SE94xx main function + * + * Copyright 2007 Red Hat, Inc. + * Copyright 2008 Marvell. + * + * 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 #include @@ -24,7 +48,6 @@ unsigned long mvst_trace_flag = MVST_DEFAULT_LOG_FLAGS; #endif - #ifndef SUPPORT_TARGET #error "SUPPORT_TARGET is NOT DEFINED" #endif @@ -38,12 +61,9 @@ static void mvst_task_mgmt_fn_done(struct scst_mgmt_cmd *mcmd); static int mvst_report_event(struct scst_aen *aen); /* Predefs for callbacks handed to mvst(target) */ static u8 mvst_response_ssp_command(struct mvs_info *mvi, u32 rx_desc); -static void mvst_async_event(uint16_t code, struct mvs_info *mvi, - uint16_t *mailbox); static void mvst_cmd_completion(struct mvs_info *mvi, u32 rx_desc); static void mvst_host_action(struct mvs_info *mvi, enum mvst_tgt_host_action_t action, u8 phyid); -static int mvst_send_cmd(struct mvs_info *mvi); static int mvst_start_sas_target(struct mvs_info *mvi, u8 id); static int mvst_restart_free_list(struct mvs_info *mvi, u8 slot_id); @@ -158,13 +178,6 @@ static inline void mvst_exec_queue(struct mvs_info *mvi) mw32(MVS_TX_PROD_IDX, (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); } -/* mvi->lock supposed to be held on entry */ -static inline void mvst_send_notify_ack(struct mvs_info *mvi, - struct mvst_mgmt_cmd *mcmd, int status) -{ - -} - /* * register with initiator driver (but target mode isn't enabled till * it's turned on via sysfs) @@ -176,9 +189,7 @@ static int mvst_target_detect(struct scst_tgt_template *templ) .magic = MVST_TARGET_MAGIC, .tgt_rsp_ssp_cmd = mvst_response_ssp_command, .tgt_cmd_cmpl = mvst_cmd_completion, - .tgt_async_event = mvst_async_event, .tgt_host_action = mvst_host_action, - .tgt_send_cmd = mvst_send_cmd }; TRACE_ENTRY(); @@ -208,9 +219,7 @@ static void mvst_free_session_done(struct scst_session *scst_sess) sess = (struct mvst_sess *)scst_sess_get_tgt_priv(scst_sess); sBUG_ON(sess == NULL); tgt = sess->tgt; - kfree(sess); - if (tgt == NULL) goto out; @@ -316,7 +325,6 @@ static int mvst_target_release(struct scst_tgt *scst_tgt) scst_tgt_set_tgt_priv(scst_tgt, NULL); mvi->tgt = NULL; spin_unlock_irqrestore(&mvi->lock, flags); - kfree(tgt); TRACE_EXIT_RES(res); @@ -337,6 +345,7 @@ mvst_put_slot(struct mvs_info *mvi, struct mvs_slot_info *slot) slot->target_cmd_tag = 0xdeadbeef; slot->tx = 0xdeadbeef; slot->slot_scst_cmd = NULL; + slot->slot_scst_mgmt_cmd = NULL; slot->response = NULL; slot->open_frame = NULL; slot->slot_tgt_port = NULL; @@ -365,6 +374,7 @@ mvst_get_slot(struct mvs_info *mvi, struct mvst_port *tgt_port) slot->target_cmd_tag = tag; slot->slot_tgt_port = tgt_port; slot->slot_scst_cmd = NULL; + slot->slot_scst_mgmt_cmd = NULL; slot->open_frame = NULL; slot->tx = mvi->tx_prod; list_add_tail(&slot->entry, &slot->slot_tgt_port->slot_list); @@ -373,11 +383,10 @@ mvst_get_slot(struct mvs_info *mvi, struct mvst_port *tgt_port) } static int mvst_prep_resp_frame(struct mvst_prm *prm, - struct mvs_slot_info *slot, u8 sense_data) + struct mvs_slot_info *slot, u8 datapres) { - u8 has_data = 0; u16 tag; - void *buf_tmp, *buf_cmd; + void *buf_tmp; dma_addr_t buf_tmp_dma; u32 resp_len = 0, req_len = 0, prd_len = 0; const u32 max_resp_len = SB_RFB_MAX; @@ -388,6 +397,7 @@ static int mvst_prep_resp_frame(struct mvst_prm *prm, struct mvs_prd *buf_prd; struct open_address_frame *open_frame; struct mv_ssp_response_iu *response_iu; + TRACE_ENTRY(); tag = slot->target_cmd_tag; cmd_hdr = (struct mvs_cmd_header *)&mvi->slot[tag]; @@ -402,25 +412,6 @@ static int mvst_prep_resp_frame(struct mvst_prm *prm, delivery_q->phy = cmd->cmd_tgt_port->wide_port_phymap; delivery_q->slot_nm = tag; - if (sense_data) { - if ((prm->rq_result) && (SCST_SENSE_VALID(prm->sense_buffer))) { - req_len = 24 + prm->sense_buffer_len; - has_data = 1; - } else { - req_len = 24; - has_data = 0; - } - } else { - if (prm->rq_result) { - req_len = 24 + 4; - has_data = 1; - } else { - req_len = 24; - has_data = 0; - } - } - req_len += sizeof(struct ssp_frame_header); - cmd_hdr->ssp_frame_type = MCH_SSP_FR_RESP; cmd_hdr->ssp_passthru = MCH_SSP_MODE_NORMAL; @@ -436,11 +427,35 @@ static int mvst_prep_resp_frame(struct mvst_prm *prm, * arrange MVS_SLOT_BUF_SZ-sized DMA buffer according to our needs */ /* command header dword 4 -5 */ - /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ************** */ - buf_tmp = buf_cmd = slot->buf; + /* region 1: command table area (MVS_SSP_CMD_SZ bytes) ******* */ + buf_tmp = slot->buf; buf_tmp_dma = slot->buf_dma; cmd_hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); + req_len += sizeof(struct ssp_frame_header); + req_len += 24; + if (datapres == SENSE_DATA) { + if (SCST_SENSE_VALID(prm->sense_buffer)) + req_len += prm->sense_buffer_len; + else + datapres = 0; + } else if (datapres == RESPONSE_DATA) + req_len += 4; + /* fill in response frame IU */ + response_iu = (struct mv_ssp_response_iu *)(buf_tmp + + sizeof(struct ssp_frame_header)); + response_iu->status = prm->rq_result; + response_iu->datapres = datapres; + if (datapres == RESPONSE_DATA) { + response_iu->response_data_len = + cpu_to_be32(prm->sense_buffer_len); + } else if (datapres == SENSE_DATA) { + response_iu->response_data_len = + cpu_to_be32(prm->sense_buffer_len); + } + memcpy(response_iu->data, + prm->sense_buffer, prm->sense_buffer_len); + /* command header dword 6 -7 */ buf_tmp += req_len; buf_tmp_dma += req_len; @@ -479,7 +494,6 @@ static int mvst_prep_resp_frame(struct mvst_prm *prm, be16_to_cpu(prm->cmd->open_frame->received_tag); open_frame->dest_sas_addr = mvst_get_be_sas_addr((u8 *)&prm->cmd->open_frame->src_sas_addr); - /* for passthru mode */ /* fill in SSP frame header (Command Table.SSP frame header) */ if (cmd_hdr->ssp_passthru == MCH_SSP_MODE_PASSTHRU) { @@ -497,33 +511,12 @@ static int mvst_prep_resp_frame(struct mvst_prm *prm, ssp_hdr->tag = be16_to_cpu(prm->cmd->ssp_hdr->tag); } - /* fill in xfer ready frame IU */ - buf_cmd += sizeof(struct ssp_frame_header); - response_iu = (struct mv_ssp_response_iu *)buf_cmd; - - if (has_data == 0) { - response_iu->datapres = NO_DATA; - } else if (sense_data) { - response_iu->status = prm->rq_result; - response_iu->datapres = SENSE_DATA; - response_iu->sense_data_len = - cpu_to_be32(prm->sense_buffer_len); - memcpy(response_iu->data, - prm->sense_buffer, prm->sense_buffer_len); - } else { - /* response data */ - response_iu->datapres = RESPONSE_DATA; - response_iu->response_data_len = cpu_to_be32((int)4); - response_iu->data[3] = INVALID_FRAME; - } - TRACE_EXIT(); return 0; } static int -mvst_send_resp_deferred(struct mvs_info *mvi, - struct mvst_cmd *cmd) +mvst_send_resp(struct mvs_info *mvi, struct mvst_cmd *cmd) { struct mvst_prm prm = { 0 }; struct scst_cmd *scst_cmd = cmd->scst_cmd; @@ -532,6 +525,7 @@ mvst_send_resp_deferred(struct mvs_info *mvi, u32 res = SCST_TGT_RES_SUCCESS; TRACE_ENTRY(); + prm.cmd = (struct mvst_cmd *)scst_cmd_get_tgt_priv(scst_cmd); prm.sg = scst_cmd_get_sg(scst_cmd); prm.bufflen = scst_cmd_get_resp_data_len(scst_cmd); @@ -553,7 +547,7 @@ mvst_send_resp_deferred(struct mvs_info *mvi, } /* save scst cmd */ slot->slot_scst_cmd = scst_cmd; - mvst_prep_resp_frame(&prm, slot, 1); + mvst_prep_resp_frame(&prm, slot, SENSE_DATA); pass++; mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); @@ -574,11 +568,11 @@ out_done: } -static int mvst_prep_data_frame_sg(struct mvst_prm *prm, - struct mvs_slot_info *slot, u8 no_response) +static int mvst_prep_data_frame(struct mvst_prm *prm, + struct mvs_slot_info *slot, u8 datapres) { u16 tag; - u8 *buf_tmp, sense_data; + u8 *buf_tmp; dma_addr_t buf_tmp_dma; u32 resp_len, prd_len = 0; const u32 max_resp_len = SB_RFB_MAX; @@ -591,6 +585,7 @@ static int mvst_prep_data_frame_sg(struct mvst_prm *prm, struct mv_ssp_response_iu *response_iu; TRACE_ENTRY(); + tag = slot->target_cmd_tag; cmd_hdr = (struct mvs_cmd_header *)&mvi->slot[tag]; /* get free delivery queue */ @@ -604,16 +599,16 @@ static int mvst_prep_data_frame_sg(struct mvst_prm *prm, delivery_q->phy = prm->cmd->cmd_tgt_port->wide_port_phymap; delivery_q->slot_nm = tag; - if ((prm->rq_result) && (SCST_SENSE_VALID(prm->sense_buffer))) - sense_data = 1; - else - sense_data = 0; + if (datapres == SENSE_DATA) { + if (SCST_SENSE_VALID(prm->sense_buffer)) + datapres = SENSE_DATA; + else + datapres = 0; + } /* command header dword 0 */ cmd_hdr->prd_entry_count = prm->sg_cnt; - cmd_hdr->ssp_frame_type = MCH_SSP_FR_READ_RESP; - cmd_hdr->ssp_passthru = MCH_SSP_MODE_NORMAL; /* command header dword 1 */ @@ -641,11 +636,9 @@ static int mvst_prep_data_frame_sg(struct mvst_prm *prm, /* prepare response frame following data */ buf_tmp += sizeof(struct ssp_frame_header); response_iu = (struct mv_ssp_response_iu *)buf_tmp; - if (sense_data == 0) { - response_iu->datapres = NO_DATA; - } else if (!no_response) { - response_iu->status = prm->rq_result; - response_iu->datapres = SENSE_DATA; + response_iu->datapres = datapres; + response_iu->status = prm->rq_result; + if (datapres) { response_iu->sense_data_len = cpu_to_le32(prm->sense_buffer_len); memcpy(response_iu->data, @@ -723,7 +716,7 @@ static int mvst_prep_data_frame_sg(struct mvst_prm *prm, } static int -mvst_send_data_frame_sg(struct mvs_info *mvi, +mvst_send_data_resp(struct mvs_info *mvi, struct mvst_prm *prm) { u16 pass = 0; @@ -739,7 +732,7 @@ mvst_send_data_frame_sg(struct mvs_info *mvi, } /* save scst cmd */ slot->slot_scst_cmd = cmd->scst_cmd; - mvst_prep_data_frame_sg(prm, slot, prm->rq_result); + mvst_prep_data_frame(prm, slot, SENSE_DATA); pass++; mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); /* Mid-level is done processing */ @@ -756,31 +749,6 @@ out_done: return res; } - -/* Be called from irq contex */ -static int -mvst_send_cmd(struct mvs_info *mvi) -{ - u32 res = SCST_TGT_RES_SUCCESS; - u8 pass = 0; - struct list_head *pos, *n; - struct mvst_cmd *cmd; - - BUG_ON(!in_irq()); - list_for_each_safe(pos, n, &mvi->data_cmd_list) { - cmd = container_of(pos, struct mvst_cmd, cmd_entry); - if (cmd->cmd_state == MVST_STATE_PROCESSED) - continue; /* has sent command */ - res = mvst_send_resp_deferred(mvi, cmd); - if (res == SCST_TGT_RES_QUEUE_FULL) { - /* no resource */ - goto out_cmd; - } - pass++; - } -out_cmd: - return res; -} static int mvst_xmit_response(struct scst_cmd *scst_cmd) { int res = SCST_TGT_RES_SUCCESS; @@ -791,6 +759,7 @@ static int mvst_xmit_response(struct scst_cmd *scst_cmd) struct mvs_info *mvi; TRACE_ENTRY(); + TRACE(TRACE_SCSI, "xmit_respons scmd[0x%p] tag=%ld, sg_cnt=%d", scst_cmd, scst_cmd_get_tag(scst_cmd), scst_cmd->sg_cnt); @@ -856,18 +825,18 @@ static int mvst_xmit_response(struct scst_cmd *scst_cmd) list_add_tail(&prm.cmd->cmd_entry, &mvi->data_cmd_list); if (mvst_has_data(scst_cmd)) { /* prepare send data frame */ - res = mvst_send_data_frame_sg(mvi, &prm); + res = mvst_send_data_resp(mvi, &prm); if (res) TRACE_DBG("xmit_response" - "mvst_send_data_frame failed[%d]!\n", + "mvst_send_data failed[%d]!\n", res); goto out_done; } else { /* prepare response frame */ - res = mvst_send_resp_deferred(mvi, prm.cmd); + res = mvst_send_resp(mvi, prm.cmd); if (res) TRACE_DBG("xmit_response" - "mvst_send_resp_deferred failed[%d]!\n", + "mvst_send_resp failed[%d]!\n", res); } @@ -880,12 +849,8 @@ out: return res; out_tgt_free: - /*ToDo: check and set scst_set_delivery_status(), if necessary */ - if (!in_interrupt()) { - msleep(250); - scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_DIRECT); - } else - scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_TASKLET); + + scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_TASKLET); /* !! At this point cmd could be already freed !! */ goto out; } @@ -908,8 +873,8 @@ static int mvst_prep_xfer_frame(struct mvst_prm *prm, struct ssp_xfrd_iu *xfrd_iu; TRACE_ENTRY(); - tag = slot->target_cmd_tag; + tag = slot->target_cmd_tag; cmd_hdr = (struct mvs_cmd_header *)&mvi->slot[tag]; /* get free delivery queue */ delivery_q = (struct mvs_delivery_queue *)&mvi->tx[mvi->tx_prod]; @@ -937,7 +902,6 @@ static int mvst_prep_xfer_frame(struct mvst_prm *prm, cmd_hdr->target_tag = cpu_to_le16(tag); cmd_hdr->tag = be16_to_cpu(prm->cmd->ssp_hdr->tag); - /* command header dword 3 */ cmd_hdr->data_len = cpu_to_le32(prm->bufflen); @@ -950,7 +914,6 @@ static int mvst_prep_xfer_frame(struct mvst_prm *prm, buf_tmp_dma = slot->buf_dma; cmd_hdr->cmd_tbl = cpu_to_le64(buf_tmp_dma); - /* command header dword 6 -7 */ buf_tmp += req_len; buf_tmp_dma += req_len; @@ -1038,6 +1001,7 @@ static int mvst_prep_xfer_frame(struct mvst_prm *prm, static int mvst_pci_map_calc_cnt(struct mvst_prm *prm) { + struct mvs_info *mvi = prm->tgt->mvi; int res = 0; sBUG_ON(prm->sg_cnt == 0); @@ -1052,8 +1016,7 @@ static int mvst_pci_map_calc_cnt(struct mvst_prm *prm) * the continuation entries, but bug on now */ - sBUG_ON(prm->seg_cnt > SG_ALL); - + sBUG_ON(prm->seg_cnt > MVS_MAX_SG); out: TRACE_DBG("seg_cnt=%d, req_cnt=%d, res=%d", prm->seg_cnt, prm->req_cnt, res); @@ -1139,8 +1102,6 @@ out_done: return res; } - - static inline void mvst_free_cmd(struct mvst_cmd *cmd) { kmem_cache_free(mvst_cmd_cachep, cmd); @@ -1185,7 +1146,6 @@ static int mvst_slot_tgt_err(struct mvs_info *mvi, u32 slot_idx) return stat; } - /* mvi->lock supposed to be held on entry */ static void mvst_do_cmd_completion(struct mvs_info *mvi, uint32_t rx_desc) @@ -1250,6 +1210,13 @@ static void mvst_do_cmd_completion(struct mvs_info *mvi, if (cmd->cmd_state == MVST_STATE_PROCESSED) { TRACE_DBG("Command %p finished", cmd); + if (mvst_has_data(scst_cmd)) { + pci_unmap_sg(mvi->pdev, + scst_cmd_get_sg(scst_cmd), + scst_cmd_get_sg_cnt(scst_cmd), + scst_to_tgt_dma_dir( + scst_cmd_get_data_direction(scst_cmd))); + } if (err) goto out; list_del(&cmd->cmd_entry); @@ -1292,6 +1259,12 @@ static void mvst_do_cmd_completion(struct mvs_info *mvi, mvi->instance, cmd->cmd_state); goto out_free; } + } else if (slot->slot_scst_mgmt_cmd) { + TRACE_DBG("Found tmf frame[0x%x] complete", + cmd_hdr->ssp_frame_type); + cmd = scst_mgmt_cmd_get_tgt_priv(slot->slot_scst_mgmt_cmd); + kfree(cmd); + goto out; } else { TRACE_DBG("Found internal target frame[0x%x] complete", cmd_hdr->ssp_frame_type); @@ -1307,11 +1280,8 @@ out_free: TRACE_MGMT_DBG("%s", "Finishing failed CTIO"); scst_set_delivery_status(scst_cmd, SCST_CMD_DELIVERY_FAILED); } - if (!in_interrupt()) { - msleep(250); - scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_DIRECT); - } else - scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_TASKLET); + + scst_tgt_cmd_done(scst_cmd, SCST_CONTEXT_TASKLET); goto out; } @@ -1323,6 +1293,7 @@ static void mvst_cmd_completion(struct mvs_info *mvi, uint32_t rx_desc) struct mvs_cmd_header *cmd_hdr = NULL; TRACE_ENTRY(); + sBUG_ON(mvi == NULL); if ((mvi->tgt != NULL) && MVST_IN_TARGET_MODE(mvi)) @@ -1401,7 +1372,6 @@ static int mvst_do_send_cmd_to_scst(struct mvs_info *mvi, struct mvst_cmd *cmd) #else context = SCST_CONTEXT_TASKLET; #endif - TRACE_DBG("Context %x", context); TRACE(TRACE_SCSI, "START Command (tag %ld)", scst_cmd_get_tag(cmd->scst_cmd)); @@ -1496,72 +1466,14 @@ struct mvst_port *mvst_get_port_by_sasaddr(struct mvs_info *mvi, return &mvi->tgt_port[n]; } -int mvst_alloc_session(struct mvst_sess *sess, struct mvst_tgt *tgt, u64 sas_addr) +int mvst_build_cmd(struct mvs_info *mvi, + struct mvs_slot_info *slot, + struct mvst_cmd **pcmd, + int cmd_type) { int res = 0; - struct mvs_info *mvi = tgt->mvi; - - TRACE_ENTRY(); - sess = mvst_find_sess_by_lid(tgt, sas_addr); - if (unlikely(sess == NULL)) { - sess = kzalloc(sizeof(*sess), GFP_ATOMIC); - if (sess == NULL) { - TRACE(TRACE_OUT_OF_MEM, "%s", - "Allocation of sess failed"); - res = -ENOMEM; - goto out; - } - - sess->tgt = tgt; - sess->initiator_sas_addr = sas_addr; - INIT_LIST_HEAD(&sess->sess_entry); - - /* register session (remote initiator) */ - { - char *name; - name = mvst_make_name(mvi); - if (name == NULL) { - PRINT_ERROR("can not make name" - "for session %p", sess); - res = -ESRCH; - goto out; - } - - sess->scst_sess = scst_register_session( - tgt->scst_tgt, SCST_ATOMIC, name, sess, - mvst_alloc_session_done); - kfree(name); - } - - if (sess->scst_sess == NULL) { - PRINT_ERROR("mvst tgt(%ld): scst_register_session()" - "failed for host %ld(%p)", - mvi->instance, - mvi->host_no, mvi); - res = -EFAULT; - goto out; - } - scst_sess_set_tgt_priv(sess->scst_sess, sess); - - /* add session data to host data structure */ - list_add(&sess->sess_entry, &tgt->sess_list); - tgt->sess_count++; - } -out: - TRACE_EXIT(); - return res; -} - -/* mvi->lock supposed to be held on entry */ - -static int mvst_send_cmd_to_scst(struct mvs_info *mvi, - struct mvs_slot_info *slot) -{ - int res = 0; - u64 initiator_sas_addr, src_sas_addr, dst_sas_addr; - struct mvst_tgt *tgt; - struct mvst_sess *sess = NULL; - struct mvst_cmd *cmd; + u64 src_sas_addr, dst_sas_addr; + struct mvst_cmd *cmd = NULL; struct open_address_frame *open_frame = (struct open_address_frame *)slot->open_frame; struct ssp_frame_header *ssp_hdr = @@ -1569,14 +1481,16 @@ static int mvst_send_cmd_to_scst(struct mvs_info *mvi, struct ssp_command_iu *ssp_cmd_iu = (struct ssp_command_iu *)((u8 *)ssp_hdr + sizeof(struct ssp_frame_header)); + struct ssp_task_iu *ssp_task_iu = + (struct ssp_task_iu *)((u8 *)ssp_hdr + + sizeof(struct ssp_frame_header)); struct mvst_port *tgt_port; + TRACE_ENTRY(); - initiator_sas_addr = be64_to_cpu(open_frame->src_sas_addr); dst_sas_addr = mvst_get_le_sas_addr((u8 *)&open_frame->dest_sas_addr); src_sas_addr = mvst_get_le_sas_addr((u8 *)&open_frame->src_sas_addr); - tgt = mvi->tgt; tgt_port = mvst_get_port_by_sasaddr(mvi, dst_sas_addr, src_sas_addr); if (tgt_port == NULL) { res = -EFAULT; @@ -1586,11 +1500,7 @@ static int mvst_send_cmd_to_scst(struct mvs_info *mvi, goto out; } - TRACE_DBG("To SCST instance=%ld tag=0x%x src_sas_addr=0x%0llx", - mvi->instance, be16_to_cpu(ssp_hdr->tag), - mvst_get_le_sas_addr((u8 *)&initiator_sas_addr)); - - if (tgt->tgt_shutdown) { + if (mvi->tgt->tgt_shutdown) { TRACE_DBG("New command while device %p is shutting " "down", tgt); res = -EFAULT; @@ -1611,27 +1521,53 @@ static int mvst_send_cmd_to_scst(struct mvs_info *mvi, memset(cmd, 0, sizeof(*cmd)); #endif /* set cmd private data for later use */ - memcpy(&cmd->save_command_iu, ssp_cmd_iu, sizeof(*ssp_cmd_iu)); + if (!cmd_type) + memcpy(&cmd->save_command_iu, + ssp_cmd_iu, sizeof(*ssp_cmd_iu)); + else + memcpy(&cmd->save_task_iu, + ssp_task_iu, sizeof(*ssp_task_iu)); memcpy(&cmd->save_open_frame, open_frame, sizeof(*open_frame)); memcpy(&cmd->save_ssp_hdr, ssp_hdr, sizeof(*ssp_hdr)); - memset(slot->buf, 0, MVS_SLOT_BUF_SZ); - cmd->command_iu = &cmd->save_command_iu; + if (!cmd_type) + cmd->command_iu = &cmd->save_command_iu; + else + cmd->task_iu = &cmd->save_task_iu; cmd->open_frame = &cmd->save_open_frame; cmd->ssp_hdr = &cmd->save_ssp_hdr; - cmd->cmd_tgt_port = tgt_port; /* save SSP Target port */ + cmd->cmd_tgt_port = tgt_port; /* save SSP Target port */ cmd->cmd_state = MVST_STATE_NEW; cmd->transfer_len = 0; cmd->finished_len = 0; cmd->transfer_buf = NULL; -#if 0 - res = mvst_alloc_session(sess, tgt, initiator_sas_addr); - if (res) { - if (-ENOMEM == res) - goto out_free_cmd; - if (-ESRCH == res || -EFAULT == res) - goto out_free_sess; - } -#else +out: + *pcmd = cmd; + TRACE_EXIT(); + return res; +} + + +/* mvi->lock supposed to be held on entry */ +int mvst_send_cmd_to_scst(struct mvs_info *mvi, + struct mvs_slot_info *slot) +{ + int res = 0; + u64 initiator_sas_addr; + struct mvst_tgt *tgt; + struct mvst_sess *sess; + struct mvst_cmd *cmd = NULL; + struct open_address_frame *open_frame = + (struct open_address_frame *)slot->open_frame; + + TRACE_ENTRY(); + + tgt = mvi->tgt; + initiator_sas_addr = be64_to_cpu(open_frame->src_sas_addr); + + res = mvst_build_cmd(mvi, slot, &cmd, MVST_CMD); + if (res) + goto out; + sess = mvst_find_sess_by_lid(tgt, initiator_sas_addr); if (unlikely(sess == NULL)) { sess = kzalloc(sizeof(*sess), GFP_ATOMIC); @@ -1678,7 +1614,6 @@ static int mvst_send_cmd_to_scst(struct mvs_info *mvi, list_add(&sess->sess_entry, &tgt->sess_list); tgt->sess_count++; } -#endif cmd->sess = sess; res = mvst_do_send_cmd_to_scst(mvi, cmd); if (res != 0) @@ -1697,7 +1632,6 @@ out_free_sess: out_free_cmd: mvst_free_cmd(cmd); - goto out; } @@ -1709,11 +1643,11 @@ static int mvst_handle_task_mgmt(struct mvs_info *mvi, u64 initiator_sas_addr; u8 lun[8]; u16 tag; - struct mvst_mgmt_cmd *mcmd; + struct mvst_cmd *cmd = NULL; struct mvst_tgt *tgt; struct mvst_sess *sess; struct open_address_frame *open_frame = - (struct open_address_frame *)slot->buf; + (struct open_address_frame *)slot->open_frame; struct ssp_frame_header *ssp_hdr = (struct ssp_frame_header *)((u8 *)slot->response+8); struct ssp_task_iu *ssp_task_iu = @@ -1727,63 +1661,58 @@ static int mvst_handle_task_mgmt(struct mvs_info *mvi, tag = be16_to_cpu(ssp_task_iu->tag); initiator_sas_addr = be64_to_cpu(open_frame->src_sas_addr); + if (mvst_build_cmd(mvi, slot, &cmd, MVST_TMF)) + goto out; + sess = mvst_find_sess_by_lid(tgt, initiator_sas_addr); if (sess == NULL) { TRACE(TRACE_MGMT, "mvsttgt(%ld): task mgmt fn 0x%x for " "non-existant session", mvi->instance, - ssp_task_iu->task_fun); + cmd->save_task_iu.task_fun); res = -EFAULT; goto out; } - mcmd = kzalloc(sizeof(*mcmd), GFP_ATOMIC); - if (mcmd == NULL) { - TRACE(TRACE_OUT_OF_MEM, "%s", "Allocation of mgmt cmd failed"); - res = -ENOMEM; - goto out; - } + cmd->sess = sess; - mcmd->sess = sess; - memcpy(&mcmd->task_iu, ssp_task_iu, sizeof(*ssp_task_iu)); - - switch (ssp_task_iu->task_fun) { + switch (cmd->save_task_iu.task_fun) { case TMF_CLEAR_ACA: TRACE(TRACE_MGMT, "%s", "TMF_CLEAR_ACA received"); rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_CLEAR_ACA, (uint8_t *)lun, sizeof(lun), - SCST_ATOMIC, mcmd); + SCST_ATOMIC, cmd); break; case TMF_LU_RESET: TRACE(TRACE_MGMT, "%s", "TMF_LU_RESET received"); rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_LUN_RESET, (uint8_t *)&lun, sizeof(lun), - SCST_ATOMIC, mcmd); + SCST_ATOMIC, cmd); break; case TMF_CLEAR_TASK_SET: TRACE(TRACE_MGMT, "%s", "TMF_CLEAR_TASK_SET received"); rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_CLEAR_TASK_SET, (uint8_t *)&lun, sizeof(lun), - SCST_ATOMIC, mcmd); + SCST_ATOMIC, cmd); break; case TMF_ABORT_TASK_SET: TRACE(TRACE_MGMT, "%s", "TMF_ABORT_TASK_SET received"); rc = scst_rx_mgmt_fn_lun(sess->scst_sess, SCST_ABORT_TASK_SET, (uint8_t *)&lun, sizeof(lun), - SCST_ATOMIC, mcmd); + SCST_ATOMIC, cmd); break; case TMF_ABORT_TASK: TRACE(TRACE_MGMT, "%s", "TMF_ABORT_TASK received"); rc = scst_rx_mgmt_fn_tag(sess->scst_sess, SCST_ABORT_TASK, tag, - SCST_ATOMIC, mcmd); + SCST_ATOMIC, cmd); break; default: PRINT_ERROR("mvsttgt(%ld): Unknown task mgmt fn 0x%x", - mvi->instance, ssp_task_iu->task_fun); + mvi->instance, cmd->save_task_iu.task_fun); break; } @@ -1799,19 +1728,19 @@ out: return res; out_free: - kfree(mcmd); + kfree(cmd); goto out; } -static int mvst_notify_attach_chg(struct mvs_info *mvi) +static int mvst_notify_attach_chg(void) { u8 i, j; int res = SCST_AEN_RES_SUCCESS; + struct mvs_info *mvi = ((struct mvs_info **)tgt_mvi)[0]; TRACE_ENTRY(); if (!mvi) return SCST_AEN_RES_FAILED; - #if 0 for (i = 0; i < mvi->chip->n_phy; i++) { struct mvs_phy *phy = &mvi->phy[i]; @@ -1842,7 +1771,7 @@ static int mvst_notify_attach_chg(struct mvs_info *mvi) if (mvi->phy[j].phy_mode) MVS_CHIP_DISP->phy_disable(mvi, j); } - msleep(500); + msleep(2000); for (j = 0; j < mvi->chip->n_phy; j++) { if (mvi->phy[j].phy_mode) { /* enable phy */ @@ -1860,7 +1789,6 @@ static int mvst_notify_attach_chg(struct mvs_info *mvi) static int mvst_notify_unit_attention(struct scst_aen *aen) { int res = SCST_AEN_RES_SUCCESS, key, asc, ascq; - struct mvs_info *mvi = ((struct mvs_info **)tgt_mvi)[0]; TRACE_ENTRY(); @@ -1874,10 +1802,11 @@ static int mvst_notify_unit_attention(struct scst_aen *aen) ascq = aen->aen_sense[13]; /* ASCQ */ } else return res; + switch (key) { case UNIT_ATTENTION: if (asc == 0x3F && ascq == 0xE) - mvst_notify_attach_chg(mvi); + mvst_notify_attach_chg(); break; /* .to support more @@ -1907,43 +1836,141 @@ static int mvst_report_event(struct scst_aen *aen) res = SCST_AEN_RES_NOT_SUPPORTED; break; } - TRACE_EXIT_RES(res); + scst_aen_done(aen); + return res; +} + +static u8 mvst_get_mgmt_status(int status) +{ + u8 resp = 0; + switch (status) { + case SCST_MGMT_STATUS_SUCCESS: + resp = MVST_TM_COMPL; + break; + case SCST_MGMT_STATUS_LUN_NOT_EXIST: + resp = MVST_TM_INCRT_LUN; + break; + case SCST_MGMT_STATUS_FN_NOT_SUPPORTED: + resp = MVST_TM_NOT_SUPPORT; + break; + case SCST_MGMT_STATUS_TASK_NOT_EXIST: + case SCST_MGMT_STATUS_REJECTED: + case SCST_MGMT_STATUS_FAILED: + default: + resp = MVST_TM_FAILED; + break; + } + return resp; +} + +/* mvi->lock supposed to be held on entry */ +static inline int mvst_send_notify_ack(struct mvst_cmd *cmd, int status) +{ + int res = 0; + u8 buf[4] = {0, 0, 0, 0}; + struct mvs_slot_info *resp_slot; + struct mvst_prm prm = { 0 }; + struct mvs_info *mvi = cmd->sess->tgt->mvi; + + TRACE_ENTRY(); + + /* prepare response frame */ + resp_slot = mvst_get_slot(mvi, cmd->cmd_tgt_port); + if (!resp_slot) { + res = SCST_TGT_RES_QUEUE_FULL; + goto out; + } + + resp_slot->slot_scst_mgmt_cmd = cmd->scst_mcmd; + prm.rq_result = SAM_STAT_GOOD; + prm.tgt = mvi->tgt; + prm.seg_cnt = 0; + prm.req_cnt = 1; + prm.sense_buffer_len = 4; + prm.sense_buffer = buf; + prm.cmd = cmd; + + buf[3] = mvst_get_mgmt_status(status); + mvst_prep_resp_frame(&prm, resp_slot, RESPONSE_DATA); + /* Mid-level is done processing */ + cmd->cmd_state = MVST_STATE_SEND_STATUS; + + mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); + MVS_CHIP_DISP->start_delivery(mvi, + (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); +out: + TRACE_EXIT(); return res; } /* SCST Callback */ static void mvst_task_mgmt_fn_done(struct scst_mgmt_cmd *scst_mcmd) { - struct mvst_mgmt_cmd *mcmd; + struct mvst_cmd *cmd; unsigned long flags; - int status; + int status, res = 0; TRACE_ENTRY(); - status = scst_mgmt_cmd_get_status(scst_mcmd); - TRACE_MGMT_DBG("scst_mcmd (%p) status %#x state %#x", scst_mcmd, - status, scst_mcmd->state); - mcmd = scst_mgmt_cmd_get_tgt_priv(scst_mcmd); - if (unlikely(mcmd == NULL)) { - PRINT_ERROR("scst_mcmd %p tgt_spec is NULL", mcmd); + cmd = scst_mgmt_cmd_get_tgt_priv(scst_mcmd); + if (unlikely(cmd == NULL)) { + PRINT_ERROR("scst_mcmd %p tgt_spec is NULL", cmd); goto out; } - spin_lock_irqsave(&mcmd->sess->tgt->mvi->lock, flags); - mvst_send_notify_ack(mcmd->sess->tgt->mvi, mcmd, status); - spin_unlock_irqrestore(&mcmd->sess->tgt->mvi->lock, flags); + cmd->scst_mcmd = scst_mcmd; + status = scst_mgmt_cmd_get_status(scst_mcmd); + spin_lock_irqsave(&cmd->sess->tgt->mvi->lock, flags); + res = mvst_send_notify_ack(cmd, status); + spin_unlock_irqrestore(&cmd->sess->tgt->mvi->lock, flags); scst_mgmt_cmd_set_tgt_priv(scst_mcmd, NULL); - kfree(mcmd); - + if (res) + kfree(cmd); out: TRACE_EXIT(); return; } - -static void mvst_send_busy(struct mvs_info *mvi, struct mvs_slot_info *slot) +static int mvst_send_busy(struct mvs_info *mvi, struct mvs_slot_info *slot) { + int res = 0; + struct mvs_slot_info *resp_slot; + struct mvst_cmd *cmd = NULL; + struct mvst_prm prm = { 0 }; + TRACE_ENTRY(); + + if (mvst_build_cmd(mvi, slot, &cmd, MVST_CMD)) { + mv_printk("failed to build cmd from slot %p\n", slot); + goto out; + } + + /* prepare response frame */ + resp_slot = mvst_get_slot(mvi, cmd->cmd_tgt_port); + if (!resp_slot) { + res = SCST_TGT_RES_QUEUE_FULL; + goto err_out; + } + + prm.cmd = cmd; + prm.rq_result = SAM_STAT_BUSY; + prm.tgt = mvi->tgt; + prm.seg_cnt = 0; + prm.req_cnt = 1; + + mvst_prep_resp_frame(&prm, resp_slot, NO_DATA); + /* Mid-level is done processing */ + cmd->cmd_state = MVST_STATE_SEND_STATUS; + + mvi->tx_prod = (mvi->tx_prod + 1) & (MVS_CHIP_SLOT_SZ - 1); + MVS_CHIP_DISP->start_delivery(mvi, + (mvi->tx_prod - 1) & (MVS_CHIP_SLOT_SZ - 1)); +out: + TRACE_EXIT(); + return res; +err_out: + mvst_free_cmd(cmd); + goto out; } /* mvi->lock supposed to be held on entry */ @@ -1959,7 +1986,6 @@ static u8 mvst_response_ssp_command(struct mvs_info *mvi, uint32_t rx_desc) (struct ssp_frame_header *)((u8 *)slot->response+8); TRACE_ENTRY(); - if (unlikely((mvi->tgt == NULL) || !MVST_IN_TARGET_MODE(mvi))) { TRACE_DBG("receive command, but no tgt. mvi %p tgt_flag %ld", mvi, MVST_IN_TARGET_MODE(mvi)); @@ -2006,7 +2032,7 @@ static u8 mvst_response_ssp_command(struct mvs_info *mvi, uint32_t rx_desc) case SSP_COMMAND: { struct ssp_command_iu *ssp_cmd_iu = NULL; - ssp_cmd_iu = (struct ssp_command_iu *)((u8 *)ssp_hdr + ssp_cmd_iu = (struct ssp_command_iu *)((u8 *)ssp_hdr + sizeof(struct ssp_frame_header)); TRACE_DBG("COMMAND FRAME:lun[0-7]=%016llx.\n", @@ -2063,27 +2089,6 @@ out: return rc; } -/* mvi->lock supposed to be held on entry */ -/* called via callback from mvst */ -static void mvst_async_event(uint16_t code, - struct mvs_info *mvi, uint16_t *mailbox) -{ - TRACE_ENTRY(); - - sBUG_ON(mvi == NULL); - - if (unlikely(mvi->tgt == NULL)) { - TRACE(TRACE_DEBUG|TRACE_MGMT, - "ASYNC EVENT %#x, but no tgt. mvi %p tgt_flag %ld", - code, mvi, MVST_IN_TARGET_MODE(mvi)); - goto out; - } - -out: - TRACE_EXIT(); - return; -} - void mvs_enable_taget_xmt(struct mvs_info *mvi, int PhyId) { void __iomem *regs = mvi->regs; @@ -2099,9 +2104,7 @@ void mvs_enable_taget_xmt(struct mvs_info *mvi, int PhyId) static void mvst_register_tgt_handler(struct mvs_info *mvi) { struct mvst_tgt *tgt = NULL; - int sg_tablesize; unsigned long flags = 0; - struct mvst_sess *sess = NULL; tgt = kzalloc(sizeof(*tgt), GFP_KERNEL); if (tgt == NULL) @@ -2111,9 +2114,6 @@ static void mvst_register_tgt_handler(struct mvs_info *mvi) INIT_LIST_HEAD(&tgt->sess_list); init_waitqueue_head(&tgt->waitQ); - /* set max sg counts */ - sg_tablesize = SG_ALL; - tgt->scst_tgt = scst_register(&tgt_template, MVST_NAME); if (!tgt->scst_tgt) { PRINT_ERROR("mvst tgt(%ld): scst_register() " @@ -2122,7 +2122,8 @@ static void mvst_register_tgt_handler(struct mvs_info *mvi) kfree(tgt); return; } - scst_tgt_set_sg_tablesize(tgt->scst_tgt, sg_tablesize); + + scst_tgt_set_sg_tablesize(tgt->scst_tgt, MVS_MAX_SG); scst_tgt_set_tgt_priv(tgt->scst_tgt, tgt); spin_lock_irqsave(&mvi->lock, flags); @@ -2150,14 +2151,13 @@ static void mvst_unregister_tgt_handler(struct mvs_info *mvi) */ tgt = NULL; } - static void mvst_enable_tgt_port(struct mvs_info *mvi, u8 phyid) { struct mvs_phy *phy; struct asd_sas_phy *sas_phy; u8 id = 0; -#if 0 +#if 0 u8 j = 0, i = 0 /*enable all the phy within the same port*/ for (id = 0, j = 0; id < mvi->chip->n_phy; id++) { @@ -2288,14 +2288,15 @@ 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_TARGET_QUEUE > MVS_CAN_QUEUE) { + if (target_port * (MVS_SLOTS/mvi->chip->n_phy) + > MVS_CAN_QUEUE) { mv_dprintk("Warning: No sufficient slots" "for target port[%d].\n", target_port); break; } mvst_enable_tgt_port(mvi, phyid); - mvst_notify_attach_chg(mvi); + mvst_notify_attach_chg(); mv_dprintk("Enable target mode......\n"); break; @@ -2503,7 +2504,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_TARGET_QUEUE); + } while (++slot_id < MVS_SLOTS/mvi->chip->n_phy); rc = 0; goto out_done; @@ -2597,7 +2598,6 @@ void mvst_int_port(struct mvs_info *mvi, u32 id) /* clean status */ mvs_write_port_irq_stat(mvi, id, phy->irq_status); - /* TBD */ /* * events is port event now , * we need check the interrupt status which belongs to per port. @@ -2726,7 +2726,6 @@ void mvst_msg_insert(struct mvst_msg_queue *msg_queue, unsigned long flags; mv_dprintk("msg insert %d.\n", event); - spin_lock_irqsave(&msg_queue->msg_lock, flags); if (list_empty(&msg_queue->free)) { /* should wreck some havoc ...*/ diff --git a/mvsas_tgt/mv_tgt.h b/mvsas_tgt/mv_tgt.h index c016a6946..ff4badd38 100644 --- a/mvsas_tgt/mv_tgt.h +++ b/mvsas_tgt/mv_tgt.h @@ -1,3 +1,27 @@ +/* + * Marvell 88SE64xx/88SE94xx main function + * + * Copyright 2007 Red Hat, Inc. + * Copyright 2008 Marvell. + * + * 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;