当前位置: 代码迷 >> 综合 >> 调试tty发送的日志问题
  详细解决方案

调试tty发送的日志问题

热度:2   发布时间:2024-01-25 00:54:25.0

tty调试时,在串口终端发送数据流程调用 printk会导致死机 

解决办法


struct mid8250 {
int line;
int dma_index;
struct pci_dev *dma_dev;
struct uart_8250_dma dma;
struct mid8250_board *board;
struct hsu_dma_chip dma_chip;
void *mid8250_private_data;
int index;
int log_cnt;
};

 


int store_to_buff( struct mid8250 *mid, const char *format, ... )
{   
unsigned char buffer[2048];
va_list  vArgs;
va_start(vArgs, format);
vsnprintf((char *)buffer, sizeof(buffer), (char const *)format, vArgs);
va_end(vArgs);

strcpy( &mid->mid8250_private_data[mid->index], buffer );
mid->index = mid->index + strlen(buffer) + 1;
mid->log_cnt++;
return 0;
}

static void __dma_tx_complete(void *param)
{
struct uart_8250_port    *p = param;
struct uart_8250_dma    *dma = p->dma;
struct circ_buf        *xmit = &p->port.state->xmit;
unsigned long    flags;
int        ret;
int retval;

    struct uart_port *uport;
struct mid8250 *mid;

    uport = &p->port;

    mid = uport->private_data;
if (!mid){
//return;
}


//*(unsigned int *)mid->mid8250_private_data = 0x56789;

    
//seq_printf(m, "mid->mid8250_private_data[0] = 0x%x\n", *(unsigned int *)mid->mid8250_private_data );


//store_to_buff(mid, "in __dma_tx_complete\n" );

    

    dma_sync_single_for_cpu(dma->txchan->device->dev, dma->tx_addr,
UART_XMIT_SIZE, DMA_TO_DEVICE);

    spin_lock_irqsave(&p->port.lock, flags);


//pr_info( "in __dma_tx_complete\n" );

    dma->tx_running = 0;

    xmit->tail += dma->tx_size;
xmit->tail &= UART_XMIT_SIZE - 1;
p->port.icount.tx += dma->tx_size;

    if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS){
//store_to_buff(mid, "__dma_tx_complete.1\n" );
uart_write_wakeup(&p->port);
}

    ret = serial8250_tx_dma(p);
if (ret) {
store_to_buff(mid, "__dma_tx_complete.2\n" );
p->ier |= UART_IER_THRI;
serial_port_out(&p->port, UART_IER, p->ier);
}
//store_to_buff(mid, "__dma_tx_complete.3\n" );
spin_unlock_irqrestore(&p->port.lock, flags);
}

 


static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct uart_8250_port uart;
struct mid8250 *mid;
unsigned int bar;
int ret;



//printk(KERN_ERR "in mid8250_probe123\n");

    
ret = pcim_enable_device(pdev);
if (ret)
return ret;


//printk(KERN_ERR "sizeof(*mid) = %d\n", sizeof(*mid) );

    

    mid = devm_kzalloc(&pdev->dev, sizeof(*mid), GFP_KERNEL);
if (!mid)
return -ENOMEM;

    mid->mid8250_private_data = devm_kzalloc(&pdev->dev, 0x100000, GFP_KERNEL);
if (!mid->mid8250_private_data)
return -ENOMEM;

    

    

    printk(KERN_ERR "&dnv_board = 0x%llx\n", &dnv_board );
printk(KERN_ERR "id->driver_data = 0x%llx\n", id->driver_data );
printk(KERN_ERR "mid->mid8250_private_data = 0x%llx\n", mid->mid8250_private_data );


printk(KERN_ERR "mid = 0x%llx\n", mid );


*(unsigned int *)mid->mid8250_private_data = 0x11223344;
printk(KERN_ERR "mid->mid8250_private_data[0] = 0x%x\n", *(unsigned int *)mid->mid8250_private_data );

    mid->board = (struct mid8250_board *)id->driver_data;
bar = FL_GET_BASE(mid->board->flags);

    memset(&uart, 0, sizeof(struct uart_8250_port));

    uart.port.dev = &pdev->dev;
uart.port.irq = pdev->irq;
uart.port.private_data = mid;
uart.port.type = PORT_16750;
uart.port.iotype = UPIO_MEM;
uart.port.uartclk = mid->board->base_baud * 16;
uart.port.flags = UPF_SHARE_IRQ | UPF_FIXED_PORT | UPF_FIXED_TYPE;
uart.port.set_termios = mid8250_set_termios;

    uart.port.mapbase = pci_resource_start(pdev, bar);
uart.port.membase = pcim_iomap(pdev, bar, 0);
if (!uart.port.membase)
return -ENOMEM;

    if (mid->board->setup) {
ret = mid->board->setup(mid, &uart.port);
if (ret)
return ret;
}

    ret = mid8250_dma_setup(mid, &uart);
if (ret)
goto err;

    ret = serial8250_register_8250_port(&uart);
if (ret < 0)
goto err;

    mid->line = ret;

    pci_set_drvdata(pdev, mid);
return 0;
err:
if (mid->board->exit)
mid->board->exit(mid);
return ret;
}

 


static void uart_line_info(struct seq_file *m, struct uart_driver *drv, int i)
{
struct uart_state *state = drv->state + i;
struct tty_port *port = &state->port;
enum uart_pm_state pm_state;
struct uart_port *uport;
char stat_buf[32];
unsigned int status;
int mmio;
struct mid8250 *mid;
int j,index;
char *p_index;

    mutex_lock(&port->mutex);
uport = uart_port_check(state);
if (!uport)
goto out;


if( i != 5 ){
goto out;
}

seq_printf(m, "uport->name = %s\n", uport->name  );
seq_printf(m, "i = %d\n", i  );
seq_printf(m, "uport->private_data = %llx\n", uport->private_data  );
mid = uport->private_data;
if (!mid){
goto out;
}
seq_printf(m, "mid->mid8250_private_data[0] = 0x%x\n", *(unsigned int *)mid->mid8250_private_data );

    index = 0x00;
p_index = (char *)mid->mid8250_private_data;
seq_printf(m, "mid->index = 0x%x\n", mid->index );

for( j=0x00; j<mid->log_cnt; j++ ){ 
seq_printf(m, "%s", p_index );
index = strlen(p_index);
p_index = p_index + index + 1;
}
//macdbg_dmphex(mid->mid8250_private_data,200,m);

    

    mmio = uport->iotype >= UPIO_MEM;
seq_printf(m, "%d: uart:%s %s%08llX irq:%d",
uport->line, uart_type(uport),
mmio ? "mmio:0x" : "port:",
mmio ? (unsigned long long)uport->mapbase
: (unsigned long long)uport->iobase,
uport->irq);

    if (uport->type == PORT_UNKNOWN) {
seq_putc(m, '\n');
goto out;
}

    if (capable(CAP_SYS_ADMIN)) {
pm_state = state->pm_state;
if (pm_state != UART_PM_STATE_ON)
uart_change_pm(state, UART_PM_STATE_ON);
spin_lock_irq(&uport->lock);
status = uport->ops->get_mctrl(uport);
spin_unlock_irq(&uport->lock);
if (pm_state != UART_PM_STATE_ON)
uart_change_pm(state, pm_state);

        seq_printf(m, " tx:%d rx:%d",
uport->icount.tx, uport->icount.rx);
if (uport->icount.frame)
seq_printf(m, " fe:%d",    uport->icount.frame);
if (uport->icount.parity)
seq_printf(m, " pe:%d",    uport->icount.parity);
if (uport->icount.brk)
seq_printf(m, " brk:%d", uport->icount.brk);
if (uport->icount.overrun)
seq_printf(m, " oe:%d", uport->icount.overrun);

#define INFOBIT(bit, str) \
if (uport->mctrl & (bit)) \
strncat(stat_buf, (str), sizeof(stat_buf) - \
strlen(stat_buf) - 2)
#define STATBIT(bit, str) \
if (status & (bit)) \
strncat(stat_buf, (str), sizeof(stat_buf) - \
strlen(stat_buf) - 2)

        stat_buf[0] = '\0';
stat_buf[1] = '\0';
INFOBIT(TIOCM_RTS, "|RTS");
STATBIT(TIOCM_CTS, "|CTS");
INFOBIT(TIOCM_DTR, "|DTR");
STATBIT(TIOCM_DSR, "|DSR");
STATBIT(TIOCM_CAR, "|CD");
STATBIT(TIOCM_RNG, "|RI");
if (stat_buf[0])
stat_buf[0] = ' ';

        seq_puts(m, stat_buf);
}
seq_putc(m, '\n');
#undef STATBIT
#undef INFOBIT
out:
mutex_unlock(&port->mutex);
}

 


u8 * g_debug_buff;
int g_debug_buff_index;
#define macdbg_prser Ser_Printf

//#define Ser_WrStr do{ LOGI("%s", buffer); }while(0)
int g_printf_switch = 0x01;
int Ser_Printf (const char *format, ...)
{   
unsigned char buffer[80 + 1];
va_list  vArgs;
if( g_printf_switch == 0x00 ){
return 1;
}
va_start(vArgs, format);
vsnprintf((char *)buffer, sizeof(buffer), (char const *)format, vArgs);
va_end(vArgs);
//Ser_WrStr;
strcpy( &g_debug_buff[g_debug_buff_index], buffer );
g_debug_buff_index = g_debug_buff_index + strlen(buffer);
return 0;
}


int macdbg_dmphex(const char* buff, int len, struct seq_file *m)
{
int retval = 0; 
int x, y, tot, lineoff;
const char* curr;

g_debug_buff = kzalloc(1024, GFP_KERNEL);
if (!g_debug_buff){
return NULL;
}

lineoff = 0;
curr = buff;
tot = 0;
for( x = 0; x+16 < len; ){  
memset( g_debug_buff, 0x00, 1024 );
g_debug_buff_index = 0x00;
Ser_Printf("%x\t", lineoff);
for( y = 0; y < 16; y++ ){
macdbg_prser("%02x ", (unsigned char)*(curr + y));
}
macdbg_prser("  ");
for( y = 0; y < 16; y++ ){
char c;
c = *(curr + y);
if( c > 31 && c < 127 ){
macdbg_prser("%c", c);
}else{
macdbg_prser("%c", '.');
}
tot++;
}
curr += 16;
x += 16;
lineoff+=16;
//macdbg_prser("\r\n");
//print_log( "%s", g_debug_buff );

         seq_printf(m, "%s", g_debug_buff );
seq_putc(m, '\n');

}

//do last line
//Ser_Printf( "tot %d.\r\n", tot );                   
//Ser_Printf( "len %d.\r\n", len );                                                                                                            
memset( g_debug_buff, 0x00, 1024 );
g_debug_buff_index = 0x00;     
if( tot < len ){
curr = (buff + tot);
macdbg_prser("%x\t", lineoff);
for( y = 0; y < (len - tot); y++ ){
macdbg_prser("%02x ", (unsigned char)*(curr + y));
}
//padding with spaces
//Ser_Printf("(len - tot) %d.\r\n", (len - tot) );
if( (len - tot) < 16 ){
for( y = 0; y < (32 - ((len - tot)*2)); y++ ){
macdbg_prser(" ");
}
}
for( y = 0; y < 16-(len - tot); y++ ){
macdbg_prser(" ");
}
macdbg_prser("  "); 
//Ser_Printf("(len - tot) %d.\r\n", (len - tot) );
for( y = 0; y < (len - tot); y++ ){
char c;
c = *(curr + y);
if( c >31 && c < 127 ){
macdbg_prser("%c", c);
}else{
macdbg_prser("%c", '.');
}
}
}
//macdbg_prser("\r\n");
seq_printf(m, "%s", g_debug_buff );
seq_putc(m, '\n');

kfree(g_debug_buff);
return retval;
}      

#ifndef __8250_H__
#define __8250_H__

#include <linux/serial_8250.h>
#include <linux/serial_reg.h>
#include <linux/dmaengine.h>

#include <linux/dma/hsu.h>
//#include <linux/8250_pci.h>

struct uart_8250_dma {
int (*tx_dma)(struct uart_8250_port *p);
int (*rx_dma)(struct uart_8250_port *p);

    /* Filter function */
dma_filter_fn        fn;
/* Parameter to the filter function */
void            *rx_param;
void            *tx_param;

    struct dma_slave_config    rxconf;
struct dma_slave_config    txconf;

    struct dma_chan        *rxchan;
struct dma_chan        *txchan;

    /* Device address base for DMA operations */
phys_addr_t        rx_dma_addr;
phys_addr_t        tx_dma_addr;

    /* DMA address of the buffer in memory */
dma_addr_t        rx_addr;
dma_addr_t        tx_addr;

    dma_cookie_t        rx_cookie;
dma_cookie_t        tx_cookie;

    void            *rx_buf;

    size_t            rx_size;
size_t            tx_size;

    unsigned char        tx_running;
unsigned char        tx_err;
unsigned char        rx_running;
};

struct old_serial_port {
unsigned int uart;
unsigned int baud_base;
unsigned int port;
unsigned int irq;
upf_t        flags;
unsigned char io_type;
unsigned char __iomem *iomem_base;
unsigned short iomem_reg_shift;
};

struct serial8250_config {
const char    *name;
unsigned short    fifo_size;
unsigned short    tx_loadsz;
unsigned char    fcr;
unsigned char    rxtrig_bytes[UART_FCR_R_TRIG_MAX_STATE];
unsigned int    flags;
};

#define UART_CAP_FIFO    (1 << 8)    /* UART has FIFO */
#define UART_CAP_EFR    (1 << 9)    /* UART has EFR */
#define UART_CAP_SLEEP    (1 << 10)    /* UART has IER sleep */
#define UART_CAP_AFE    (1 << 11)    /* MCR-based hw flow control */
#define UART_CAP_UUE    (1 << 12)    /* UART needs IER bit 6 set (Xscale) */
#define UART_CAP_RTOIE    (1 << 13)    /* UART needs IER bit 4 set (Xscale, Tegra) */
#define UART_CAP_HFIFO    (1 << 14)    /* UART has a "hidden" FIFO */
#define UART_CAP_RPM    (1 << 15)    /* Runtime PM is active while idle */
#define UART_CAP_IRDA    (1 << 16)    /* UART supports IrDA line discipline */
#define UART_CAP_MINI    (1 << 17)    /* Mini UART on BCM283X family lacks:
* STOP PARITY EPAR SPAR WLEN5 WLEN6
*/

#define UART_BUG_QUOT    (1 << 0)    /* UART has buggy quot LSB */
#define UART_BUG_TXEN    (1 << 1)    /* UART has buggy TX IIR status */
#define UART_BUG_NOMSR    (1 << 2)    /* UART has buggy MSR status bits (Au1x00) */
#define UART_BUG_THRE    (1 << 3)    /* UART has buggy THRE reassertion */
#define UART_BUG_PARITY    (1 << 4)    /* UART mishandles parity if FIFO enabled */


#ifdef CONFIG_SERIAL_8250_SHARE_IRQ
#define SERIAL8250_SHARE_IRQS 1
#else
#define SERIAL8250_SHARE_IRQS 0
#endif

#define SERIAL8250_PORT_FLAGS(_base, _irq, _flags)        \
{                            \
.iobase        = _base,            \
.irq        = _irq,                \
.uartclk    = 1843200,            \
.iotype        = UPIO_PORT,            \
.flags        = UPF_BOOT_AUTOCONF | (_flags),    \
}

#define SERIAL8250_PORT(_base, _irq) SERIAL8250_PORT_FLAGS(_base, _irq, 0)


static inline int serial_in(struct uart_8250_port *up, int offset)
{
return up->port.serial_in(&up->port, offset);
}

static inline void serial_out(struct uart_8250_port *up, int offset, int value)
{
up->port.serial_out(&up->port, offset, value);
}

void serial8250_clear_and_reinit_fifos(struct uart_8250_port *p);

static inline int serial_dl_read(struct uart_8250_port *up)
{
return up->dl_read(up);
}

static inline void serial_dl_write(struct uart_8250_port *up, int value)
{
up->dl_write(up, value);
}

struct uart_8250_port *serial8250_get_port(int line);

void serial8250_rpm_get(struct uart_8250_port *p);
void serial8250_rpm_put(struct uart_8250_port *p);

void serial8250_rpm_get_tx(struct uart_8250_port *p);
void serial8250_rpm_put_tx(struct uart_8250_port *p);

int serial8250_em485_init(struct uart_8250_port *p);
void serial8250_em485_destroy(struct uart_8250_port *p);

static inline void serial8250_out_MCR(struct uart_8250_port *up, int value)
{
serial_out(up, UART_MCR, value);
}

static inline int serial8250_in_MCR(struct uart_8250_port *up)
{
return serial_in(up, UART_MCR);
}

#if defined(__alpha__) && !defined(CONFIG_PCI)
/*
* Digital did something really horribly wrong with the OUT1 and OUT2
* lines on at least some ALPHA's.  The failure mode is that if either
* is cleared, the machine locks up with endless interrupts.
*/
#define ALPHA_KLUDGE_MCR  (UART_MCR_OUT2 | UART_MCR_OUT1)
#else
#define ALPHA_KLUDGE_MCR 0
#endif

#ifdef CONFIG_SERIAL_8250_PNP
int serial8250_pnp_init(void);
void serial8250_pnp_exit(void);
#else
static inline int serial8250_pnp_init(void) { return 0; }
static inline void serial8250_pnp_exit(void) { }
#endif

#ifdef CONFIG_SERIAL_8250_FINTEK
int fintek_8250_probe(struct uart_8250_port *uart);
#else
static inline int fintek_8250_probe(struct uart_8250_port *uart) { return 0; }
#endif

#ifdef CONFIG_ARCH_OMAP1
static inline int is_omap1_8250(struct uart_8250_port *pt)
{
int res;

    switch (pt->port.mapbase) {
case OMAP1_UART1_BASE:
case OMAP1_UART2_BASE:
case OMAP1_UART3_BASE:
res = 1;
break;
default:
res = 0;
break;
}

    return res;
}

static inline int is_omap1510_8250(struct uart_8250_port *pt)
{
if (!cpu_is_omap1510())
return 0;

    return is_omap1_8250(pt);
}
#else
static inline int is_omap1_8250(struct uart_8250_port *pt)
{
return 0;
}
static inline int is_omap1510_8250(struct uart_8250_port *pt)
{
return 0;
}
#endif

#ifdef CONFIG_SERIAL_8250_DMA
extern int serial8250_tx_dma(struct uart_8250_port *);
extern int serial8250_rx_dma(struct uart_8250_port *);
extern void serial8250_rx_dma_flush(struct uart_8250_port *);
extern int serial8250_request_dma(struct uart_8250_port *);
extern void serial8250_release_dma(struct uart_8250_port *);
#else
static inline int serial8250_tx_dma(struct uart_8250_port *p)
{
return -1;
}
static inline int serial8250_rx_dma(struct uart_8250_port *p)
{
return -1;
}
static inline void serial8250_rx_dma_flush(struct uart_8250_port *p) { }
static inline int serial8250_request_dma(struct uart_8250_port *p)
{
return -1;
}
static inline void serial8250_release_dma(struct uart_8250_port *p) { }
#endif

static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
{
unsigned char status;

    status = serial_in(up, 0x04); /* EXCR2 */
#define PRESL(x) ((x) & 0x30)
if (PRESL(status) == 0x10) {
/* already in high speed mode */
return 0;
} else {
status &= ~0xB0; /* Disable LOCK, mask out PRESL[01] */
status |= 0x10;  /* 1.625 divisor for baud_base --> 921600 */
serial_out(up, 0x04, status);
}
return 1;
}

static inline int serial_index(struct uart_port *port)
{
return port->minor - 64;
}

struct mid8250;

struct mid8250_board {
unsigned int flags;
unsigned long freq;
unsigned int base_baud;
int (*setup)(struct mid8250 *, struct uart_port *p);
void (*exit)(struct mid8250 *);
};

struct mid8250 {
int line;
int dma_index;
struct pci_dev *dma_dev;
struct uart_8250_dma dma;
struct mid8250_board *board;
struct hsu_dma_chip dma_chip;
void *mid8250_private_data;
int index;
int log_cnt;
};

#endif

 

  相关解决方案