Alan,
I've noticed the oops has been fixed but the driver still fails due to a
memory exaustion. I've worked on merging 2.4.1-ac1 changes with what I
developed so far. Following is the result. No more memory exaustion, as
skbs are not allocated with GFP_ATOMIC upon startup anymore (no change to
the rx interrupt handler, of course).
I've also changed drivers/net/Config.in -- the driver handles EISA DEFEA
boards as well.
I'm not sure who is responsible for 2.4.1-ac1 fixes to the driver so I
put a change log entry with no ID.
Maciej
--
+ Maciej W. Rozycki, Technical University of Gdansk, Poland +
+--------------------------------------------------------------+
+ e-mail: [email protected], PGP key available +
patch-2.4.1-ac1-defxx-8
diff -up --recursive --new-file linux-2.4.1-ac1.macro/drivers/net/Config.in linux-2.4.1-ac1/drivers/net/Config.in
--- linux-2.4.1-ac1.macro/drivers/net/Config.in Sat Feb 3 12:16:31 2001
+++ linux-2.4.1-ac1/drivers/net/Config.in Sat Feb 3 13:03:29 2001
@@ -192,7 +192,9 @@ endmenu
bool 'FDDI driver support' CONFIG_FDDI
if [ "$CONFIG_FDDI" = "y" ]; then
- dep_tristate ' Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX $CONFIG_PCI
+ if [ "$CONFIG_PCI" = "y" -o "$CONFIG_EISA" = "y" ]; then
+ tristate ' Digital DEFEA and DEFPA adapter support' CONFIG_DEFXX
+ fi
tristate ' SysKonnect FDDI PCI support' CONFIG_SKFP
fi
diff -up --recursive --new-file linux-2.4.1-ac1.macro/drivers/net/defxx.c linux-2.4.1-ac1/drivers/net/defxx.c
--- linux-2.4.1-ac1.macro/drivers/net/defxx.c Sat Feb 3 12:16:33 2001
+++ linux-2.4.1-ac1/drivers/net/defxx.c Sat Feb 3 14:22:52 2001
@@ -195,6 +195,7 @@
* Jun 2000 jgarzik PCI and resource alloc cleanups
* Jul 2000 tjeerd Much cleanup and some bug fixes
* Sep 2000 tjeerd Fix leak on unload, cosmetic code cleanup
+ * Feb 2001 Skb allocation fixes
*/
/* Include files */
@@ -225,7 +226,7 @@
/* Version information string - should be updated prior to each new release!!! */
static char version[] __devinitdata =
- "defxx.c:v1.05d 2000/09/05 Lawrence V. Stefani and others\n";
+ "defxx.c:v1.05e 2001/02/03 Lawrence V. Stefani and others\n";
#define DYNAMIC_BUFFERS 1
@@ -242,7 +243,7 @@ static void dfx_bus_init(struct net_dev
static void dfx_bus_config_check(DFX_board_t *bp);
static int dfx_driver_init(struct net_device *dev);
-static int dfx_adap_init(DFX_board_t *bp);
+static int dfx_adap_init(DFX_board_t *bp, int get_buffers);
static int dfx_open(struct net_device *dev);
static int dfx_close(struct net_device *dev);
@@ -264,7 +265,7 @@ static void dfx_hw_adap_reset(DFX_board
static int dfx_hw_adap_state_rd(DFX_board_t *bp);
static int dfx_hw_dma_uninit(DFX_board_t *bp, PI_UINT32 type);
-static int dfx_rcv_init(DFX_board_t *bp);
+static int dfx_rcv_init(DFX_board_t *bp, int get_buffers);
static void dfx_rcv_queue_process(DFX_board_t *bp);
static void dfx_rcv_flush(DFX_board_t *bp);
@@ -973,6 +974,7 @@ static int __devinit dfx_driver_init(str
*
* Arguments:
* bp - pointer to board information
+ * get_buffers - non-zero if buffers to be allocated
*
* Functional Description:
* Issues the low-level firmware/hardware calls necessary to bring
@@ -992,7 +994,7 @@ static int __devinit dfx_driver_init(str
* upon a successful return of this routine.
*/
-static int dfx_adap_init(DFX_board_t *bp)
+static int dfx_adap_init(DFX_board_t *bp, int get_buffers)
{
DBG_printk("In dfx_adap_init...\n");
@@ -1132,14 +1134,16 @@ static int dfx_adap_init(DFX_board_t *bp
* reinitialized)
*/
- dfx_rcv_flush(bp);
+ if (get_buffers)
+ dfx_rcv_flush(bp);
/* Initialize receive descriptor block and produce buffers */
- if (dfx_rcv_init(bp))
+ if (dfx_rcv_init(bp, get_buffers))
{
printk("%s: Receive buffer allocation failed\n", bp->dev->name);
- dfx_rcv_flush(bp);
+ if (get_buffers)
+ dfx_rcv_flush(bp);
return(DFX_K_FAILURE);
}
@@ -1149,7 +1153,8 @@ static int dfx_adap_init(DFX_board_t *bp
if (dfx_hw_dma_cmd_req(bp) != DFX_K_SUCCESS)
{
printk("%s: Start command failed\n", bp->dev->name);
- dfx_rcv_flush(bp);
+ if (get_buffers)
+ dfx_rcv_flush(bp);
return(DFX_K_FAILURE);
}
@@ -1235,7 +1240,7 @@ static int dfx_open(struct net_device *d
/* Reset and initialize adapter */
bp->reset_type = PI_PDATA_A_RESET_M_SKIP_ST; /* skip self-test */
- if (dfx_adap_init(bp) != DFX_K_SUCCESS)
+ if (dfx_adap_init(bp, 1) != DFX_K_SUCCESS)
{
printk(KERN_ERR "%s: Adapter open failed!\n", dev->name);
free_irq(dev->irq, dev);
@@ -1512,7 +1517,7 @@ static void dfx_int_type_0_process(DFX_b
bp->link_available = PI_K_FALSE; /* link is no longer available */
bp->reset_type = 0; /* rerun on-board diagnostics */
printk("%s: Resetting adapter...\n", bp->dev->name);
- if (dfx_adap_init(bp) != DFX_K_SUCCESS)
+ if (dfx_adap_init(bp, 0) != DFX_K_SUCCESS)
{
printk("%s: Adapter reset failed! Disabling adapter interrupts.\n", bp->dev->name);
dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
@@ -1560,7 +1565,7 @@ static void dfx_int_type_0_process(DFX_b
bp->link_available = PI_K_FALSE; /* link is no longer available */
bp->reset_type = 0; /* rerun on-board diagnostics */
printk("%s: Resetting adapter...\n", bp->dev->name);
- if (dfx_adap_init(bp) != DFX_K_SUCCESS)
+ if (dfx_adap_init(bp, 0) != DFX_K_SUCCESS)
{
printk("%s: Adapter reset failed! Disabling adapter interrupts.\n", bp->dev->name);
dfx_port_write_long(bp, PI_PDQ_K_REG_HOST_INT_ENB, PI_HOST_INT_K_DISABLE_ALL_INTS);
@@ -2634,7 +2639,28 @@ static int dfx_hw_dma_uninit(DFX_board_t
return(DFX_K_HW_TIMEOUT);
return(DFX_K_SUCCESS);
}
+
+/*
+ * =================
+ * = dfx_alloc_skb =
+ * =================
+ *
+ * Overview:
+ * Allocate an skbuff for sending.
+ *
+ * Functional Description:
+ * Same as dev_alloc_skb(), but it may sleep.
+ */
+static inline struct sk_buff *dfx_alloc_skb(unsigned int length)
+{
+ struct sk_buff *skb;
+
+ skb = alloc_skb(length + 16, GFP_BUFFER);
+ if (skb)
+ skb_reserve(skb, 16);
+ return skb;
+}
/*
* Align an sk_buff to a boundary power of 2
@@ -2665,6 +2691,7 @@ static void my_skb_align(struct sk_buff
*
* Arguments:
* bp - pointer to board information
+ * get_buffers - non-zero if buffers to be allocated
*
* Functional Description:
* This routine can be called during dfx_adap_init() or during an adapter
@@ -2686,7 +2713,7 @@ static void my_skb_align(struct sk_buff
* is notified.
*/
-static int dfx_rcv_init(DFX_board_t *bp)
+static int dfx_rcv_init(DFX_board_t *bp, int get_buffers)
{
int i, j; /* used in for loop */
@@ -2708,13 +2735,14 @@ static int dfx_rcv_init(DFX_board_t *bp)
* driver initialization when we allocated memory for the receive buffers.
*/
+ if (get_buffers) {
#ifdef DYNAMIC_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 = dev_alloc_skb(NEW_SKB_SIZE);
+ struct sk_buff *newskb = dfx_alloc_skb(NEW_SKB_SIZE);
if (!newskb)
- return -ENOMEM;
+ 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));
/*
@@ -2740,6 +2768,7 @@ static int dfx_rcv_init(DFX_board_t *bp)
bp->p_rcv_buff_va[i+j] = (char *) (bp->rcv_block_virt + (i * PI_RCV_DATA_K_SIZE_MAX));
}
#endif
+ }
/* Update receive producer and Type 2 register */
@@ -3221,7 +3250,8 @@ static void dfx_rcv_flush( DFX_board_t *
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 *skb = bp->p_rcv_buff_va[i+j];
+ struct sk_buff *skb;
+ skb = (struct sk_buff *)bp->p_rcv_buff_va[i+j];
if (skb)
dev_kfree_skb(skb);
bp->p_rcv_buff_va[i+j] = NULL;