From: Ke Wei <kewei@marvell.com>
To: linux-scsi@vger.kernel.org
Cc: James Bottomley <James.Bottomley@HansenPartnership.com>, jeff@garzik.org
Subject: [PATCH scsi-rc-fixes-2.6] mvsas: fix error handling.
Date: Tue, 08 Apr 2008 18:31:38 +0800 [thread overview]
Message-ID: <47FB498A.2010107@marvell.com> (raw)
Changed error handling: Add a internal queue to send command in mvs_task_abort function.
Set max_id and max_lun to a valid value. It's good for 64xx chip.
BTW, DVD-ROM compatibility needs to test carefully.
Signed-off-by: Ke Wei <kewei@marvell.com>
---
drivers/scsi/mvsas.c | 101 +++++++++++++++++++++++--------------------------
1 files changed, 47 insertions(+), 54 deletions(-)
diff --git a/drivers/scsi/mvsas.c b/drivers/scsi/mvsas.c
index e55b903..b45185e 100644
--- a/drivers/scsi/mvsas.c
+++ b/drivers/scsi/mvsas.c
@@ -639,6 +639,7 @@ struct mvs_slot_info {
void *response;
struct mvs_port *port;
+ struct completion *completion;
};
struct mvs_info {
@@ -674,9 +675,6 @@ struct mvs_info {
/* further per-slot information */
struct mvs_phy phy[MVS_MAX_PHYS];
struct mvs_port port[MVS_MAX_PHYS];
-#ifdef MVS_USE_TASKLET
- struct tasklet_struct tasklet;
-#endif
};
static int mvs_phy_control(struct asd_sas_phy *sas_phy, enum phy_func func,
@@ -1225,7 +1223,7 @@ static void mvs_int_sata(struct mvs_info *mvi)
}
static void mvs_slot_reset(struct mvs_info *mvi, struct sas_task *task,
- u32 slot_idx)
+ u32 slot_idx, struct completion *completion)
{
void __iomem *regs = mvi->regs;
struct domain_device *dev = task->dev;
@@ -1233,6 +1231,7 @@ static void mvs_slot_reset(struct mvs_info *mvi, struct sas_task *task,
struct mvs_port *port = mvi->slot_info[slot_idx].port;
u32 reg_set, phy_mask;
+ mvi->slot_info[slot_idx].completion = completion;
if (!sas_protocol_ata(task->task_proto)) {
reg_set = 0;
phy_mask = (port->wide_port_phymap) ? port->wide_port_phymap :
@@ -1313,7 +1312,7 @@ static int mvs_slot_err(struct mvs_info *mvi, struct sas_task *task,
if (err_dw1 & SLOT_BSY_ERR) {
stat = SAS_QUEUE_FULL;
- mvs_slot_reset(mvi, task, slot_idx);
+ mvs_slot_reset(mvi, task, slot_idx, NULL);
}
switch (task->task_proto) {
case SAS_PROTOCOL_SSP:
@@ -1350,17 +1349,17 @@ static int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
mvs_hba_cq_dump(mvi);
spin_lock(&task->task_state_lock);
+ task->task_state_flags &=
+ ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
+ task->task_state_flags |= SAS_TASK_STATE_DONE;
aborted = task->task_state_flags & SAS_TASK_STATE_ABORTED;
- if (!aborted) {
- task->task_state_flags &=
- ~(SAS_TASK_STATE_PENDING | SAS_TASK_AT_INITIATOR);
- task->task_state_flags |= SAS_TASK_STATE_DONE;
- }
spin_unlock(&task->task_state_lock);
-
- if (aborted) {
+ if (unlikely(aborted)) {
+ struct completion *completion = slot->completion;
mvs_slot_task_free(mvi, task, slot, slot_idx);
mvs_slot_free(mvi, rx_desc);
+ if (completion)
+ complete(completion);
return -1;
}
@@ -1426,7 +1425,7 @@ static int mvs_slot_complete(struct mvs_info *mvi, u32 rx_desc, u32 flags)
out:
mvs_slot_task_free(mvi, task, slot, slot_idx);
- if (unlikely(tstat->stat != SAS_QUEUE_FULL))
+ if (tstat->stat != SAS_QUEUE_FULL)
mvs_slot_free(mvi, rx_desc);
spin_unlock(&mvi->lock);
@@ -1521,9 +1520,9 @@ static int mvs_int_rx(struct mvs_info *mvi, bool self_clear)
dev_printk(KERN_DEBUG, &pdev->dev, "RXQ_ERR %X\n",
rx_desc);
} else if (rx_desc & RXQ_SLOT_RESET) {
+ mvs_slot_free(mvi, rx_desc);
dev_printk(KERN_DEBUG, &pdev->dev, "Slot reset[%X]\n",
rx_desc);
- mvs_slot_free(mvi, rx_desc);
}
}
@@ -1533,23 +1532,6 @@ static int mvs_int_rx(struct mvs_info *mvi, bool self_clear)
return 0;
}
-#ifdef MVS_USE_TASKLET
-static void mvs_tasklet(unsigned long data)
-{
- struct mvs_info *mvi = (struct mvs_info *) data;
- unsigned long flags;
-
- spin_lock_irqsave(&mvi->lock, flags);
-
-#ifdef MVS_DISABLE_MSI
- mvs_int_full(mvi);
-#else
- mvs_int_rx(mvi, true);
-#endif
- spin_unlock_irqrestore(&mvi->lock, flags);
-}
-#endif
-
static irqreturn_t mvs_interrupt(int irq, void *opaque)
{
struct mvs_info *mvi = opaque;
@@ -1564,15 +1546,12 @@ static irqreturn_t mvs_interrupt(int irq, void *opaque)
/* clear CMD_CMPLT ASAP */
mw32_f(INT_STAT, CINT_DONE);
-#ifndef MVS_USE_TASKLET
spin_lock(&mvi->lock);
mvs_int_full(mvi);
spin_unlock(&mvi->lock);
-#else
- tasklet_schedule(&mvi->tasklet);
-#endif
+
return IRQ_HANDLED;
}
@@ -1581,15 +1560,12 @@ static irqreturn_t mvs_msi_interrupt(int irq, void *opaque)
{
struct mvs_info *mvi = opaque;
-#ifndef MVS_USE_TASKLET
spin_lock(&mvi->lock);
mvs_int_rx(mvi, true);
spin_unlock(&mvi->lock);
-#else
- tasklet_schedule(&mvi->tasklet);
-#endif
+
return IRQ_HANDLED;
}
#endif
@@ -2037,7 +2013,8 @@ static int mvs_task_prep_ssp(struct mvs_info *mvi,
return 0;
}
-static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags)
+static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags,
+ struct completion *completion)
{
struct domain_device *dev = task->dev;
struct mvs_info *mvi = dev->port->ha->lldd_ha;
@@ -2093,6 +2070,8 @@ static int mvs_task_exec(struct sas_task *task, const int num, gfp_t gfp_flags)
t->lldd_task = NULL;
slot->n_elem = n_elem;
memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
+ slot->completion = completion;
+
tei.task = t;
tei.hdr = &mvi->slot[tag];
tei.tag = tag;
@@ -2157,6 +2136,12 @@ out_done:
return rc;
}
+static int mvs_queue_command(struct sas_task *task, const int num,
+ gfp_t gfp_flags)
+{
+ return mvs_task_exec(task, num, gfp_flags, NULL);
+}
+
static int mvs_task_abort(struct sas_task *task)
{
int rc;
@@ -2164,6 +2149,7 @@ static int mvs_task_abort(struct sas_task *task)
struct mvs_info *mvi = task->dev->port->ha->lldd_ha;
struct pci_dev *pdev = mvi->pdev;
int tag;
+ DECLARE_COMPLETION_ONSTACK(completion);
spin_lock_irqsave(&task->task_state_lock, flags);
if (task->task_state_flags & SAS_TASK_STATE_DONE) {
@@ -2208,10 +2194,18 @@ static int mvs_task_abort(struct sas_task *task)
mvs_slot_task_free(mvi, task, &mvi->slot_info[tag], tag);
spin_unlock_irqrestore(&mvi->lock, flags);
}
- if (!mvs_task_exec(task, 1, GFP_ATOMIC))
+ mvs_task_exec(task, 1, GFP_ATOMIC, &completion);
+ wait_for_completion_timeout(&completion, 5 * HZ);
+ spin_lock_irqsave(&task->task_state_lock, flags);
+ if (task->task_state_flags & SAS_TASK_STATE_DONE) {
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
rc = TMF_RESP_FUNC_COMPLETE;
- else
- rc = TMF_RESP_FUNC_FAILED;
+ dev_printk(KERN_DEBUG, &pdev->dev, "%s: task 0x%p done\n",
+ __func__, task);
+ goto out_done;
+ }
+ spin_unlock_irqrestore(&task->task_state_lock, flags);
+ rc = TMF_RESP_FUNC_FAILED;
out_done:
return rc;
}
@@ -2348,9 +2342,7 @@ static struct mvs_info *__devinit mvs_alloc(struct pci_dev *pdev,
return NULL;
spin_lock_init(&mvi->lock);
-#ifdef MVS_USE_TASKLET
- tasklet_init(&mvi->tasklet, mvs_tasklet, (unsigned long)mvi);
-#endif
+
mvi->pdev = pdev;
mvi->chip = chip;
@@ -2382,8 +2374,8 @@ static struct mvs_info *__devinit mvs_alloc(struct pci_dev *pdev,
SHOST_TO_SAS_HA(mvi->shost) = &mvi->sas;
mvi->shost->transportt = mvs_stt;
- mvi->shost->max_id = 21;
- mvi->shost->max_lun = ~0;
+ mvi->shost->max_id = 128;
+ mvi->shost->max_lun = 1;
mvi->shost->max_channel = 0;
mvi->shost->max_cmd_len = 16;
@@ -2812,7 +2804,7 @@ static void mvs_update_phyinfo(struct mvs_info *mvi, int i,
} else {
dev_printk(KERN_DEBUG, &pdev->dev,
"No sig fis\n");
- phy->phy_type &= ~(PORT_TYPE_SATA);
+ phy->phy_type &= ~PORT_TYPE_SATA;
goto out_done;
}
}
@@ -2822,7 +2814,9 @@ static void mvs_update_phyinfo(struct mvs_info *mvi, int i,
dev_printk(KERN_DEBUG, &pdev->dev,
"phy[%d] Get Attached Address 0x%llX ,"
" SAS Address 0x%llX\n",
- i, phy->att_dev_sas_addr, phy->dev_sas_addr);
+ i,
+ (unsigned long long)phy->att_dev_sas_addr,
+ (unsigned long long)phy->dev_sas_addr);
dev_printk(KERN_DEBUG, &pdev->dev,
"Rate = %x , type = %d\n",
sas_phy->linkrate, phy->phy_type);
@@ -2918,7 +2912,7 @@ static int __devinit mvs_hw_init(struct mvs_info *mvi)
else
mw32_f(CTL, cctl | CCTL_RST);
- /* write to device control _AND_ device status register? - A.C. */
+ /* write to device control _AND_ device status register */
pci_read_config_dword(mvi->pdev, PCR_DEV_CTRL, &tmp);
tmp &= ~PRD_REQ_MASK;
tmp |= PRD_REQ_SIZE;
@@ -2998,8 +2992,7 @@ static int __devinit mvs_hw_init(struct mvs_info *mvi)
/* FIXME: update wide port bitmaps */
/* little endian for open address and command table, etc. */
- /* A.C.
- * it seems that ( from the spec ) turning on big-endian won't
+ /* it seems that ( from the spec ) turning on big-endian won't
* do us any good on big-endian machines, need further confirmation
*/
cctl = mr32(CTL);
@@ -3153,7 +3146,7 @@ static void __devexit mvs_pci_remove(struct pci_dev *pdev)
}
static struct sas_domain_function_template mvs_transport_ops = {
- .lldd_execute_task = mvs_task_exec,
+ .lldd_execute_task = mvs_queue_command,
.lldd_control_phy = mvs_phy_control,
.lldd_abort_task = mvs_task_abort,
.lldd_port_formed = mvs_port_formed,
--
1.5.4
next reply other threads:[~2008-04-08 10:31 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-04-08 10:31 Ke Wei [this message]
2008-04-25 15:51 ` [PATCH scsi-rc-fixes-2.6] mvsas: fix error handling Jeff Garzik
2008-04-25 16:07 ` James Bottomley
2008-04-28 16:05 ` Ke Wei
2008-05-07 10:34 ` Ke Wei
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=47FB498A.2010107@marvell.com \
--to=kewei@marvell.com \
--cc=James.Bottomley@HansenPartnership.com \
--cc=jeff@garzik.org \
--cc=linux-scsi@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.