Skip to content

Commit

Permalink
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/k…
Browse files Browse the repository at this point in the history
…ernel/git/jgarzik/netdev-2.6

* 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzik/netdev-2.6: (31 commits)
  Replace cpmac fix
  dl2k: the rest
  dl2k: MSCR, MSSR, ESR, PHY_SCR fixes
  dl2k: BMSR fixes
  dl2k: ANAR, ANLPAR fixes
  dl2k: BMCR_t fixes
  3c574, 3c515 bitfields abuse
  sbni endian fixes
  wan/lmc bitfields fixes
  dscc4 endian fixes
  S2io: Fixed synchronization between scheduling of napi with card reset and close
  atl1: fix frame length bug
  Documentation: add a guideline for hard_start_xmit method
  Revert "sky2: remove check for PCI wakeup setting from BIOS"
  e1000e Kconfig: remove ref to nonexistant docs
  bonding: Don't hold lock when calling rtnl_unlock
  bonding: fix lock ordering for rtnl and bonding_rwsem
  bonding: Fix up parameter parsing
  bonding: release slaves when master removed via sysfs
  bonding: fix locking during alb failover and slave removal
  ...
  • Loading branch information
Linus Torvalds committed Jan 18, 2008
2 parents c9daa27 + ba596a0 commit 8b2d183
Show file tree
Hide file tree
Showing 24 changed files with 387 additions and 482 deletions.
5 changes: 4 additions & 1 deletion Documentation/networking/driver.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,10 @@ Transmit path guidelines:
2) Do not forget to update netdev->trans_start to jiffies after
each new tx packet is given to the hardware.

3) Do not forget that once you return 0 from your hard_start_xmit
3) A hard_start_xmit method must not modify the shared parts of a
cloned SKB.

4) Do not forget that once you return 0 from your hard_start_xmit
method, it is your driver's responsibility to free up the SKB
and in some finite amount of time.

Expand Down
60 changes: 31 additions & 29 deletions drivers/net/3c515.c
Original file line number Diff line number Diff line change
Expand Up @@ -243,14 +243,16 @@ enum eeprom_offset {
enum Window3 { /* Window 3: MAC/config bits. */
Wn3_Config = 0, Wn3_MAC_Ctrl = 6, Wn3_Options = 8,
};
union wn3_config {
int i;
struct w3_config_fields {
unsigned int ram_size:3, ram_width:1, ram_speed:2, rom_size:2;
int pad8:8;
unsigned int ram_split:2, pad18:2, xcvr:3, pad21:1, autoselect:1;
int pad24:7;
} u;
enum wn3_config {
Ram_size = 7,
Ram_width = 8,
Ram_speed = 0x30,
Rom_size = 0xc0,
Ram_split_shift = 16,
Ram_split = 3 << Ram_split_shift,
Xcvr_shift = 20,
Xcvr = 7 << Xcvr_shift,
Autoselect = 0x1000000,
};

enum Window4 {
Expand Down Expand Up @@ -614,7 +616,7 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,
/* Read the station address from the EEPROM. */
EL3WINDOW(0);
for (i = 0; i < 0x18; i++) {
short *phys_addr = (short *) dev->dev_addr;
__be16 *phys_addr = (__be16 *) dev->dev_addr;
int timer;
outw(EEPROM_Read + i, ioaddr + Wn0EepromCmd);
/* Pause for at least 162 us. for the read to take place. */
Expand Down Expand Up @@ -646,22 +648,22 @@ static int corkscrew_setup(struct net_device *dev, int ioaddr,

{
char *ram_split[] = { "5:3", "3:1", "1:1", "3:5" };
union wn3_config config;
__u32 config;
EL3WINDOW(3);
vp->available_media = inw(ioaddr + Wn3_Options);
config.i = inl(ioaddr + Wn3_Config);
config = inl(ioaddr + Wn3_Config);
if (corkscrew_debug > 1)
printk(KERN_INFO " Internal config register is %4.4x, transceivers %#x.\n",
config.i, inw(ioaddr + Wn3_Options));
config, inw(ioaddr + Wn3_Options));
printk(KERN_INFO " %dK %s-wide RAM %s Rx:Tx split, %s%s interface.\n",
8 << config.u.ram_size,
config.u.ram_width ? "word" : "byte",
ram_split[config.u.ram_split],
config.u.autoselect ? "autoselect/" : "",
media_tbl[config.u.xcvr].name);
dev->if_port = config.u.xcvr;
vp->default_media = config.u.xcvr;
vp->autoselect = config.u.autoselect;
8 << config & Ram_size,
config & Ram_width ? "word" : "byte",
ram_split[(config & Ram_split) >> Ram_split_shift],
config & Autoselect ? "autoselect/" : "",
media_tbl[(config & Xcvr) >> Xcvr_shift].name);
vp->default_media = (config & Xcvr) >> Xcvr_shift;
vp->autoselect = config & Autoselect ? 1 : 0;
dev->if_port = vp->default_media;
}
if (vp->media_override != 7) {
printk(KERN_INFO " Media override to transceiver type %d (%s).\n",
Expand Down Expand Up @@ -694,14 +696,14 @@ static int corkscrew_open(struct net_device *dev)
{
int ioaddr = dev->base_addr;
struct corkscrew_private *vp = netdev_priv(dev);
union wn3_config config;
__u32 config;
int i;

/* Before initializing select the active media port. */
EL3WINDOW(3);
if (vp->full_duplex)
outb(0x20, ioaddr + Wn3_MAC_Ctrl); /* Set the full-duplex bit. */
config.i = inl(ioaddr + Wn3_Config);
config = inl(ioaddr + Wn3_Config);

if (vp->media_override != 7) {
if (corkscrew_debug > 1)
Expand All @@ -727,12 +729,12 @@ static int corkscrew_open(struct net_device *dev)
} else
dev->if_port = vp->default_media;

config.u.xcvr = dev->if_port;
outl(config.i, ioaddr + Wn3_Config);
config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
outl(config, ioaddr + Wn3_Config);

if (corkscrew_debug > 1) {
printk("%s: corkscrew_open() InternalConfig %8.8x.\n",
dev->name, config.i);
dev->name, config);
}

outw(TxReset, ioaddr + EL3_CMD);
Expand Down Expand Up @@ -901,7 +903,7 @@ static void corkscrew_timer(unsigned long data)
ok = 1;
}
if (!ok) {
union wn3_config config;
__u32 config;

do {
dev->if_port =
Expand All @@ -928,9 +930,9 @@ static void corkscrew_timer(unsigned long data)
ioaddr + Wn4_Media);

EL3WINDOW(3);
config.i = inl(ioaddr + Wn3_Config);
config.u.xcvr = dev->if_port;
outl(config.i, ioaddr + Wn3_Config);
config = inl(ioaddr + Wn3_Config);
config = (config & ~Xcvr) | (dev->if_port << Xcvr_shift);
outl(config, ioaddr + Wn3_Config);

outw(dev->if_port == 3 ? StartCoax : StopCoax,
ioaddr + EL3_CMD);
Expand Down
3 changes: 0 additions & 3 deletions drivers/net/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1976,9 +1976,6 @@ config E1000E

<http://support.intel.com>

More specific information on configuring the driver is in
<file:Documentation/networking/e1000e.txt>.

To compile this driver as a module, choose M here. The module
will be called e1000e.

Expand Down
8 changes: 4 additions & 4 deletions drivers/net/atl1/atl1_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ static int __devinit atl1_sw_init(struct atl1_adapter *adapter)
struct atl1_hw *hw = &adapter->hw;
struct net_device *netdev = adapter->netdev;

hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
hw->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;

adapter->wol = 0;
Expand Down Expand Up @@ -688,7 +688,7 @@ static int atl1_change_mtu(struct net_device *netdev, int new_mtu)
{
struct atl1_adapter *adapter = netdev_priv(netdev);
int old_mtu = netdev->mtu;
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;

if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) ||
(max_frame > MAX_JUMBO_FRAME_SIZE)) {
Expand Down Expand Up @@ -853,8 +853,8 @@ static u32 atl1_configure(struct atl1_adapter *adapter)
/* set Interrupt Clear Timer */
iowrite16(adapter->ict, hw->hw_addr + REG_CMBDISDMA_TIMER);

/* set MTU, 4 : VLAN */
iowrite32(hw->max_frame_size + 4, hw->hw_addr + REG_MTU);
/* set max frame size hw will accept */
iowrite32(hw->max_frame_size, hw->hw_addr + REG_MTU);

/* jumbo size & rrd retirement timer */
value = (((u32) hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK)
Expand Down
23 changes: 14 additions & 9 deletions drivers/net/bonding/bond_alb.c
Original file line number Diff line number Diff line change
Expand Up @@ -979,14 +979,16 @@ static void alb_swap_mac_addr(struct bonding *bond, struct slave *slave1, struct
/*
* Send learning packets after MAC address swap.
*
* Called with RTNL and bond->lock held for read.
* Called with RTNL and no other locks
*/
static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1,
struct slave *slave2)
{
int slaves_state_differ = (SLAVE_IS_OK(slave1) != SLAVE_IS_OK(slave2));
struct slave *disabled_slave = NULL;

ASSERT_RTNL();

/* fasten the change in the switch */
if (SLAVE_IS_OK(slave1)) {
alb_send_learning_packets(slave1, slave1->dev->dev_addr);
Expand Down Expand Up @@ -1031,7 +1033,7 @@ static void alb_fasten_mac_swap(struct bonding *bond, struct slave *slave1,
* a slave that has @slave's permanet address as its current address.
* We'll make sure that that slave no longer uses @slave's permanent address.
*
* Caller must hold bond lock
* Caller must hold RTNL and no other locks
*/
static void alb_change_hw_addr_on_detach(struct bonding *bond, struct slave *slave)
{
Expand Down Expand Up @@ -1542,7 +1544,12 @@ int bond_alb_init_slave(struct bonding *bond, struct slave *slave)
return 0;
}

/* Caller must hold bond lock for write */
/*
* Remove slave from tlb and rlb hash tables, and fix up MAC addresses
* if necessary.
*
* Caller must hold RTNL and no other locks
*/
void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave)
{
if (bond->slave_cnt > 1) {
Expand Down Expand Up @@ -1601,9 +1608,6 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
struct slave *swap_slave;
int i;

if (new_slave)
ASSERT_RTNL();

if (bond->curr_active_slave == new_slave) {
return;
}
Expand Down Expand Up @@ -1649,6 +1653,8 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
write_unlock_bh(&bond->curr_slave_lock);
read_unlock(&bond->lock);

ASSERT_RTNL();

/* curr_active_slave must be set before calling alb_swap_mac_addr */
if (swap_slave) {
/* swap mac address */
Expand All @@ -1659,12 +1665,11 @@ void bond_alb_handle_active_change(struct bonding *bond, struct slave *new_slave
bond->alb_info.rlb_enabled);
}

read_lock(&bond->lock);

if (swap_slave) {
alb_fasten_mac_swap(bond, swap_slave, new_slave);
read_lock(&bond->lock);
} else {
/* fasten bond mac on new current slave */
read_lock(&bond->lock);
alb_send_learning_packets(new_slave, bond->dev->dev_addr);
}

Expand Down
64 changes: 47 additions & 17 deletions drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1746,7 +1746,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
* has been cleared (if our_slave == old_current),
* but before a new active slave is selected.
*/
write_unlock_bh(&bond->lock);
bond_alb_deinit_slave(bond, slave);
write_lock_bh(&bond->lock);
}

if (oldcurrent == slave) {
Expand Down Expand Up @@ -1905,6 +1907,12 @@ static int bond_release_all(struct net_device *bond_dev)
slave_dev = slave->dev;
bond_detach_slave(bond, slave);

/* now that the slave is detached, unlock and perform
* all the undo steps that should not be called from
* within a lock.
*/
write_unlock_bh(&bond->lock);

if ((bond->params.mode == BOND_MODE_TLB) ||
(bond->params.mode == BOND_MODE_ALB)) {
/* must be called only after the slave
Expand All @@ -1915,12 +1923,6 @@ static int bond_release_all(struct net_device *bond_dev)

bond_compute_features(bond);

/* now that the slave is detached, unlock and perform
* all the undo steps that should not be called from
* within a lock.
*/
write_unlock_bh(&bond->lock);

bond_destroy_slave_symlinks(bond_dev, slave_dev);
bond_del_vlans_from_slave(bond, slave_dev);

Expand Down Expand Up @@ -2384,7 +2386,9 @@ void bond_mii_monitor(struct work_struct *work)
rtnl_lock();
read_lock(&bond->lock);
__bond_mii_monitor(bond, 1);
rtnl_unlock();
read_unlock(&bond->lock);
rtnl_unlock(); /* might sleep, hold no other locks */
read_lock(&bond->lock);
}

delay = ((bond->params.miimon * HZ) / 1000) ? : 1;
Expand Down Expand Up @@ -3399,9 +3403,7 @@ static int bond_master_netdev_event(unsigned long event, struct net_device *bond
case NETDEV_CHANGENAME:
return bond_event_changename(event_bond);
case NETDEV_UNREGISTER:
/*
* TODO: remove a bond from the list?
*/
bond_release_all(event_bond->dev);
break;
default:
break;
Expand Down Expand Up @@ -4540,18 +4542,27 @@ static void bond_free_all(void)

/*
* Convert string input module parms. Accept either the
* number of the mode or its string name.
* number of the mode or its string name. A bit complicated because
* some mode names are substrings of other names, and calls from sysfs
* may have whitespace in the name (trailing newlines, for example).
*/
int bond_parse_parm(char *mode_arg, struct bond_parm_tbl *tbl)
int bond_parse_parm(const char *buf, struct bond_parm_tbl *tbl)
{
int i;
int mode = -1, i, rv;
char modestr[BOND_MAX_MODENAME_LEN + 1] = { 0, };

rv = sscanf(buf, "%d", &mode);
if (!rv) {
rv = sscanf(buf, "%20s", modestr);
if (!rv)
return -1;
}

for (i = 0; tbl[i].modename; i++) {
if ((isdigit(*mode_arg) &&
tbl[i].mode == simple_strtol(mode_arg, NULL, 0)) ||
(strcmp(mode_arg, tbl[i].modename) == 0)) {
if (mode == tbl[i].mode)
return tbl[i].mode;
if (strcmp(modestr, tbl[i].modename) == 0)
return tbl[i].mode;
}
}

return -1;
Expand Down Expand Up @@ -4865,9 +4876,22 @@ static struct lock_class_key bonding_netdev_xmit_lock_key;
int bond_create(char *name, struct bond_params *params, struct bonding **newbond)
{
struct net_device *bond_dev;
struct bonding *bond, *nxt;
int res;

rtnl_lock();
down_write(&bonding_rwsem);

/* Check to see if the bond already exists. */
list_for_each_entry_safe(bond, nxt, &bond_dev_list, bond_list)
if (strnicmp(bond->dev->name, name, IFNAMSIZ) == 0) {
printk(KERN_ERR DRV_NAME
": cannot add bond %s; it already exists\n",
name);
res = -EPERM;
goto out_rtnl;
}

bond_dev = alloc_netdev(sizeof(struct bonding), name ? name : "",
ether_setup);
if (!bond_dev) {
Expand Down Expand Up @@ -4906,10 +4930,12 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond

netif_carrier_off(bond_dev);

up_write(&bonding_rwsem);
rtnl_unlock(); /* allows sysfs registration of net device */
res = bond_create_sysfs_entry(bond_dev->priv);
if (res < 0) {
rtnl_lock();
down_write(&bonding_rwsem);
goto out_bond;
}

Expand All @@ -4920,6 +4946,7 @@ int bond_create(char *name, struct bond_params *params, struct bonding **newbond
out_netdev:
free_netdev(bond_dev);
out_rtnl:
up_write(&bonding_rwsem);
rtnl_unlock();
return res;
}
Expand All @@ -4940,6 +4967,9 @@ static int __init bonding_init(void)
#ifdef CONFIG_PROC_FS
bond_create_proc_dir();
#endif

init_rwsem(&bonding_rwsem);

for (i = 0; i < max_bonds; i++) {
res = bond_create(NULL, &bonding_defaults, NULL);
if (res)
Expand Down
Loading

0 comments on commit 8b2d183

Please sign in to comment.