1 /*******************************************************************************
2 
3 
4   Copyright(c) 1999 - 2004 Intel Corporation. All rights reserved.
5 
6   This program is free software; you can redistribute it and/or modify it
7   under the terms of the GNU General Public License as published by the Free
8   Software Foundation; either version 2 of the License, or (at your option)
9   any later version.
10 
11   This program is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
14   more details.
15 
16   You should have received a copy of the GNU General Public License along with
17   this program; if not, write to the Free Software Foundation, Inc., 59
18   Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 
20   The full GNU General Public License is included in this distribution in the
21   file called LICENSE.
22 
23   Contact Information:
24   Linux NICS <linux.nics@intel.com>
25   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
26 *******************************************************************************/
27 
28 /**********************************************************************
29 *                                                                     *
30 * INTEL CORPORATION                                                   *
31 *                                                                     *
32 * This software is supplied under the terms of the license included   *
33 * above.  All use of this driver must be in accordance with the terms *
34 * of that license.                                                    *
35 *                                                                     *
36 * Module Name:  e100_config.c                                         *
37 *                                                                     *
38 * Abstract:     Functions for configuring the network adapter.        *
39 *                                                                     *
40 * Environment:  This file is intended to be specific to the Linux     *
41 *               operating system.                                     *
42 *                                                                     *
43 **********************************************************************/
44 #include "e100_config.h"
45 
46 static void e100_config_long_rx(struct e100_private *bdp, unsigned char enable);
47 
48 static const u8 def_config[] = {
49 	CB_CFIG_BYTE_COUNT,
50 	0x08, 0x00, 0x00, 0x00, 0x00, 0x32, 0x07, 0x01,
51 	0x00, 0x2e, 0x00, 0x60, 0x00, 0xf2, 0xc8, 0x00,
52 	0x40, 0xf2, 0x80, 0x3f, 0x05
53 };
54 
55 /**
56  * e100_config_init_82557 - config the 82557 adapter
57  * @bdp: atapter's private data struct
58  *
59  * This routine will initialize the 82557 configure block.
60  * All other init functions will only set values that are
61  * different from the 82557 default.
62  */
63 void
e100_config_init_82557(struct e100_private * bdp)64 e100_config_init_82557(struct e100_private *bdp)
65 {
66 	/* initialize config block */
67 	memcpy(bdp->config, def_config, sizeof (def_config));
68 	bdp->config[0] = CB_CFIG_BYTE_COUNT;	/* just in case */
69 
70 	e100_config_ifs(bdp);
71 
72 	/*
73 	 * Enable extended statistical counters (82558 and up) and TCO counters
74 	 * (82559 and up) and set the statistical counters' mode in bdp
75 	 *
76 	 *  stat. mode      |    TCO stat. bit (2)  |  Extended stat. bit (5)
77 	 * ------------------------------------------------------------------
78 	 *  Basic (557)     |       0               |         1
79 	 * ------------------------------------------------------------------
80 	 *  Extended (558)  |       0               |         0
81 	 * ------------------------------------------------------------------
82 	 *  TCO (559)       |       1               |         1
83 	 * ------------------------------------------------------------------
84 	 *  Reserved        |       1               |         0
85 	 * ------------------------------------------------------------------
86 	 */
87 	bdp->config[6] &= ~CB_CFIG_TCO_STAT;
88 	bdp->config[6] |= CB_CFIG_EXT_STAT_DIS;
89 	bdp->stat_mode = E100_BASIC_STATS;
90 
91 	/* Setup for MII or 503 operation.  The CRS+CDT bit should only be set */
92 	/* when operating in 503 mode. */
93 	if (bdp->phy_addr == 32) {
94 		bdp->config[8] &= ~CB_CFIG_503_MII;
95 		bdp->config[15] |= CB_CFIG_CRS_OR_CDT;
96 	} else {
97 		bdp->config[8] |= CB_CFIG_503_MII;
98 		bdp->config[15] &= ~CB_CFIG_CRS_OR_CDT;
99 	}
100 
101 	e100_config_fc(bdp);
102 	e100_config_force_dplx(bdp);
103 	e100_config_promisc(bdp, false);
104 	e100_config_mulcast_enbl(bdp, false);
105 }
106 
107 static void
e100_config_init_82558(struct e100_private * bdp)108 e100_config_init_82558(struct e100_private *bdp)
109 {
110 	/* MWI enable. This should be turned on only if the adapter is a 82558/9
111 	 * and if the PCI command reg. has enabled the MWI bit. */
112 	bdp->config[3] |= CB_CFIG_MWI_EN;
113 
114 	bdp->config[6] &= ~CB_CFIG_EXT_TCB_DIS;
115 
116 	if (bdp->rev_id >= D101MA_REV_ID) {
117 		/* this is 82559 and up - enable TCO counters */
118 		bdp->config[6] |= CB_CFIG_TCO_STAT;
119 		bdp->config[6] |= CB_CFIG_EXT_STAT_DIS;
120 		bdp->stat_mode = E100_TCO_STATS;
121 
122 		if ((bdp->rev_id < D102_REV_ID) &&
123 		    (bdp->params.b_params & PRM_XSUMRX) &&
124 		    (bdp->pdev->device != 0x1209)) {
125 
126 			bdp->flags |= DF_CSUM_OFFLOAD;
127 			bdp->config[9] |= 1;
128 		}
129 	} else {
130 		/* this is 82558 */
131 		bdp->config[6] &= ~CB_CFIG_TCO_STAT;
132 		bdp->config[6] &= ~CB_CFIG_EXT_STAT_DIS;
133 		bdp->stat_mode = E100_EXTENDED_STATS;
134 	}
135 
136 	e100_config_long_rx(bdp, true);
137 }
138 
139 static void
e100_config_init_82550(struct e100_private * bdp)140 e100_config_init_82550(struct e100_private *bdp)
141 {
142 	/* The D102 chip allows for 32 config bytes.  This value is
143 	 * supposed to be in Byte 0.  Just add the extra bytes to
144 	 * what was already setup in the block. */
145 	bdp->config[0] += CB_CFIG_D102_BYTE_COUNT;
146 
147 	/* now we need to enable the extended RFD.  When this is
148 	 * enabled, the immediated receive data buffer starts at offset
149 	 * 32 from the RFD base address, instead of at offset 16. */
150 	bdp->config[7] |= CB_CFIG_EXTENDED_RFD;
151 
152 	/* put the chip into D102 receive mode.  This is necessary
153 	 * for any parsing and offloading features. */
154 	bdp->config[22] = CB_CFIG_RECEIVE_GAMLA_MODE;
155 
156 	/* set the flag if checksum offloading was enabled */
157 	if (bdp->params.b_params & PRM_XSUMRX) {
158 		bdp->flags |= DF_CSUM_OFFLOAD;
159 	}
160 }
161 
162 /* Initialize the adapter's configure block */
163 void
e100_config_init(struct e100_private * bdp)164 e100_config_init(struct e100_private *bdp)
165 {
166 	e100_config_init_82557(bdp);
167 
168 	if (bdp->flags & IS_BACHELOR)
169 		e100_config_init_82558(bdp);
170 
171 	if (bdp->rev_id >= D102_REV_ID)
172 		e100_config_init_82550(bdp);
173 }
174 
175 /**
176  * e100_force_config - force a configure command
177  * @bdp: atapter's private data struct
178  *
179  * This routine will force a configure command to the adapter.
180  * The command will be executed in polled mode as interrupts
181  * are _disabled_ at this time.
182  *
183  * Returns:
184  *      true: if the configure command was successfully issued and completed
185  *      false: otherwise
186  */
187 unsigned char
e100_force_config(struct e100_private * bdp)188 e100_force_config(struct e100_private *bdp)
189 {
190 	spin_lock_bh(&(bdp->config_lock));
191 
192 	bdp->config[0] = CB_CFIG_BYTE_COUNT;
193 	if (bdp->rev_id >= D102_REV_ID) {
194 		/* The D102 chip allows for 32 config bytes.  This value is
195 		   supposed to be in Byte 0.  Just add the extra bytes to
196 		   what was already setup in the block. */
197 		bdp->config[0] += CB_CFIG_D102_BYTE_COUNT;
198 	}
199 
200 	spin_unlock_bh(&(bdp->config_lock));
201 
202 	// although we call config outside the lock, there is no
203 	// race condition because config byte count has maximum value
204 	return e100_config(bdp);
205 }
206 
207 /**
208  * e100_config - issue a configure command
209  * @bdp: atapter's private data struct
210  *
211  * This routine will issue a configure command to the 82557.
212  * This command will be executed in polled mode as interrupts
213  * are _disabled_ at this time.
214  *
215  * Returns:
216  *      true: if the configure command was successfully issued and completed
217  *      false: otherwise
218  */
219 unsigned char
e100_config(struct e100_private * bdp)220 e100_config(struct e100_private *bdp)
221 {
222 	cb_header_t *pntcb_hdr;
223 	unsigned char res = true;
224 	nxmit_cb_entry_t *cmd;
225 
226 	if (bdp->config[0] == 0) {
227 		goto exit;
228 	}
229 
230 	if ((cmd = e100_alloc_non_tx_cmd(bdp)) == NULL) {
231 		res = false;
232 		goto exit;
233 	}
234 
235 	pntcb_hdr = (cb_header_t *) cmd->non_tx_cmd;
236 	pntcb_hdr->cb_cmd = __constant_cpu_to_le16(CB_CONFIGURE);
237 
238 	spin_lock_bh(&bdp->config_lock);
239 
240 	if (bdp->config[0] < CB_CFIG_MIN_PARAMS) {
241 		bdp->config[0] = CB_CFIG_MIN_PARAMS;
242 	}
243 
244 	/* Copy the device's config block to the device's memory */
245 	memcpy(cmd->non_tx_cmd->ntcb.config.cfg_byte, bdp->config,
246 	       bdp->config[0]);
247 	/* reset number of bytes to config next time */
248 	bdp->config[0] = 0;
249 
250 	spin_unlock_bh(&bdp->config_lock);
251 
252 	res = e100_exec_non_cu_cmd(bdp, cmd);
253 
254 exit:
255 	if (netif_running(bdp->device))
256 		netif_wake_queue(bdp->device);
257 	return res;
258 }
259 
260 /**
261  * e100_config_fc - config flow-control state
262  * @bdp: adapter's private data struct
263  *
264  * This routine will enable or disable flow control support in the adapter's
265  * config block. Flow control will be enable only if requested using the command
266  * line option, and if the link is flow-contorl capable (both us and the link
267  * partner). But, if link partner is capable of autoneg, but not capable of
268  * flow control, received PAUSE	frames are still honored.
269  */
270 void
e100_config_fc(struct e100_private * bdp)271 e100_config_fc(struct e100_private *bdp)
272 {
273 	unsigned char enable = false;
274 	/* 82557 doesn't support fc. Don't touch this option */
275 	if (!(bdp->flags & IS_BACHELOR))
276 		return;
277 
278 	/* Enable fc if requested and if the link supports it */
279 	if ((bdp->params.b_params & PRM_FC) && (bdp->flags &
280 		(DF_LINK_FC_CAP | DF_LINK_FC_TX_ONLY))) {
281 		enable = true;
282 	}
283 
284 	spin_lock_bh(&(bdp->config_lock));
285 
286 	if (enable) {
287 		if (bdp->flags & DF_LINK_FC_TX_ONLY) {
288 			/* If link partner is capable of autoneg, but  */
289 			/* not capable of flow control, Received PAUSE */
290 			/* frames are still honored, i.e.,             */
291 			/* transmitted frames would be paused by       */
292 			/* incoming PAUSE frames                       */
293 			bdp->config[16] = DFLT_NO_FC_DELAY_LSB;
294 			bdp->config[17] = DFLT_NO_FC_DELAY_MSB;
295 			bdp->config[19] &= ~(CB_CFIG_FC_RESTOP | CB_CFIG_FC_RESTART);
296 			bdp->config[19] |= CB_CFIG_FC_REJECT;
297 			bdp->config[19] &= ~CB_CFIG_TX_FC_DIS;
298 		} else {
299 			bdp->config[16] = DFLT_FC_DELAY_LSB;
300 			bdp->config[17] = DFLT_FC_DELAY_MSB;
301 			bdp->config[19] |= CB_CFIG_FC_OPTS;
302 			bdp->config[19] &= ~CB_CFIG_TX_FC_DIS;
303 		}
304 	} else {
305 		bdp->config[16] = DFLT_NO_FC_DELAY_LSB;
306 		bdp->config[17] = DFLT_NO_FC_DELAY_MSB;
307 		bdp->config[19] &= ~CB_CFIG_FC_OPTS;
308 		bdp->config[19] |= CB_CFIG_TX_FC_DIS;
309 	}
310 	E100_CONFIG(bdp, 19);
311 	spin_unlock_bh(&(bdp->config_lock));
312 
313 	return;
314 }
315 
316 /**
317  * e100_config_promisc - configure promiscuous mode
318  * @bdp: atapter's private data struct
319  * @enable: should we enable this option or not
320  *
321  * This routine will enable or disable promiscuous mode
322  * in the adapter's config block.
323  */
324 void
e100_config_promisc(struct e100_private * bdp,unsigned char enable)325 e100_config_promisc(struct e100_private *bdp, unsigned char enable)
326 {
327 	spin_lock_bh(&(bdp->config_lock));
328 
329 	/* if in promiscuous mode, save bad frames */
330 	if (enable) {
331 
332 		if (!(bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES)) {
333 			bdp->config[6] |= CB_CFIG_SAVE_BAD_FRAMES;
334 			E100_CONFIG(bdp, 6);
335 		}
336 
337 		if (bdp->config[7] & (u8) BIT_0) {
338 			bdp->config[7] &= (u8) (~BIT_0);
339 			E100_CONFIG(bdp, 7);
340 		}
341 
342 		if (!(bdp->config[15] & CB_CFIG_PROMISCUOUS)) {
343 			bdp->config[15] |= CB_CFIG_PROMISCUOUS;
344 			E100_CONFIG(bdp, 15);
345 		}
346 
347 	} else {		/* not in promiscuous mode */
348 
349 		if (bdp->config[6] & CB_CFIG_SAVE_BAD_FRAMES) {
350 			bdp->config[6] &= ~CB_CFIG_SAVE_BAD_FRAMES;
351 			E100_CONFIG(bdp, 6);
352 		}
353 
354 		if (!(bdp->config[7] & (u8) BIT_0)) {
355 			bdp->config[7] |= (u8) (BIT_0);
356 			E100_CONFIG(bdp, 7);
357 		}
358 
359 		if (bdp->config[15] & CB_CFIG_PROMISCUOUS) {
360 			bdp->config[15] &= ~CB_CFIG_PROMISCUOUS;
361 			E100_CONFIG(bdp, 15);
362 		}
363 	}
364 
365 	spin_unlock_bh(&(bdp->config_lock));
366 }
367 
368 /**
369  * e100_config_mulcast_enbl - configure allmulti mode
370  * @bdp: atapter's private data struct
371  * @enable: should we enable this option or not
372  *
373  * This routine will enable or disable reception of all multicast packets
374  * in the adapter's config block.
375  */
376 void
e100_config_mulcast_enbl(struct e100_private * bdp,unsigned char enable)377 e100_config_mulcast_enbl(struct e100_private *bdp, unsigned char enable)
378 {
379 	spin_lock_bh(&(bdp->config_lock));
380 
381 	/* this flag is used to enable receiving all multicast packet */
382 	if (enable) {
383 		if (!(bdp->config[21] & CB_CFIG_MULTICAST_ALL)) {
384 			bdp->config[21] |= CB_CFIG_MULTICAST_ALL;
385 			E100_CONFIG(bdp, 21);
386 		}
387 
388 	} else {
389 		if (bdp->config[21] & CB_CFIG_MULTICAST_ALL) {
390 			bdp->config[21] &= ~CB_CFIG_MULTICAST_ALL;
391 			E100_CONFIG(bdp, 21);
392 		}
393 	}
394 
395 	spin_unlock_bh(&(bdp->config_lock));
396 }
397 
398 /**
399  * e100_config_ifs - configure the IFS parameter
400  * @bdp: atapter's private data struct
401  *
402  * This routine will configure the adaptive IFS value
403  * in the adapter's config block. IFS values are only
404  * relevant in half duplex, so set to 0 in full duplex.
405  */
406 void
e100_config_ifs(struct e100_private * bdp)407 e100_config_ifs(struct e100_private *bdp)
408 {
409 	u8 value = 0;
410 
411 	spin_lock_bh(&(bdp->config_lock));
412 
413 	/* IFS value is only needed to be specified at half-duplex mode */
414 	if (bdp->cur_dplx_mode == HALF_DUPLEX) {
415 		value = (u8) bdp->ifs_value;
416 	}
417 
418 	if (bdp->config[2] != value) {
419 		bdp->config[2] = value;
420 		E100_CONFIG(bdp, 2);
421 	}
422 
423 	spin_unlock_bh(&(bdp->config_lock));
424 }
425 
426 /**
427  * e100_config_force_dplx - configure the forced full duplex mode
428  * @bdp: atapter's private data struct
429  *
430  * This routine will enable or disable force full duplex
431  * in the adapter's config block. If the PHY is 503, and
432  * the duplex is full, consider the adapter forced.
433  */
434 void
e100_config_force_dplx(struct e100_private * bdp)435 e100_config_force_dplx(struct e100_private *bdp)
436 {
437 	spin_lock_bh(&(bdp->config_lock));
438 
439 	/* We must force full duplex on if we are using PHY 0, and we are */
440 	/* supposed to run in FDX mode. We do this because the e100 has only */
441 	/* one FDX# input pin, and that pin will be connected to PHY 1. */
442 	/* Changed the 'if' condition below to fix performance problem * at 10
443 	 * full. The Phy was getting forced to full duplex while the MAC * was
444 	 * not, because the cur_dplx_mode was not being set to 2 by SetupPhy. *
445 	 * This is how the condition was, initially. * This has been changed so
446 	 * that the MAC gets forced to full duplex * simply if the user has
447 	 * forced full duplex. * * if (( bdp->phy_addr == 0 ) && (
448 	 * bdp->cur_dplx_mode == 2 )) */
449 	/* The rest of the fix is in the PhyDetect code. */
450 	if ((bdp->params.e100_speed_duplex == E100_SPEED_10_FULL) ||
451 	    (bdp->params.e100_speed_duplex == E100_SPEED_100_FULL) ||
452 	    ((bdp->phy_addr == 32) && (bdp->cur_dplx_mode == FULL_DUPLEX))) {
453 		if (!(bdp->config[19] & (u8) CB_CFIG_FORCE_FDX)) {
454 			bdp->config[19] |= (u8) CB_CFIG_FORCE_FDX;
455 			E100_CONFIG(bdp, 19);
456 		}
457 
458 	} else {
459 		if (bdp->config[19] & (u8) CB_CFIG_FORCE_FDX) {
460 			bdp->config[19] &= (u8) (~CB_CFIG_FORCE_FDX);
461 			E100_CONFIG(bdp, 19);
462 		}
463 	}
464 
465 	spin_unlock_bh(&(bdp->config_lock));
466 }
467 
468 /**
469  * e100_config_long_rx
470  * @bdp: atapter's private data struct
471  * @enable: should we enable this option or not
472  *
473  * This routine will enable or disable reception of larger packets.
474  * This is needed by VLAN implementations.
475  */
476 static void
e100_config_long_rx(struct e100_private * bdp,unsigned char enable)477 e100_config_long_rx(struct e100_private *bdp, unsigned char enable)
478 {
479 	if (enable) {
480 		if (!(bdp->config[18] & CB_CFIG_LONG_RX_OK)) {
481 			bdp->config[18] |= CB_CFIG_LONG_RX_OK;
482 			E100_CONFIG(bdp, 18);
483 		}
484 
485 	} else {
486 		if ((bdp->config[18] & CB_CFIG_LONG_RX_OK)) {
487 			bdp->config[18] &= ~CB_CFIG_LONG_RX_OK;
488 			E100_CONFIG(bdp, 18);
489 		}
490 	}
491 }
492 
493 /**
494  * e100_config_wol
495  * @bdp: atapter's private data struct
496  *
497  * This sets configuration options for PHY and Magic Packet WoL
498  */
499 void
e100_config_wol(struct e100_private * bdp)500 e100_config_wol(struct e100_private *bdp)
501 {
502 	spin_lock_bh(&(bdp->config_lock));
503 
504 	if (bdp->wolopts & WAKE_PHY) {
505 		bdp->config[9] |= CB_LINK_STATUS_WOL;
506 	}
507 	else {
508 		/* Disable PHY WoL */
509 		bdp->config[9] &= ~CB_LINK_STATUS_WOL;
510 	}
511 
512 	if (bdp->wolopts & WAKE_MAGIC) {
513 		bdp->config[19] &= ~CB_DISABLE_MAGPAK_WAKE;
514 	}
515 	else {
516 		/* Disable Magic Packet WoL */
517 		bdp->config[19] |= CB_DISABLE_MAGPAK_WAKE;
518 	}
519 
520 	E100_CONFIG(bdp, 19);
521 	spin_unlock_bh(&(bdp->config_lock));
522 }
523 
524 void
e100_config_vlan_drop(struct e100_private * bdp,unsigned char enable)525 e100_config_vlan_drop(struct e100_private *bdp, unsigned char enable)
526 {
527 	spin_lock_bh(&(bdp->config_lock));
528 	if (enable) {
529 		if (!(bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) {
530 			bdp->config[22] |= CB_CFIG_VLAN_DROP_ENABLE;
531 			E100_CONFIG(bdp, 22);
532 		}
533 
534 	} else {
535 		if ((bdp->config[22] & CB_CFIG_VLAN_DROP_ENABLE)) {
536 			bdp->config[22] &= ~CB_CFIG_VLAN_DROP_ENABLE;
537 			E100_CONFIG(bdp, 22);
538 		}
539 	}
540 	spin_unlock_bh(&(bdp->config_lock));
541 }
542 
543 /**
544  * e100_config_loopback_mode
545  * @bdp: atapter's private data struct
546  * @mode: loopback mode(phy/mac/none)
547  *
548  */
549 unsigned char
e100_config_loopback_mode(struct e100_private * bdp,u8 mode)550 e100_config_loopback_mode(struct e100_private *bdp, u8 mode)
551 {
552 	unsigned char bc_changed = false;
553 	u8 config_byte;
554 
555 	spin_lock_bh(&(bdp->config_lock));
556 
557 	switch (mode) {
558 	case NO_LOOPBACK:
559 		config_byte = CB_CFIG_LOOPBACK_NORMAL;
560 		break;
561 	case MAC_LOOPBACK:
562 		config_byte = CB_CFIG_LOOPBACK_INTERNAL;
563 		break;
564 	case PHY_LOOPBACK:
565 		config_byte = CB_CFIG_LOOPBACK_EXTERNAL;
566 		break;
567 	default:
568 		printk(KERN_NOTICE "e100: e100_config_loopback_mode: "
569 		       "Invalid argument 'mode': %d\n", mode);
570 		goto exit;
571 	}
572 
573 	if ((bdp->config[10] & CB_CFIG_LOOPBACK_MODE) != config_byte) {
574 
575 		bdp->config[10] &= (~CB_CFIG_LOOPBACK_MODE);
576 		bdp->config[10] |= config_byte;
577 		E100_CONFIG(bdp, 10);
578 		bc_changed = true;
579 	}
580 
581 exit:
582 	spin_unlock_bh(&(bdp->config_lock));
583 	return bc_changed;
584 }
585 unsigned char
e100_config_tcb_ext_enable(struct e100_private * bdp,unsigned char enable)586 e100_config_tcb_ext_enable(struct e100_private *bdp, unsigned char enable)
587 {
588         unsigned char bc_changed = false;
589 
590         spin_lock_bh(&(bdp->config_lock));
591 
592         if (enable) {
593                 if (bdp->config[6] & CB_CFIG_EXT_TCB_DIS) {
594 
595                         bdp->config[6] &= (~CB_CFIG_EXT_TCB_DIS);
596                         E100_CONFIG(bdp, 6);
597                         bc_changed = true;
598                 }
599 
600         } else {
601                 if (!(bdp->config[6] & CB_CFIG_EXT_TCB_DIS)) {
602 
603                         bdp->config[6] |= CB_CFIG_EXT_TCB_DIS;
604                         E100_CONFIG(bdp, 6);
605                         bc_changed = true;
606                 }
607         }
608         spin_unlock_bh(&(bdp->config_lock));
609 
610         return bc_changed;
611 }
612 unsigned char
e100_config_dynamic_tbd(struct e100_private * bdp,unsigned char enable)613 e100_config_dynamic_tbd(struct e100_private *bdp, unsigned char enable)
614 {
615         unsigned char bc_changed = false;
616 
617         spin_lock_bh(&(bdp->config_lock));
618 
619         if (enable) {
620                 if (!(bdp->config[7] & CB_CFIG_DYNTBD_EN)) {
621 
622                         bdp->config[7] |= CB_CFIG_DYNTBD_EN;
623                         E100_CONFIG(bdp, 7);
624                         bc_changed = true;
625                 }
626 
627         } else {
628                 if (bdp->config[7] & CB_CFIG_DYNTBD_EN) {
629 
630                         bdp->config[7] &= (~CB_CFIG_DYNTBD_EN);
631                         E100_CONFIG(bdp, 7);
632                         bc_changed = true;
633                 }
634         }
635         spin_unlock_bh(&(bdp->config_lock));
636 
637         return bc_changed;
638 }
639 
640