Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/71.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 网络设备没有缓冲区空间_C_Linux_Driver_Device_Uart - Fatal编程技术网

C 网络设备没有缓冲区空间

C 网络设备没有缓冲区空间,c,linux,driver,device,uart,C,Linux,Driver,Device,Uart,您好,我创建了网络驱动程序,它使用uart端口发送和接收数据。 我的驱动程序处理一些问题。我能打乒乓球,但每次打几下后,我都会得到 ping:sendmsg:没有可用的缓冲区空间 我检查了内核日志,但什么也看不到 这就是我接收数据的方式: struct stm32_port *stm32_port = netdev_priv(my_net); struct sk_buff *skb; unsigned char *dma_start; dma_start = stm32_port->rx

您好,我创建了网络驱动程序,它使用uart端口发送和接收数据。 我的驱动程序处理一些问题。我能打乒乓球,但每次打几下后,我都会得到

ping:sendmsg:没有可用的缓冲区空间

我检查了内核日志,但什么也看不到

这就是我接收数据的方式:

struct stm32_port *stm32_port = netdev_priv(my_net);
struct sk_buff *skb;
unsigned char *dma_start;

dma_start = stm32_port->rx_buf + (RX_BUF_L - stm32_port->last_res);
print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_OFFSET, 16, 1, dma_start, 16, true);

skb = dev_alloc_skb(dma_size + 2);
if (!skb) {
    if (printk_ratelimit(  ))
        printk(KERN_NOTICE "snull rx: low on mem - packet dropped\n");
    my_net->stats.rx_dropped++;
    //goto error;
}

memcpy(skb_put(skb, dma_size), dma_start, dma_size);

/* Write metadata, and then pass to the receive level */
skb->dev = my_net;
skb->protocol = eth_type_trans(skb, my_net);
skb->ip_summed = CHECKSUM_NONE; // let the OS check the checksum
my_net->stats.rx_packets++;
my_net->stats.rx_bytes += dma_size;
netif_rx(skb);

port->icount.rx += dma_size;
stm32_port->last_res -= dma_size;
if (stm32_port->last_res == 0)
    stm32_port->last_res = RX_BUF_L; //dma_count
以下是我发送数据的方式:

struct stm32_port *lp = netdev_priv(ndev);
struct uart_port *port = &lp->port;
struct sk_buff *sk_buff;
struct dma_async_tx_descriptor *desc = NULL;
struct stm32_usart_offsets *ofs = &lp->info->ofs;
unsigned pktlen = skb->len;
dma_cookie_t cookie;
int ret = 0;

//print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_OFFSET, 16, 1, skb->data, 16, true);

netif_stop_queue(ndev);

sk_buff = skb_get(skb);

if (ofs->icr == UNDEF_REG){
    stm32_usart_clr_bits(port, ofs->isr, USART_SR_TC);
}else{
    writel_relaxed(USART_ICR_TCCF, port->membase + ofs->icr);
}

    memcpy(&lp->tx_buf[0], sk_buff->data, pktlen);
    desc = dmaengine_prep_slave_single(lp->tx_ch,
                   lp->tx_dma_buf,
                   pktlen,
                   DMA_MEM_TO_DEV,
                   DMA_PREP_INTERRUPT);

    if (!desc){
        goto fallback_err;            
    }
    
    cookie = dmaengine_submit(desc);
    ret = dma_submit_error(cookie);
    if (ret) {
        /* dma no yet started, safe to free resources */
        dmaengine_terminate_async(lp->tx_ch);
        goto fallback_err;
    }

    /* Issue pending DMA TX requests */
    dma_async_issue_pending(lp->tx_ch);

    stm32_usart_set_bits(port, ofs->cr3, USART_CR3_DMAT);

/* rely on TXE irq (mask or unmask) for sending remaining data */
stm32_usart_tx_interrupt_disable(port);

ndev->stats.tx_packets++;
ndev->stats.tx_bytes += pktlen;

fallback_err:
skb_tx_timestamp(skb);
dev_kfree_skb (skb);
netif_start_queue(ndev);
return NETDEV_TX_OK;

多亏了@stark,我找到了一个解决方案,我现在用uu kfree_skb()方法释放缓冲区,因为这样就不会检查refcount。

skb不会被释放,如果refcount不是0。也许试着加一张支票。对不起,我的问题可能很傻。你到底是什么意思。我想当我发送时,netif_rx会释放缓冲区。发送时,我用dev_kfree_skb清除缓冲区。