问题描述
您好,我创建了使用 uart 端口发送和接收的网络驱动程序。 我的驱动程序遇到了一些问题。我能够 ping 但总是在我得到几个 ping 之后
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,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_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,skb->data,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,我找到了一个解决方案,我现在使用 __kfree_skb() 方法释放缓冲区,因为这样不会检查引用计数。