e***@sun.com
2008-07-31 05:32:29 UTC
Hi,
I have some questions about how to use ddi_fm_acc_err_get() and
ddi_fm_dma_err_get().
If DDI_DMA_FLAGERR and DDI_FLAGERR_ACC are set in a driver, but
you don't have your own error handler to control errors reported,
then should ddi_fm_acc_err_get() and ddi_fm_dma_err_get() be
called every time ddi_{get,put}XX() and pci_config_{get,put}XX()
are issued or the dma transaction is finished (to handler errors)?
For example, you just call pci_ereport_post() in your error handler
because your card is connected to PCI-e but you don't want to
control your errors in detail such as:
int
your_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
{
/*
* as the driver can always deal with an error in any dma or
* access handle, we can just return the fme_status value.
*/
pci_ereport_post(dip, err, NULL);
return (err->fme_status);
}
then should you check the result by calling ddi_fm_acc_err_get() or
ddi_fm_dma_err_get() after ddi_{get,put}XX() and pci_config_{get,put}XX()
are called or the dma is over respectively?
For example, you should call ddi_fma_acc_err() and ddi_fm_dma_err_get()
as follows in this case? It looks tedious though.
(Is there a different way not to get the corrupted data or guarantee the
data is written correctly?)
uintXX_t value;
ddi_fma_err_t de;
/* ddi_getXX example */
value = ddi_getXX(handle, address);
ddi_fma_acc_err(handle, &de, DDI_FME_VERSION);
if (de.fme_statue != FM_OK) {
ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
ddi_fm_service_impact(dip, DDI_SERVICE_DEGRADED);
return (EIO);
}
/* ddi_putXX example */
ddi_putXX(handle, address, value);
ddi_fma_acc_err(handle, &de, DDI_FME_VERSION);
if (de.fme_statue != FM_OK) {
ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
ddi_fm_service_impact(dip, DDI_SERVICE_DEGRADED);
return (EIO);
}
/* pci_config_getXX example */
value = pci_config_getXX(handle, offset);
ddi_fma_acc_err(handle, &de, DDI_FME_VERSION);
if (de.fme_statue != FM_OK) {
ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
ddi_fm_service_impact(dip, DDI_SERVICE_DEGRADED);
return (EIO);
}
/* pci_config_putXX example */
pci_config_putXX(handle, offset, value);
ddi_fma_acc_err(handle, &de, DDI_FME_VERSION);
if (de.fme_statue != FM_OK) {
ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
ddi_fm_service_impact(dip, DDI_SERVICE_DEGRADED);
return (EIO);
}
/* dma example */
SET_DATA_TO_DMA_BUFFER(dip); // pseudo code to set data
START_DMA(handle); // pseudo code to start DMA transaction.
DMA_SYNC(handle);
ddi_fma_dma_err(handle, &de, DDI_FME_VERSION);
if (de.fme_statue != FM_OK) {
ddi_fm_dma_err_clear(handle, DDI_FME_VERSION);
ddi_fm_service_impact(dip, DDI_SERVICE_DEGRADED);
return (EIO);
}
Also there looks no functions yet calling ddi_fm_dma_err_clear(), but why?
For example, bge_check_acc_handle() calls ddi_fm_acc_err_clear() inside,
but bge_check_dma_handle() doesn't call ddi_fm_dma_err_clear().
(and there looks no functions calling it yet..)
/*ARGSUSED*/
int
bge_check_acc_handle(bge_t *bgep, ddi_acc_handle_t handle)
{
ddi_fm_error_t de;
ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
return (de.fme_status);
}
/*ARGSUSED*/
int
bge_check_dma_handle(bge_t *bgep, ddi_dma_handle_t handle)
{
ddi_fm_error_t de;
ASSERT(bgep->progress & PROGRESS_BUFS);
ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
return (de.fme_status);
}
One more. If you call pci_ereport_post() in your error handler,
I guess the system panics in case of the fatal errors, but what kind of
errors are there as non-fatal ones? I think BTO/BERRs or some
target/master aborts might be OK, but how can I tell which is which
exactly?
Thanks,
-Eiji
I have some questions about how to use ddi_fm_acc_err_get() and
ddi_fm_dma_err_get().
If DDI_DMA_FLAGERR and DDI_FLAGERR_ACC are set in a driver, but
you don't have your own error handler to control errors reported,
then should ddi_fm_acc_err_get() and ddi_fm_dma_err_get() be
called every time ddi_{get,put}XX() and pci_config_{get,put}XX()
are issued or the dma transaction is finished (to handler errors)?
For example, you just call pci_ereport_post() in your error handler
because your card is connected to PCI-e but you don't want to
control your errors in detail such as:
int
your_fm_error_cb(dev_info_t *dip, ddi_fm_error_t *err, const void *impl_data)
{
/*
* as the driver can always deal with an error in any dma or
* access handle, we can just return the fme_status value.
*/
pci_ereport_post(dip, err, NULL);
return (err->fme_status);
}
then should you check the result by calling ddi_fm_acc_err_get() or
ddi_fm_dma_err_get() after ddi_{get,put}XX() and pci_config_{get,put}XX()
are called or the dma is over respectively?
For example, you should call ddi_fma_acc_err() and ddi_fm_dma_err_get()
as follows in this case? It looks tedious though.
(Is there a different way not to get the corrupted data or guarantee the
data is written correctly?)
uintXX_t value;
ddi_fma_err_t de;
/* ddi_getXX example */
value = ddi_getXX(handle, address);
ddi_fma_acc_err(handle, &de, DDI_FME_VERSION);
if (de.fme_statue != FM_OK) {
ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
ddi_fm_service_impact(dip, DDI_SERVICE_DEGRADED);
return (EIO);
}
/* ddi_putXX example */
ddi_putXX(handle, address, value);
ddi_fma_acc_err(handle, &de, DDI_FME_VERSION);
if (de.fme_statue != FM_OK) {
ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
ddi_fm_service_impact(dip, DDI_SERVICE_DEGRADED);
return (EIO);
}
/* pci_config_getXX example */
value = pci_config_getXX(handle, offset);
ddi_fma_acc_err(handle, &de, DDI_FME_VERSION);
if (de.fme_statue != FM_OK) {
ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
ddi_fm_service_impact(dip, DDI_SERVICE_DEGRADED);
return (EIO);
}
/* pci_config_putXX example */
pci_config_putXX(handle, offset, value);
ddi_fma_acc_err(handle, &de, DDI_FME_VERSION);
if (de.fme_statue != FM_OK) {
ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
ddi_fm_service_impact(dip, DDI_SERVICE_DEGRADED);
return (EIO);
}
/* dma example */
SET_DATA_TO_DMA_BUFFER(dip); // pseudo code to set data
START_DMA(handle); // pseudo code to start DMA transaction.
DMA_SYNC(handle);
ddi_fma_dma_err(handle, &de, DDI_FME_VERSION);
if (de.fme_statue != FM_OK) {
ddi_fm_dma_err_clear(handle, DDI_FME_VERSION);
ddi_fm_service_impact(dip, DDI_SERVICE_DEGRADED);
return (EIO);
}
Also there looks no functions yet calling ddi_fm_dma_err_clear(), but why?
For example, bge_check_acc_handle() calls ddi_fm_acc_err_clear() inside,
but bge_check_dma_handle() doesn't call ddi_fm_dma_err_clear().
(and there looks no functions calling it yet..)
/*ARGSUSED*/
int
bge_check_acc_handle(bge_t *bgep, ddi_acc_handle_t handle)
{
ddi_fm_error_t de;
ddi_fm_acc_err_get(handle, &de, DDI_FME_VERSION);
ddi_fm_acc_err_clear(handle, DDI_FME_VERSION);
return (de.fme_status);
}
/*ARGSUSED*/
int
bge_check_dma_handle(bge_t *bgep, ddi_dma_handle_t handle)
{
ddi_fm_error_t de;
ASSERT(bgep->progress & PROGRESS_BUFS);
ddi_fm_dma_err_get(handle, &de, DDI_FME_VERSION);
return (de.fme_status);
}
One more. If you call pci_ereport_post() in your error handler,
I guess the system panics in case of the fatal errors, but what kind of
errors are there as non-fatal ones? I think BTO/BERRs or some
target/master aborts might be OK, but how can I tell which is which
exactly?
Thanks,
-Eiji