Skip to content

Commit

Permalink
[SCSI] qla2xxx: Properly acknowledge IDC notification messages.
Browse files Browse the repository at this point in the history
To ensure smooth operations amongst the FCoE and NIC side
components of the ISP81xx chip, the FCoE driver (qla2xxx) must
ensure the 10gb NIC driver (qlge) does not timeout waiting for
IDC (Inter-Driver Communication) acknowledgments.  The
acknowledgment requirements are trivial -- a simple mirroring of
incoming mailbox registers during the AEN to a process-context
capable mailbox command.

Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
  • Loading branch information
Andrew Vasquez authored and James Bottomley committed Feb 10, 2009
1 parent 618a752 commit 8a65957
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 13 deletions.
5 changes: 5 additions & 0 deletions drivers/scsi/qla2xxx/qla_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -2135,6 +2135,7 @@ struct qla_msix_entry {
/* Work events. */
enum qla_work_type {
QLA_EVT_AEN,
QLA_EVT_IDC_ACK,
};


Expand All @@ -2149,6 +2150,10 @@ struct qla_work_evt {
enum fc_host_event_code code;
u32 data;
} aen;
struct {
#define QLA_IDC_ACK_REGS 7
uint16_t mb[QLA_IDC_ACK_REGS];
} idc_ack;
} u;
};

Expand Down
2 changes: 2 additions & 0 deletions drivers/scsi/qla2xxx/qla_fw.h
Original file line number Diff line number Diff line change
Expand Up @@ -1402,6 +1402,8 @@ struct access_chip_rsp_84xx {
#define MBA_IDC_NOTIFY 0x8101
#define MBA_IDC_TIME_EXT 0x8102

#define MBC_IDC_ACK 0x101

struct nvram_81xx {
/* NVRAM header. */
uint8_t id[4];
Expand Down
3 changes: 3 additions & 0 deletions drivers/scsi/qla2xxx/qla_gbl.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ extern int qla2x00_loop_reset(scsi_qla_host_t *);
extern void qla2x00_abort_all_cmds(scsi_qla_host_t *, int);
extern int qla2x00_post_aen_work(struct scsi_qla_host *, enum
fc_host_event_code, u32);
extern int qla2x00_post_idc_ack_work(struct scsi_qla_host *, uint16_t *);

extern void qla2x00_abort_fcport_cmds(fc_port_t *);
extern struct scsi_qla_host *qla2x00_create_host(struct scsi_host_template *,
Expand Down Expand Up @@ -266,6 +267,8 @@ qla2x00_set_idma_speed(scsi_qla_host_t *, uint16_t, uint16_t, uint16_t *);

extern int qla84xx_verify_chip(struct scsi_qla_host *, uint16_t *);

extern int qla81xx_idc_ack(scsi_qla_host_t *, uint16_t *);

/*
* Global Function Prototypes in qla_isr.c source file.
*/
Expand Down
48 changes: 35 additions & 13 deletions drivers/scsi/qla2xxx/qla_isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,40 @@ qla2x00_mbx_completion(scsi_qla_host_t *vha, uint16_t mb0)
}
}

static void
qla81xx_idc_event(scsi_qla_host_t *vha, uint16_t aen, uint16_t descr)
{
static char *event[] =
{ "Complete", "Request Notification", "Time Extension" };
int rval;
struct device_reg_24xx __iomem *reg24 = &vha->hw->iobase->isp24;
uint16_t __iomem *wptr;
uint16_t cnt, timeout, mb[QLA_IDC_ACK_REGS];

/* Seed data -- mailbox1 -> mailbox7. */
wptr = (uint16_t __iomem *)&reg24->mailbox1;
for (cnt = 0; cnt < QLA_IDC_ACK_REGS; cnt++, wptr++)
mb[cnt] = RD_REG_WORD(wptr);

DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
"%04x %04x %04x %04x %04x %04x %04x.\n", vha->host_no,
event[aen & 0xff],
mb[0], mb[1], mb[2], mb[3], mb[4], mb[5], mb[6]));

/* Acknowledgement needed? [Notify && non-zero timeout]. */
timeout = (descr >> 8) & 0xf;
if (aen != MBA_IDC_NOTIFY || !timeout)
return;

DEBUG2(printk("scsi(%ld): Inter-Driver Commucation %s -- "
"ACK timeout=%d.\n", vha->host_no, event[aen & 0xff], timeout));

rval = qla2x00_post_idc_ack_work(vha, mb);
if (rval != QLA_SUCCESS)
qla_printk(KERN_WARNING, vha->hw,
"IDC failed to post ACK.\n");
}

/**
* qla2x00_async_event() - Process aynchronous events.
* @ha: SCSI driver HA context
Expand Down Expand Up @@ -714,21 +748,9 @@ qla2x00_async_event(scsi_qla_host_t *vha, struct rsp_que *rsp, uint16_t *mb)
"%04x %04x %04x\n", vha->host_no, mb[1], mb[2], mb[3]));
break;
case MBA_IDC_COMPLETE:
DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
"Complete -- %04x %04x %04x\n", vha->host_no, mb[1], mb[2],
mb[3]));
break;
case MBA_IDC_NOTIFY:
DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
"Request Notification -- %04x %04x %04x\n", vha->host_no,
mb[1], mb[2], mb[3]));
/**** Mailbox registers 4 - 7 valid!!! */
break;
case MBA_IDC_TIME_EXT:
DEBUG2(printk("scsi(%ld): Inter-Driver Commucation "
"Time Extension -- %04x %04x %04x\n", vha->host_no, mb[1],
mb[2], mb[3]));
/**** Mailbox registers 4 - 7 valid!!! */
qla81xx_idc_event(vha, mb[0], mb[1]);
break;
}

Expand Down
26 changes: 26 additions & 0 deletions drivers/scsi/qla2xxx/qla_mbx.c
Original file line number Diff line number Diff line change
Expand Up @@ -3191,3 +3191,29 @@ qla25xx_init_rsp_que(struct scsi_qla_host *vha, struct rsp_que *rsp)
return rval;
}

int
qla81xx_idc_ack(scsi_qla_host_t *vha, uint16_t *mb)
{
int rval;
mbx_cmd_t mc;
mbx_cmd_t *mcp = &mc;

DEBUG11(printk("%s(%ld): entered.\n", __func__, vha->host_no));

mcp->mb[0] = MBC_IDC_ACK;
memcpy(&mcp->mb[1], mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
mcp->out_mb = MBX_7|MBX_6|MBX_5|MBX_4|MBX_3|MBX_2|MBX_1|MBX_0;
mcp->in_mb = MBX_0;
mcp->tov = MBX_TOV_SECONDS;
mcp->flags = 0;
rval = qla2x00_mailbox_command(vha, mcp);

if (rval != QLA_SUCCESS) {
DEBUG2_3_11(printk("%s(%ld): failed=%x (%x).\n", __func__,
vha->host_no, rval, mcp->mb[0]));
} else {
DEBUG11(printk("%s(%ld): done.\n", __func__, vha->host_no));
}

return rval;
}
16 changes: 16 additions & 0 deletions drivers/scsi/qla2xxx/qla_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -2522,6 +2522,19 @@ qla2x00_post_aen_work(struct scsi_qla_host *vha, enum fc_host_event_code code,
return qla2x00_post_work(vha, e, 1);
}

int
qla2x00_post_idc_ack_work(struct scsi_qla_host *vha, uint16_t *mb)
{
struct qla_work_evt *e;

e = qla2x00_alloc_work(vha, QLA_EVT_IDC_ACK, 1);
if (!e)
return QLA_FUNCTION_FAILED;

memcpy(e->u.idc_ack.mb, mb, QLA_IDC_ACK_REGS * sizeof(uint16_t));
return qla2x00_post_work(vha, e, 1);
}

static void
qla2x00_do_work(struct scsi_qla_host *vha)
{
Expand All @@ -2539,6 +2552,9 @@ qla2x00_do_work(struct scsi_qla_host *vha)
fc_host_post_event(vha->host, fc_get_event_number(),
e->u.aen.code, e->u.aen.data);
break;
case QLA_EVT_IDC_ACK:
qla81xx_idc_ack(vha, e->u.idc_ack.mb);
break;
}
if (e->flags & QLA_EVT_FLAG_FREE)
kfree(e);
Expand Down

0 comments on commit 8a65957

Please sign in to comment.