aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/fddi/defxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/fddi/defxx.c')
-rw-r--r--drivers/net/fddi/defxx.c142
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;
}