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;