Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 47386
b: refs/heads/master
c: 5bd28a4
h: refs/heads/master
v: v3
  • Loading branch information
Robert Hancock authored and Jeff Garzik committed Feb 9, 2007
1 parent 3815fd8 commit 137bf85
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 76 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 92ae78493f5f3de323652f3ea0ec8b7b2839c3d2
refs/heads/master: 5bd28a4b6efa73c5d033f3b86201c2c366b170cf
147 changes: 72 additions & 75 deletions trunk/drivers/ata/sata_nv.c
Original file line number Diff line number Diff line change
Expand Up @@ -651,53 +651,62 @@ static unsigned int nv_adma_tf_to_cpb(struct ata_taskfile *tf, __le16 *cpb)
return idx;
}

static void nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
static int nv_adma_check_cpb(struct ata_port *ap, int cpb_num, int force_err)
{
struct nv_adma_port_priv *pp = ap->private_data;
int complete = 0, have_err = 0;
u8 flags = pp->cpb[cpb_num].resp_flags;

VPRINTK("CPB %d, flags=0x%x\n", cpb_num, flags);

if (flags & NV_CPB_RESP_DONE) {
VPRINTK("CPB flags done, flags=0x%x\n", flags);
complete = 1;
}
if (flags & NV_CPB_RESP_ATA_ERR) {
ata_port_printk(ap, KERN_ERR, "CPB flags ATA err, flags=0x%x\n", flags);
have_err = 1;
complete = 1;
}
if (flags & NV_CPB_RESP_CMD_ERR) {
ata_port_printk(ap, KERN_ERR, "CPB flags CMD err, flags=0x%x\n", flags);
have_err = 1;
complete = 1;
}
if (flags & NV_CPB_RESP_CPB_ERR) {
ata_port_printk(ap, KERN_ERR, "CPB flags CPB err, flags=0x%x\n", flags);
have_err = 1;
complete = 1;
if (unlikely((force_err ||
flags & (NV_CPB_RESP_ATA_ERR |
NV_CPB_RESP_CMD_ERR |
NV_CPB_RESP_CPB_ERR)))) {
struct ata_eh_info *ehi = &ap->eh_info;
int freeze = 0;

ata_ehi_clear_desc(ehi);
ata_ehi_push_desc(ehi, "CPB resp_flags 0x%x", flags );
if (flags & NV_CPB_RESP_ATA_ERR) {
ata_ehi_push_desc(ehi, ": ATA error");
ehi->err_mask |= AC_ERR_DEV;
} else if (flags & NV_CPB_RESP_CMD_ERR) {
ata_ehi_push_desc(ehi, ": CMD error");
ehi->err_mask |= AC_ERR_DEV;
} else if (flags & NV_CPB_RESP_CPB_ERR) {
ata_ehi_push_desc(ehi, ": CPB error");
ehi->err_mask |= AC_ERR_SYSTEM;
freeze = 1;
} else {
/* notifier error, but no error in CPB flags? */
ehi->err_mask |= AC_ERR_OTHER;
freeze = 1;
}
/* Kill all commands. EH will determine what actually failed. */
if (freeze)
ata_port_freeze(ap);
else
ata_port_abort(ap);
return 1;
}
if(complete || force_err)
{

if (flags & NV_CPB_RESP_DONE) {
struct ata_queued_cmd *qc = ata_qc_from_tag(ap, cpb_num);
if(likely(qc)) {
u8 ata_status = 0;
/* Only use the ATA port status for non-NCQ commands.
VPRINTK("CPB flags done, flags=0x%x\n", flags);
if (likely(qc)) {
/* Grab the ATA port status for non-NCQ commands.
For NCQ commands the current status may have nothing to do with
the command just completed. */
if(qc->tf.protocol != ATA_PROT_NCQ)
ata_status = readb(pp->ctl_block + (ATA_REG_STATUS * 4));

if(have_err || force_err)
ata_status |= ATA_ERR;

qc->err_mask |= ac_err_mask(ata_status);
if (qc->tf.protocol != ATA_PROT_NCQ) {
u8 ata_status = readb(pp->ctl_block + (ATA_REG_STATUS * 4));
qc->err_mask |= ac_err_mask(ata_status);
}
DPRINTK("Completing qc from tag %d with err_mask %u\n",cpb_num,
qc->err_mask);
ata_qc_complete(qc);
}
}
return 0;
}

static int nv_host_intr(struct ata_port *ap, u8 irq_stat)
Expand Down Expand Up @@ -741,7 +750,6 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
void __iomem *mmio = pp->ctl_block;
u16 status;
u32 gen_ctl;
int have_global_err = 0;
u32 notifier, notifier_error;

/* if in ATA register mode, use standard ata interrupt handler */
Expand Down Expand Up @@ -777,42 +785,50 @@ static irqreturn_t nv_adma_interrupt(int irq, void *dev_instance)
readw(mmio + NV_ADMA_STAT); /* flush posted write */
rmb();

/* freeze if hotplugged */
if (unlikely(status & (NV_ADMA_STAT_HOTPLUG | NV_ADMA_STAT_HOTUNPLUG))) {
ata_port_printk(ap, KERN_NOTICE, "Hotplug event, freezing\n");
handled++; /* irq handled if we got here */

/* freeze if hotplugged or controller error */
if (unlikely(status & (NV_ADMA_STAT_HOTPLUG |
NV_ADMA_STAT_HOTUNPLUG |
NV_ADMA_STAT_TIMEOUT))) {
struct ata_eh_info *ehi = &ap->eh_info;

ata_ehi_clear_desc(ehi);
ata_ehi_push_desc(ehi, "ADMA status 0x%08x", status );
if (status & NV_ADMA_STAT_TIMEOUT) {
ehi->err_mask |= AC_ERR_SYSTEM;
ata_ehi_push_desc(ehi, ": timeout");
} else if (status & NV_ADMA_STAT_HOTPLUG) {
ata_ehi_hotplugged(ehi);
ata_ehi_push_desc(ehi, ": hotplug");
} else if (status & NV_ADMA_STAT_HOTUNPLUG) {
ata_ehi_hotplugged(ehi);
ata_ehi_push_desc(ehi, ": hot unplug");
}
ata_port_freeze(ap);
handled++;
continue;
}

if (status & NV_ADMA_STAT_TIMEOUT) {
ata_port_printk(ap, KERN_ERR, "timeout, stat=0x%x\n", status);
have_global_err = 1;
}
if (status & NV_ADMA_STAT_CPBERR) {
ata_port_printk(ap, KERN_ERR, "CPB error, stat=0x%x\n", status);
have_global_err = 1;
}
if ((status & NV_ADMA_STAT_DONE) || have_global_err) {
if (status & (NV_ADMA_STAT_DONE |
NV_ADMA_STAT_CPBERR)) {
/** Check CPBs for completed commands */

if(ata_tag_valid(ap->active_tag))
if (ata_tag_valid(ap->active_tag)) {
/* Non-NCQ command */
nv_adma_check_cpb(ap, ap->active_tag, have_global_err ||
(notifier_error & (1 << ap->active_tag)));
else {
int pos;
nv_adma_check_cpb(ap, ap->active_tag,
notifier_error & (1 << ap->active_tag));
} else {
int pos, error = 0;
u32 active = ap->sactive;
while( (pos = ffs(active)) ) {

while ((pos = ffs(active)) && !error) {
pos--;
nv_adma_check_cpb(ap, pos, have_global_err ||
(notifier_error & (1 << pos)) );
error = nv_adma_check_cpb(ap, pos,
notifier_error & (1 << pos) );
active &= ~(1 << pos );
}
}
}

handled++; /* irq handled if we got here */
}
}

Expand Down Expand Up @@ -1372,28 +1388,9 @@ static void nv_adma_error_handler(struct ata_port *ap)
int i;
u16 tmp;

u32 notifier = readl(mmio + NV_ADMA_NOTIFIER);
u32 notifier_error = readl(mmio + NV_ADMA_NOTIFIER_ERROR);
u32 gen_ctl = readl(pp->gen_block + NV_ADMA_GEN_CTL);
u32 status = readw(mmio + NV_ADMA_STAT);

ata_port_printk(ap, KERN_ERR, "EH in ADMA mode, notifier 0x%X "
"notifier_error 0x%X gen_ctl 0x%X status 0x%X\n",
notifier, notifier_error, gen_ctl, status);

for( i=0;i<NV_ADMA_MAX_CPBS;i++) {
struct nv_adma_cpb *cpb = &pp->cpb[i];
if( cpb->ctl_flags || cpb->resp_flags )
ata_port_printk(ap, KERN_ERR,
"CPB %d: ctl_flags 0x%x, resp_flags 0x%x\n",
i, cpb->ctl_flags, cpb->resp_flags);
}

/* Push us back into port register mode for error handling. */
nv_adma_register_mode(ap);

ata_port_printk(ap, KERN_ERR, "Resetting port\n");

/* Mark all of the CPBs as invalid to prevent them from being executed */
for( i=0;i<NV_ADMA_MAX_CPBS;i++)
pp->cpb[i].ctl_flags &= ~NV_CPB_CTL_CPB_VALID;
Expand Down

0 comments on commit 137bf85

Please sign in to comment.