Add sysctls in ahd(4) in order to keep track of different classes of

errors. So far 3 different classes are present (correctable,
uncorrectable and fatal) but more can be added easilly.

Obtained from:	Sandvine Incorporated
Reviewed by:	emase, gibbs
Sponsored by:	Sandvine Incorporated
MFC:		2 weeks
This commit is contained in:
attilio 2009-11-13 22:57:20 +00:00
parent 5fe8543b99
commit 0e3418f9cf
5 changed files with 197 additions and 2 deletions

View File

@ -134,6 +134,7 @@ ahd_pci_attach(device_t dev)
return (error);
}
ahd_sysctl(ahd);
ahd_attach(ahd);
return (0);
}
@ -198,6 +199,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
bus_release_resource(ahd->dev_softc, regs_type,
regs_id, regs);
regs = NULL;
AHD_CORRECTABLE_ERROR(ahd);
} else {
command &= ~PCIM_CMD_PORTEN;
aic_pci_write_config(ahd->dev_softc,
@ -214,6 +216,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
if (regs == NULL) {
device_printf(ahd->dev_softc,
"can't allocate register resources\n");
AHD_UNCORRECTABLE_ERROR(ahd);
return (ENOMEM);
}
ahd->tags[0] = rman_get_bustag(regs);
@ -226,6 +229,7 @@ ahd_pci_map_registers(struct ahd_softc *ahd)
if (regs2 == NULL) {
device_printf(ahd->dev_softc,
"can't allocate register resources\n");
AHD_UNCORRECTABLE_ERROR(ahd);
return (ENOMEM);
}
ahd->tags[1] = rman_get_bustag(regs2);

View File

@ -401,6 +401,7 @@ ahd_flush_qoutfifo(struct ahd_softc *ahd)
if (scb == NULL) {
printf("%s: Warning - GSFIFO SCB %d invalid\n",
ahd_name(ahd), scbid);
AHD_CORRECTABLE_ERROR(ahd);
continue;
}
/*
@ -525,6 +526,7 @@ rescan_fifos:
if (scb == NULL) {
printf("%s: Warning - DMA-up and complete "
"SCB %d invalid\n", ahd_name(ahd), scbid);
AHD_CORRECTABLE_ERROR(ahd);
continue;
}
hscb_ptr = (uint8_t *)scb->hscb;
@ -546,6 +548,7 @@ rescan_fifos:
if (scb == NULL) {
printf("%s: Warning - Complete Qfrz SCB %d invalid\n",
ahd_name(ahd), scbid);
AHD_CORRECTABLE_ERROR(ahd);
continue;
}
@ -563,6 +566,7 @@ rescan_fifos:
if (scb == NULL) {
printf("%s: Warning - Complete SCB %d invalid\n",
ahd_name(ahd), scbid);
AHD_CORRECTABLE_ERROR(ahd);
continue;
}
@ -870,6 +874,7 @@ ahd_run_qoutfifo(struct ahd_softc *ahd)
"(cmdcmplt)\nQOUTPOS = %d\n",
ahd_name(ahd), scb_index,
ahd->qoutfifonext);
AHD_CORRECTABLE_ERROR(ahd);
ahd_dump_card_state(ahd);
} else if ((completion->sg_status & SG_STATUS_VALID) != 0) {
ahd_handle_scb_status(ahd, scb);
@ -897,9 +902,11 @@ ahd_handle_hwerrint(struct ahd_softc *ahd)
error = ahd_inb(ahd, ERROR);
for (i = 0; i < num_errors; i++) {
if ((error & ahd_hard_errors[i].errno) != 0)
if ((error & ahd_hard_errors[i].errno) != 0) {
printf("%s: hwerrint, %s\n",
ahd_name(ahd), ahd_hard_errors[i].errmesg);
AHD_UNCORRECTABLE_ERROR(ahd);
}
}
ahd_dump_card_state(ahd);
@ -990,6 +997,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_name(ahd));
ahd_dump_card_state(ahd);
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
AHD_UNCORRECTABLE_ERROR(ahd);
break;
case STATUS_OVERRUN:
{
@ -1005,6 +1013,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
printf("SCB %d Packetized Status Overrun", scbid);
ahd_dump_card_state(ahd);
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
AHD_UNCORRECTABLE_ERROR(ahd);
break;
}
case CFG4ISTAT_INTR:
@ -1017,6 +1026,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
if (scb == NULL) {
ahd_dump_card_state(ahd);
printf("CFG4ISTAT: Free SCB %d referenced", scbid);
AHD_FATAL_ERROR(ahd);
panic("For safety");
}
ahd_outq(ahd, HADDR, scb->sense_busaddr);
@ -1044,6 +1054,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
case P_MESGIN:
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
printf("%s: Issued Bus Reset.\n", ahd_name(ahd));
AHD_UNCORRECTABLE_ERROR(ahd);
break;
case P_COMMAND:
{
@ -1068,6 +1079,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
scbid = ahd_get_scbptr(ahd);
scb = ahd_lookup_scb(ahd, scbid);
if (scb == NULL) {
AHD_CORRECTABLE_ERROR(ahd);
printf("Invalid phase with no valid SCB. "
"Resetting bus.\n");
ahd_reset_channel(ahd, 'A',
@ -1127,6 +1139,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
#ifdef AHD_DEBUG
if ((ahd_debug & AHD_SHOW_RECOVERY) != 0) {
ahd_print_path(ahd, scb);
AHD_CORRECTABLE_ERROR(ahd);
printf("Unexpected command phase from "
"packetized target\n");
}
@ -1214,6 +1227,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
&& bus_phase != P_MESGOUT) {
printf("ahd_intr: HOST_MSG_LOOP bad "
"phase 0x%x\n", bus_phase);
AHD_CORRECTABLE_ERROR(ahd);
/*
* Probably transitioned to bus free before
* we got here. Just punt the message.
@ -1316,6 +1330,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_name(ahd), 'A',
SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),
lastphase, ahd_inb(ahd, SCSISIGI));
AHD_CORRECTABLE_ERROR(ahd);
break;
}
case MISSED_BUSFREE:
@ -1328,6 +1343,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
ahd_name(ahd), 'A',
SCSIID_TARGET(ahd, ahd_inb(ahd, SAVED_SCSIID)),
lastphase, ahd_inb(ahd, SCSISIGI));
AHD_CORRECTABLE_ERROR(ahd);
ahd_restart(ahd);
return;
}
@ -1387,6 +1403,7 @@ ahd_handle_seqint(struct ahd_softc *ahd, u_int intstat)
devinfo.lun);
scbid = ahd_get_scbptr(ahd);
scb = ahd_lookup_scb(ahd, scbid);
AHD_CORRECTABLE_ERROR(ahd);
if (scb != NULL
&& (scb->flags & SCB_RECOVERY_SCB) != 0)
/*
@ -1570,11 +1587,13 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
printf("%s: SCSI offset overrun detected. Resetting bus.\n",
ahd_name(ahd));
AHD_CORRECTABLE_ERROR(ahd);
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
} else if ((status & SCSIRSTI) != 0) {
printf("%s: Someone reset channel A\n", ahd_name(ahd));
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/FALSE);
AHD_UNCORRECTABLE_ERROR(ahd);
} else if ((status & SCSIPERR) != 0) {
/* Make sure the sequencer is in a safe location. */
@ -1619,6 +1638,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
"valid during SELTO scb(0x%x)\n",
ahd_name(ahd), scbid);
ahd_dump_card_state(ahd);
AHD_UNCORRECTABLE_ERROR(ahd);
} else {
struct ahd_devinfo devinfo;
#ifdef AHD_DEBUG
@ -1654,6 +1674,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
} else if (status3 != 0) {
printf("%s: SCSI Cell parity error SSTAT3 == 0x%x\n",
ahd_name(ahd), status3);
AHD_CORRECTABLE_ERROR(ahd);
ahd_outb(ahd, CLRSINT3, status3);
} else if ((lqistat1 & (LQIPHASE_LQ|LQIPHASE_NLQ)) != 0) {
@ -1712,6 +1733,7 @@ ahd_handle_scsiint(struct ahd_softc *ahd, u_int intstat)
"during unexpected busfree\n",
ahd_name(ahd), scbid, mode);
packetized = 0;
AHD_CORRECTABLE_ERROR(ahd);
} else
packetized = (scb->flags & SCB_PACKETIZED) != 0;
clear_fifo = 1;
@ -1856,6 +1878,7 @@ ahd_handle_transmission_error(struct ahd_softc *ahd)
ahd_scsisigi_print(curphase, &cur_col, 50);
ahd_perrdiag_print(perrdiag, &cur_col, 50);
printf("\n");
AHD_CORRECTABLE_ERROR(ahd);
ahd_dump_card_state(ahd);
}
@ -1864,6 +1887,7 @@ ahd_handle_transmission_error(struct ahd_softc *ahd)
printf("%s: Gross protocol error during incoming "
"packet. lqistat1 == 0x%x. Resetting bus.\n",
ahd_name(ahd), lqistat1);
AHD_UNCORRECTABLE_ERROR(ahd);
}
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
return;
@ -1891,6 +1915,7 @@ ahd_handle_transmission_error(struct ahd_softc *ahd)
*/
ahd_outb(ahd, LQCTL2, LQIRETRY);
printf("LQIRetry for LQICRCI_LQ to release ACK\n");
AHD_CORRECTABLE_ERROR(ahd);
} else if ((lqistat1 & LQICRCI_NLQ) != 0) {
/*
* We detected a CRC error in a NON-LQ packet.
@ -1942,6 +1967,7 @@ ahd_handle_transmission_error(struct ahd_softc *ahd)
if (scb == NULL) {
printf("%s: No SCB valid for LQICRC_NLQ. "
"Resetting bus\n", ahd_name(ahd));
AHD_UNCORRECTABLE_ERROR(ahd);
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
return;
}
@ -1999,9 +2025,11 @@ ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1)
&& (ahd_inb(ahd, MDFFSTAT) & DLZERO) != 0) {
if ((lqistat1 & LQIPHASE_LQ) != 0) {
printf("LQIRETRY for LQIPHASE_LQ\n");
AHD_CORRECTABLE_ERROR(ahd);
ahd_outb(ahd, LQCTL2, LQIRETRY);
} else if ((lqistat1 & LQIPHASE_NLQ) != 0) {
printf("LQIRETRY for LQIPHASE_NLQ\n");
AHD_CORRECTABLE_ERROR(ahd);
ahd_outb(ahd, LQCTL2, LQIRETRY);
} else
panic("ahd_handle_lqiphase_error: No phase errors\n");
@ -2010,6 +2038,7 @@ ahd_handle_lqiphase_error(struct ahd_softc *ahd, u_int lqistat1)
ahd_unpause(ahd);
} else {
printf("Reseting Channel for LQI Phase error\n");
AHD_CORRECTABLE_ERROR(ahd);
ahd_dump_card_state(ahd);
ahd_reset_channel(ahd, 'A', /*Initiate Reset*/TRUE);
}
@ -2099,6 +2128,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
ahd_print_path(ahd, scb);
printf("Probable outgoing LQ CRC error. "
"Retrying command\n");
AHD_CORRECTABLE_ERROR(ahd);
}
scb->crc_retry_count++;
} else {
@ -2134,6 +2164,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
scb = ahd_lookup_scb(ahd, scbid);
ahd_print_path(ahd, scb);
printf("Unexpected PKT busfree condition\n");
AHD_UNCORRECTABLE_ERROR(ahd);
ahd_dump_card_state(ahd);
ahd_abort_scbs(ahd, SCB_GET_TARGET(ahd, scb), 'A',
SCB_GET_LUN(scb), SCB_GET_TAG(scb),
@ -2143,6 +2174,7 @@ ahd_handle_pkt_busfree(struct ahd_softc *ahd, u_int busfreetime)
return (1);
}
printf("%s: Unexpected PKT busfree condition\n", ahd_name(ahd));
AHD_UNCORRECTABLE_ERROR(ahd);
ahd_dump_card_state(ahd);
/* Restart the sequencer. */
return (1);
@ -2421,6 +2453,7 @@ ahd_handle_nonpkt_busfree(struct ahd_softc *ahd)
ahd_lookup_phase_entry(lastphase)->phasemsg,
aborted,
ahd_inw(ahd, PRGMCNT));
AHD_UNCORRECTABLE_ERROR(ahd);
ahd_dump_card_state(ahd);
if (lastphase != P_BUSFREE)
ahd_force_renegotiation(ahd, &devinfo);
@ -2456,6 +2489,7 @@ ahd_handle_proto_violation(struct ahd_softc *ahd)
ahd_print_devinfo(ahd, &devinfo);
printf("Target did not send an IDENTIFY message. "
"LASTPHASE = 0x%x.\n", lastphase);
AHD_UNCORRECTABLE_ERROR(ahd);
scb = NULL;
} else if (scb == NULL) {
/*
@ -2464,12 +2498,14 @@ ahd_handle_proto_violation(struct ahd_softc *ahd)
*/
ahd_print_devinfo(ahd, &devinfo);
printf("No SCB found during protocol violation\n");
AHD_UNCORRECTABLE_ERROR(ahd);
goto proto_violation_reset;
} else {
aic_set_transaction_status(scb, CAM_SEQUENCE_FAIL);
if ((seq_flags & NO_CDB_SENT) != 0) {
ahd_print_path(ahd, scb);
printf("No or incomplete CDB sent to device.\n");
AHD_UNCORRECTABLE_ERROR(ahd);
} else if ((ahd_inb_scbram(ahd, SCB_CONTROL)
& STATUS_RCVD) == 0) {
/*
@ -2484,6 +2520,7 @@ ahd_handle_proto_violation(struct ahd_softc *ahd)
} else {
ahd_print_path(ahd, scb);
printf("Unknown protocol violation.\n");
AHD_UNCORRECTABLE_ERROR(ahd);
ahd_dump_card_state(ahd);
}
}
@ -2499,6 +2536,7 @@ proto_violation_reset:
found = ahd_reset_channel(ahd, 'A', TRUE);
printf("%s: Issued Channel %c Bus Reset. "
"%d SCBs aborted\n", ahd_name(ahd), 'A', found);
AHD_UNCORRECTABLE_ERROR(ahd);
} else {
/*
* Leave the selection hardware off in case
@ -2521,6 +2559,7 @@ proto_violation_reset:
}
printf("Protocol violation %s. Attempting to abort.\n",
ahd_lookup_phase_entry(curphase)->phasemsg);
AHD_UNCORRECTABLE_ERROR(ahd);
}
}
@ -2602,6 +2641,7 @@ ahd_clear_critical_section(struct ahd_softc *ahd)
"%s: First Instruction 0x%x now 0x%x\n",
ahd_name(ahd), ahd_name(ahd), first_instr,
seqaddr);
AHD_FATAL_ERROR(ahd);
ahd_dump_card_state(ahd);
panic("critical section loop");
}
@ -3566,6 +3606,7 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
} else if (scb == NULL) {
printf("%s: WARNING. No pending message for "
"I_T msgin. Issuing NO-OP\n", ahd_name(ahd));
AHD_CORRECTABLE_ERROR(ahd);
ahd->msgout_buf[ahd->msgout_index++] = MSG_NOOP;
ahd->msgout_len++;
ahd->msg_type = MSG_TYPE_INITIATOR_MSGOUT;
@ -3596,6 +3637,7 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
ahd->msgout_len++;
ahd_print_path(ahd, scb);
printf("Bus Device Reset Message Sent\n");
AHD_CORRECTABLE_ERROR(ahd);
/*
* Clear our selection hardware in advance of
* the busfree. We may have an entry in the waiting
@ -3615,6 +3657,7 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
ahd_print_path(ahd, scb);
printf("Abort%s Message Sent\n",
(scb->hscb->control & TAG_ENB) != 0 ? " Tag" : "");
AHD_CORRECTABLE_ERROR(ahd);
/*
* Clear our selection hardware in advance of
* the busfree. We may have an entry in the waiting
@ -3638,6 +3681,7 @@ ahd_setup_initiator_msgout(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
"does not have a waiting message\n");
printf("SCSIID = %x, target_mask = %x\n", scb->hscb->scsiid,
devinfo->target_mask);
AHD_FATAL_ERROR(ahd);
panic("SCB = %d, SCB Control = %x:%x, MSG_OUT = %x "
"SCB flags = %x", SCB_GET_TAG(scb), scb->hscb->control,
ahd_inb_scbram(ahd, SCB_CONTROL), ahd_inb(ahd, MSG_OUT),
@ -5129,9 +5173,11 @@ ahd_handle_devreset(struct ahd_softc *ahd, struct ahd_devinfo *devinfo,
lun, AC_SENT_BDR, NULL);
if (message != NULL
&& (verbose_level <= bootverbose))
&& (verbose_level <= bootverbose)) {
AHD_CORRECTABLE_ERROR(ahd);
printf("%s: %s on %c:%d. %d SCBs aborted\n", ahd_name(ahd),
message, devinfo->channel, devinfo->target, found);
}
}
#ifdef AHD_TARGET_MODE
@ -5509,6 +5555,7 @@ ahd_reset(struct ahd_softc *ahd, int reinit)
if (wait == 0) {
printf("%s: WARNING - Failed chip reset! "
"Trying to initialize anyway.\n", ahd_name(ahd));
AHD_FATAL_ERROR(ahd);
}
ahd_outb(ahd, HCNTRL, ahd->pause);
@ -5630,6 +5677,7 @@ ahd_init_scbdata(struct ahd_softc *ahd)
scb_data->maxhscbs = ahd_probe_scbs(ahd);
if (scb_data->maxhscbs == 0) {
printf("%s: No SCB space found\n", ahd_name(ahd));
AHD_FATAL_ERROR(ahd);
return (ENXIO);
}
@ -6474,6 +6522,7 @@ ahd_init(struct ahd_softc *ahd)
printf("%s: WARNING. Termination is not configured correctly.\n"
"%s: WARNING. SCSI bus operations may FAIL.\n",
ahd_name(ahd), ahd_name(ahd));
AHD_CORRECTABLE_ERROR(ahd);
}
init_done:
ahd_restart(ahd);
@ -6830,6 +6879,7 @@ ahd_default_config(struct ahd_softc *ahd)
if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {
printf("%s: unable to allocate ahd_tmode_tstate. "
"Failing attach\n", ahd_name(ahd));
AHD_FATAL_ERROR(ahd);
return (ENOMEM);
}
@ -6909,6 +6959,7 @@ ahd_parse_cfgdata(struct ahd_softc *ahd, struct seeprom_config *sc)
if (ahd_alloc_tstate(ahd, ahd->our_id, 'A') == NULL) {
printf("%s: unable to allocate ahd_tmode_tstate. "
"Failing attach\n", ahd_name(ahd));
AHD_FATAL_ERROR(ahd);
return (ENOMEM);
}
@ -7135,6 +7186,7 @@ ahd_pause_and_flushwork(struct ahd_softc *ahd)
if (maxloops == 0) {
printf("Infinite interrupt loop, INTSTAT = %x",
ahd_inb(ahd, INTSTAT));
AHD_FATAL_ERROR(ahd);
}
ahd->qfreeze_cnt++;
ahd_outw(ahd, KERNEL_QFREEZE_COUNT, ahd->qfreeze_cnt);
@ -7440,6 +7492,7 @@ ahd_search_qinfifo(struct ahd_softc *ahd, int target, char channel,
if (scb == NULL) {
printf("qinpos = %d, SCB index = %d\n",
qinpos, ahd->qinfifo[qinpos]);
AHD_FATAL_ERROR(ahd);
panic("Loop 1\n");
}
@ -8195,20 +8248,26 @@ ahd_handle_scsi_status(struct ahd_softc *ahd, struct scb *scb)
switch (SIU_PKTFAIL_CODE(siu)) {
case SIU_PFC_NONE:
printf("No packet failure found\n");
AHD_UNCORRECTABLE_ERROR(ahd);
break;
case SIU_PFC_CIU_FIELDS_INVALID:
printf("Invalid Command IU Field\n");
AHD_UNCORRECTABLE_ERROR(ahd);
break;
case SIU_PFC_TMF_NOT_SUPPORTED:
printf("TMF not supportd\n");
AHD_UNCORRECTABLE_ERROR(ahd);
break;
case SIU_PFC_TMF_FAILED:
printf("TMF failed\n");
AHD_UNCORRECTABLE_ERROR(ahd);
break;
case SIU_PFC_INVALID_TYPE_CODE:
printf("Invalid L_Q Type code\n");
AHD_UNCORRECTABLE_ERROR(ahd);
break;
case SIU_PFC_ILLEGAL_REQUEST:
AHD_UNCORRECTABLE_ERROR(ahd);
printf("Illegal request\n");
default:
break;
@ -9281,6 +9340,7 @@ ahd_recover_commands(struct ahd_softc *ahd)
printf("%s: Recovery Initiated - Card was %spaused\n", ahd_name(ahd),
was_paused ? "" : "not ");
AHD_CORRECTABLE_ERROR(ahd);
ahd_dump_card_state(ahd);
ahd_pause_and_flushwork(ahd);
@ -9507,6 +9567,7 @@ ahd_other_scb_timeout(struct ahd_softc *ahd, struct scb *scb,
(scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
? " again\n" : "\n");
AHD_UNCORRECTABLE_ERROR(ahd);
newtimeout = aic_get_timeout(scb);
scb->flags |= SCB_OTHERTCL_TIMEOUT;
found = 0;
@ -9929,6 +9990,7 @@ ahd_handle_en_lun(struct ahd_softc *ahd, struct cam_sim *sim, union ccb *ccb)
if (lstate != NULL) {
xpt_print_path(ccb->ccb_h.path);
printf("Lun already enabled\n");
AHD_CORRECTABLE_ERROR(ahd);
ccb->ccb_h.status = CAM_LUN_ALRDY_ENA;
return;
}

View File

@ -1061,6 +1061,27 @@ typedef enum {
#define AHD_MODE_UNKNOWN_MSK AHD_MK_MSK(AHD_MODE_UNKNOWN)
#define AHD_MODE_ANY_MSK (~0)
typedef enum {
AHD_SYSCTL_ROOT,
AHD_SYSCTL_SUMMARY,
AHD_SYSCTL_DEBUG,
AHD_SYSCTL_NUMBER
} ahd_sysctl_types_t;
typedef enum {
AHD_ERRORS_CORRECTABLE,
AHD_ERRORS_UNCORRECTABLE,
AHD_ERRORS_FATAL,
AHD_ERRORS_NUMBER
} ahd_sysctl_errors_t;
#define AHD_CORRECTABLE_ERROR(sc) \
(((sc)->summerr[AHD_ERRORS_CORRECTABLE])++)
#define AHD_UNCORRECTABLE_ERROR(sc) \
(((sc)->summerr[AHD_ERRORS_UNCORRECTABLE])++)
#define AHD_FATAL_ERROR(sc) \
(((sc)->summerr[AHD_ERRORS_FATAL])++)
typedef uint8_t ahd_mode_state;
typedef void ahd_callback_t (void *);
@ -1158,6 +1179,13 @@ struct ahd_softc {
uint32_t cmdcmplt_counts[AHD_STAT_BUCKETS];
uint32_t cmdcmplt_total;
/*
* Errors statistics and printouts.
*/
struct sysctl_ctx_list sysctl_ctx[AHD_SYSCTL_NUMBER];
struct sysctl_oid *sysctl_tree[AHD_SYSCTL_NUMBER];
u_int summerr[AHD_ERRORS_NUMBER];
/*
* Card characteristics
*/

View File

@ -77,6 +77,63 @@ static int ahd_create_path(struct ahd_softc *ahd,
char channel, u_int target, u_int lun,
struct cam_path **path);
static const char *ahd_sysctl_node_elements[] = {
"root",
"summary",
"debug"
};
static const char *ahd_sysctl_node_descriptions[] = {
"root error collection for aic79xx controllers",
"summary collection for aic79xx controllers",
"debug collection for aic79xx controllers"
};
static const char *ahd_sysctl_errors_elements[] = {
"Cerrors",
"Uerrors",
"Ferrors"
};
static const char *ahd_sysctl_errors_descriptions[] = {
"Correctable errors",
"Uncorrectable errors",
"Fatal errors"
};
static int
ahd_set_debugcounters(SYSCTL_HANDLER_ARGS)
{
struct ahd_softc *sc;
int error, tmpv;
tmpv = 0;
sc = arg1;
error = sysctl_handle_int(oidp, &tmpv, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
if (tmpv < 0 || tmpv >= AHD_ERRORS_NUMBER)
return (EINVAL);
sc->summerr[arg2] = tmpv;
return (0);
}
static int
ahd_clear_allcounters(SYSCTL_HANDLER_ARGS)
{
struct ahd_softc *sc;
int error, tmpv;
tmpv = 0;
sc = arg1;
error = sysctl_handle_int(oidp, &tmpv, 0, req);
if (error != 0 || req->newptr == NULL)
return (error);
if (tmpv != 0)
bzero(sc->summerr, sizeof(sc->summerr));
return (0);
}
static int
ahd_create_path(struct ahd_softc *ahd, char channel, u_int target,
u_int lun, struct cam_path **path)
@ -88,6 +145,48 @@ ahd_create_path(struct ahd_softc *ahd, char channel, u_int target,
path_id, target, lun));
}
void
ahd_sysctl(struct ahd_softc *ahd)
{
u_int i;
for (i = 0; i < AHD_SYSCTL_NUMBER; i++)
sysctl_ctx_init(&ahd->sysctl_ctx[i]);
ahd->sysctl_tree[AHD_SYSCTL_ROOT] =
SYSCTL_ADD_NODE(&ahd->sysctl_ctx[AHD_SYSCTL_ROOT],
SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
device_get_nameunit(ahd->dev_softc), CTLFLAG_RD, 0,
ahd_sysctl_node_descriptions[AHD_SYSCTL_ROOT]);
SYSCTL_ADD_PROC(&ahd->sysctl_ctx[AHD_SYSCTL_ROOT],
SYSCTL_CHILDREN(ahd->sysctl_tree[AHD_SYSCTL_ROOT]),
OID_AUTO, "clear", CTLTYPE_UINT | CTLFLAG_RW, ahd,
0, ahd_clear_allcounters, "IU",
"Clear all counters");
for (i = AHD_SYSCTL_SUMMARY; i < AHD_SYSCTL_NUMBER; i++)
ahd->sysctl_tree[i] =
SYSCTL_ADD_NODE(&ahd->sysctl_ctx[i],
SYSCTL_CHILDREN(ahd->sysctl_tree[AHD_SYSCTL_ROOT]),
OID_AUTO, ahd_sysctl_node_elements[i],
CTLFLAG_RD, 0,
ahd_sysctl_node_descriptions[i]);
for (i = AHD_ERRORS_CORRECTABLE; i < AHD_ERRORS_NUMBER; i++) {
SYSCTL_ADD_UINT(&ahd->sysctl_ctx[AHD_SYSCTL_SUMMARY],
SYSCTL_CHILDREN(ahd->sysctl_tree[AHD_SYSCTL_SUMMARY]),
OID_AUTO, ahd_sysctl_errors_elements[i],
CTLFLAG_RD, &ahd->summerr[i], i,
ahd_sysctl_errors_descriptions[i]);
SYSCTL_ADD_PROC(&ahd->sysctl_ctx[AHD_SYSCTL_DEBUG],
SYSCTL_CHILDREN(ahd->sysctl_tree[AHD_SYSCTL_DEBUG]),
OID_AUTO, ahd_sysctl_errors_elements[i],
CTLFLAG_RW | CTLTYPE_UINT, ahd, i,
ahd_set_debugcounters, "IU",
ahd_sysctl_errors_descriptions[i]);
}
}
int
ahd_map_int(struct ahd_softc *ahd)
{

View File

@ -51,6 +51,7 @@
#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
#define AIC_PCI_CONFIG 1
#include <machine/bus.h>
@ -259,6 +260,7 @@ void ahd_platform_free(struct ahd_softc *ahd);
int ahd_map_int(struct ahd_softc *ahd);
int ahd_attach(struct ahd_softc *);
int ahd_softc_comp(struct ahd_softc *lahd, struct ahd_softc *rahd);
void ahd_sysctl(struct ahd_softc *ahd);
int ahd_detach(device_t);
#define ahd_platform_init(arg)