diff options
Diffstat (limited to 'drivers/net/fddi/defxx.c')
-rw-r--r-- | drivers/net/fddi/defxx.c | 142 |
1 files changed, 97 insertions, 45 deletions
diff --git a/drivers/net/fddi/defxx.c b/drivers/net/fddi/defxx.c index 2aa57270838f..6eb849a56da5 100644 --- a/drivers/net/fddi/defxx.c +++ b/drivers/net/fddi/defxx.c @@ -196,6 +196,7 @@ * 14 Jun 2005 macro Use irqreturn_t. * 23 Oct 2006 macro Big-endian host support. * 14 Dec 2006 macro TURBOchannel support. + * 01 Jul 2014 macro Fixes for DMA on 64-bit hosts. */ /* Include files */ @@ -224,8 +225,8 @@ /* Version information string should be updated prior to each new release! */ #define DRV_NAME "defxx" -#define DRV_VERSION "v1.10" -#define DRV_RELDATE "2006/12/14" +#define DRV_VERSION "v1.11" +#define DRV_RELDATE "2014/07/01" static char version[] = DRV_NAME ": " DRV_VERSION " " DRV_RELDATE @@ -1126,17 +1127,16 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name, /* Display virtual and physical addresses if debug driver */ - DBG_printk("%s: Descriptor block virt = %0lX, phys = %0X\n", - print_name, - (long)bp->descr_block_virt, bp->descr_block_phys); - DBG_printk("%s: Command Request buffer virt = %0lX, phys = %0X\n", - print_name, (long)bp->cmd_req_virt, bp->cmd_req_phys); - DBG_printk("%s: Command Response buffer virt = %0lX, phys = %0X\n", - print_name, (long)bp->cmd_rsp_virt, bp->cmd_rsp_phys); - DBG_printk("%s: Receive buffer block virt = %0lX, phys = %0X\n", - print_name, (long)bp->rcv_block_virt, bp->rcv_block_phys); - DBG_printk("%s: Consumer block virt = %0lX, phys = %0X\n", - print_name, (long)bp->cons_block_virt, bp->cons_block_phys); + DBG_printk("%s: Descriptor block virt = %p, phys = %pad\n", + print_name, bp->descr_block_virt, &bp->descr_block_phys); + DBG_printk("%s: Command Request buffer virt = %p, phys = %pad\n", + print_name, bp->cmd_req_virt, &bp->cmd_req_phys); + DBG_printk("%s: Command Response buffer virt = %p, phys = %pad\n", + print_name, bp->cmd_rsp_virt, &bp->cmd_rsp_phys); + DBG_printk("%s: Receive buffer block virt = %p, phys = %pad\n", + print_name, bp->rcv_block_virt, &bp->rcv_block_phys); + DBG_printk("%s: Consumer block virt = %p, phys = %pad\n", + print_name, bp->cons_block_virt, &bp->cons_block_phys); return DFX_K_SUCCESS; } @@ -2927,21 +2927,35 @@ static int dfx_rcv_init(DFX_board_t *bp, int get_buffers) for (i = 0; i < (int)(bp->rcv_bufs_to_post); i++) for (j = 0; (i + j) < (int)PI_RCV_DATA_K_NUM_ENTRIES; j += bp->rcv_bufs_to_post) { - struct sk_buff *newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE, GFP_NOIO); + struct sk_buff *newskb; + dma_addr_t dma_addr; + + newskb = __netdev_alloc_skb(bp->dev, NEW_SKB_SIZE, + GFP_NOIO); if (!newskb) return -ENOMEM; - bp->descr_block_virt->rcv_data[i+j].long_0 = (u32) (PI_RCV_DESCR_M_SOP | - ((PI_RCV_DATA_K_SIZE_MAX / PI_ALIGN_K_RCV_DATA_BUFF) << PI_RCV_DESCR_V_SEG_LEN)); /* * align to 128 bytes for compatibility with * the old EISA boards. */ my_skb_align(newskb, 128); + dma_addr = dma_map_single(bp->bus_dev, + newskb->data, + PI_RCV_DATA_K_SIZE_MAX, + DMA_FROM_DEVICE); + if (dma_mapping_error(bp->bus_dev, dma_addr)) { + dev_kfree_skb(newskb); + return -ENOMEM; + } + bp->descr_block_virt->rcv_data[i + j].long_0 = + (u32)(PI_RCV_DESCR_M_SOP | + ((PI_RCV_DATA_K_SIZE_MAX / + PI_ALIGN_K_RCV_DATA_BUFF) << + PI_RCV_DESCR_V_SEG_LEN)); bp->descr_block_virt->rcv_data[i + j].long_1 = - (u32)dma_map_single(bp->bus_dev, newskb->data, - NEW_SKB_SIZE, - DMA_FROM_DEVICE); + (u32)dma_addr; + /* * p_rcv_buff_va is only used inside the * kernel so we put the skb pointer here. @@ -3008,7 +3022,7 @@ static void dfx_rcv_queue_process( PI_TYPE_2_CONSUMER *p_type_2_cons; /* ptr to rcv/xmt consumer block register */ char *p_buff; /* ptr to start of packet receive buffer (FMC descriptor) */ u32 descr, pkt_len; /* FMC descriptor field and packet length */ - struct sk_buff *skb; /* pointer to a sk_buff to hold incoming packet data */ + struct sk_buff *skb = NULL; /* pointer to a sk_buff to hold incoming packet data */ /* Service all consumed LLC receive frames */ @@ -3016,7 +3030,7 @@ static void dfx_rcv_queue_process( while (bp->rcv_xmt_reg.index.rcv_comp != p_type_2_cons->index.rcv_cons) { /* Process any errors */ - + dma_addr_t dma_addr; int entry; entry = bp->rcv_xmt_reg.index.rcv_comp; @@ -3025,6 +3039,11 @@ static void dfx_rcv_queue_process( #else p_buff = bp->p_rcv_buff_va[entry]; #endif + dma_addr = bp->descr_block_virt->rcv_data[entry].long_1; + dma_sync_single_for_cpu(bp->bus_dev, + dma_addr + RCV_BUFF_K_DESCR, + sizeof(u32), + DMA_FROM_DEVICE); memcpy(&descr, p_buff + RCV_BUFF_K_DESCR, sizeof(u32)); if (descr & PI_FMC_DESCR_M_RCC_FLUSH) @@ -3046,31 +3065,46 @@ static void dfx_rcv_queue_process( bp->rcv_length_errors++; else{ #ifdef DYNAMIC_BUFFERS + struct sk_buff *newskb = NULL; + if (pkt_len > SKBUFF_RX_COPYBREAK) { - struct sk_buff *newskb; + dma_addr_t new_dma_addr; - newskb = dev_alloc_skb(NEW_SKB_SIZE); + newskb = netdev_alloc_skb(bp->dev, + NEW_SKB_SIZE); if (newskb){ + my_skb_align(newskb, 128); + new_dma_addr = dma_map_single( + bp->bus_dev, + newskb->data, + PI_RCV_DATA_K_SIZE_MAX, + DMA_FROM_DEVICE); + if (dma_mapping_error( + bp->bus_dev, + new_dma_addr)) { + dev_kfree_skb(newskb); + newskb = NULL; + } + } + if (newskb) { rx_in_place = 1; - my_skb_align(newskb, 128); skb = (struct sk_buff *)bp->p_rcv_buff_va[entry]; dma_unmap_single(bp->bus_dev, - bp->descr_block_virt->rcv_data[entry].long_1, - NEW_SKB_SIZE, + dma_addr, + PI_RCV_DATA_K_SIZE_MAX, DMA_FROM_DEVICE); skb_reserve(skb, RCV_BUFF_K_PADDING); bp->p_rcv_buff_va[entry] = (char *)newskb; - bp->descr_block_virt->rcv_data[entry].long_1 = - (u32)dma_map_single(bp->bus_dev, - newskb->data, - NEW_SKB_SIZE, - DMA_FROM_DEVICE); - } else - skb = NULL; - } else + bp->descr_block_virt->rcv_data[entry].long_1 = (u32)new_dma_addr; + } + } + if (!newskb) #endif - skb = dev_alloc_skb(pkt_len+3); /* alloc new buffer to pass up, add room for PRH */ + /* Alloc new buffer to pass up, + * add room for PRH. */ + skb = netdev_alloc_skb(bp->dev, + pkt_len + 3); if (skb == NULL) { printk("%s: Could not allocate receive buffer. Dropping packet.\n", bp->dev->name); @@ -3080,6 +3114,12 @@ static void dfx_rcv_queue_process( else { if (!rx_in_place) { /* Receive buffer allocated, pass receive packet up */ + dma_sync_single_for_cpu( + bp->bus_dev, + dma_addr + + RCV_BUFF_K_PADDING, + pkt_len + 3, + DMA_FROM_DEVICE); skb_copy_to_linear_data(skb, p_buff + RCV_BUFF_K_PADDING, @@ -3182,6 +3222,7 @@ static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb, u8 prod; /* local transmit producer index */ PI_XMT_DESCR *p_xmt_descr; /* ptr to transmit descriptor block entry */ XMT_DRIVER_DESCR *p_xmt_drv_descr; /* ptr to transmit driver descriptor */ + dma_addr_t dma_addr; unsigned long flags; netif_stop_queue(dev); @@ -3229,6 +3270,20 @@ static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb, } } + /* Write the three PRH bytes immediately before the FC byte */ + + skb_push(skb, 3); + skb->data[0] = DFX_PRH0_BYTE; /* these byte values are defined */ + skb->data[1] = DFX_PRH1_BYTE; /* in the Motorola FDDI MAC chip */ + skb->data[2] = DFX_PRH2_BYTE; /* specification */ + + dma_addr = dma_map_single(bp->bus_dev, skb->data, skb->len, + DMA_TO_DEVICE); + if (dma_mapping_error(bp->bus_dev, dma_addr)) { + skb_pull(skb, 3); + return NETDEV_TX_BUSY; + } + spin_lock_irqsave(&bp->lock, flags); /* Get the current producer and the next free xmt data descriptor */ @@ -3249,13 +3304,6 @@ static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb, p_xmt_drv_descr = &(bp->xmt_drv_descr_blk[prod++]); /* also bump producer index */ - /* Write the three PRH bytes immediately before the FC byte */ - - skb_push(skb,3); - skb->data[0] = DFX_PRH0_BYTE; /* these byte values are defined */ - skb->data[1] = DFX_PRH1_BYTE; /* in the Motorola FDDI MAC chip */ - skb->data[2] = DFX_PRH2_BYTE; /* specification */ - /* * Write the descriptor with buffer info and bump producer * @@ -3284,8 +3332,7 @@ static netdev_tx_t dfx_xmt_queue_pkt(struct sk_buff *skb, */ p_xmt_descr->long_0 = (u32) (PI_XMT_DESCR_M_SOP | PI_XMT_DESCR_M_EOP | ((skb->len) << PI_XMT_DESCR_V_SEG_LEN)); - p_xmt_descr->long_1 = (u32)dma_map_single(bp->bus_dev, skb->data, - skb->len, DMA_TO_DEVICE); + p_xmt_descr->long_1 = (u32)dma_addr; /* * Verify that descriptor is actually available @@ -3448,8 +3495,13 @@ static void dfx_rcv_flush( DFX_board_t *bp ) { struct sk_buff *skb; skb = (struct sk_buff *)bp->p_rcv_buff_va[i+j]; - if (skb) + if (skb) { + dma_unmap_single(bp->bus_dev, + bp->descr_block_virt->rcv_data[i+j].long_1, + PI_RCV_DATA_K_SIZE_MAX, + DMA_FROM_DEVICE); dev_kfree_skb(skb); + } bp->p_rcv_buff_va[i+j] = NULL; } |