Commit b78e01cf authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/davem/net-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents d8d1f77e 6b63219c
...@@ -60,8 +60,8 @@ ...@@ -60,8 +60,8 @@
#define DRV_MODULE_NAME "tg3" #define DRV_MODULE_NAME "tg3"
#define PFX DRV_MODULE_NAME ": " #define PFX DRV_MODULE_NAME ": "
#define DRV_MODULE_VERSION "3.22" #define DRV_MODULE_VERSION "3.23"
#define DRV_MODULE_RELDATE "February 11, 2005" #define DRV_MODULE_RELDATE "February 15, 2005"
#define TG3_DEF_MAC_MODE 0 #define TG3_DEF_MAC_MODE 0
#define TG3_DEF_RX_MODE 0 #define TG3_DEF_RX_MODE 0
...@@ -591,9 +591,10 @@ static void tg3_phy_set_wirespeed(struct tg3 *tp) ...@@ -591,9 +591,10 @@ static void tg3_phy_set_wirespeed(struct tg3 *tp)
if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED) if (tp->tg3_flags2 & TG3_FLG2_NO_ETH_WIRE_SPEED)
return; return;
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007); if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x7007) &&
tg3_readphy(tp, MII_TG3_AUX_CTRL, &val); !tg3_readphy(tp, MII_TG3_AUX_CTRL, &val))
tg3_writephy(tp, MII_TG3_AUX_CTRL, (val | (1 << 15) | (1 << 4))); tg3_writephy(tp, MII_TG3_AUX_CTRL,
(val | (1 << 15) | (1 << 4)));
} }
static int tg3_bmcr_reset(struct tg3 *tp) static int tg3_bmcr_reset(struct tg3 *tp)
...@@ -634,10 +635,11 @@ static int tg3_wait_macro_done(struct tg3 *tp) ...@@ -634,10 +635,11 @@ static int tg3_wait_macro_done(struct tg3 *tp)
while (limit--) { while (limit--) {
u32 tmp32; u32 tmp32;
tg3_readphy(tp, 0x16, &tmp32); if (!tg3_readphy(tp, 0x16, &tmp32)) {
if ((tmp32 & 0x1000) == 0) if ((tmp32 & 0x1000) == 0)
break; break;
} }
}
if (limit <= 0) if (limit <= 0)
return -EBUSY; return -EBUSY;
...@@ -688,9 +690,9 @@ static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp) ...@@ -688,9 +690,9 @@ static int tg3_phy_write_and_check_testpat(struct tg3 *tp, int *resetp)
for (i = 0; i < 6; i += 2) { for (i = 0; i < 6; i += 2) {
u32 low, high; u32 low, high;
tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low); if (tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &low) ||
tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high); tg3_readphy(tp, MII_TG3_DSP_RW_PORT, &high) ||
if (tg3_wait_macro_done(tp)) { tg3_wait_macro_done(tp)) {
*resetp = 1; *resetp = 1;
return -EBUSY; return -EBUSY;
} }
...@@ -746,7 +748,9 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) ...@@ -746,7 +748,9 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
} }
/* Disable transmitter and interrupt. */ /* Disable transmitter and interrupt. */
tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32); if (tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32))
continue;
reg32 |= 0x3000; reg32 |= 0x3000;
tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
...@@ -755,7 +759,9 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) ...@@ -755,7 +759,9 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
BMCR_FULLDPLX | TG3_BMCR_SPEED1000); BMCR_FULLDPLX | TG3_BMCR_SPEED1000);
/* Set to master mode. */ /* Set to master mode. */
tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig); if (tg3_readphy(tp, MII_TG3_CTRL, &phy9_orig))
continue;
tg3_writephy(tp, MII_TG3_CTRL, tg3_writephy(tp, MII_TG3_CTRL,
(MII_TG3_CTRL_AS_MASTER | (MII_TG3_CTRL_AS_MASTER |
MII_TG3_CTRL_ENABLE_AS_MASTER)); MII_TG3_CTRL_ENABLE_AS_MASTER));
...@@ -793,9 +799,11 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) ...@@ -793,9 +799,11 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp)
tg3_writephy(tp, MII_TG3_CTRL, phy9_orig); tg3_writephy(tp, MII_TG3_CTRL, phy9_orig);
tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32); if (!tg3_readphy(tp, MII_TG3_EXT_CTRL, &reg32)) {
reg32 &= ~0x3000; reg32 &= ~0x3000;
tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32); tg3_writephy(tp, MII_TG3_EXT_CTRL, reg32);
} else if (!err)
err = -EBUSY;
return err; return err;
} }
...@@ -859,8 +867,8 @@ static int tg3_phy_reset(struct tg3 *tp) ...@@ -859,8 +867,8 @@ static int tg3_phy_reset(struct tg3 *tp)
u32 phy_reg; u32 phy_reg;
/* Set bit 14 with read-modify-write to preserve other bits */ /* Set bit 14 with read-modify-write to preserve other bits */
tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007); if (!tg3_writephy(tp, MII_TG3_AUX_CTRL, 0x0007) &&
tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg); !tg3_readphy(tp, MII_TG3_AUX_CTRL, &phy_reg))
tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000); tg3_writephy(tp, MII_TG3_AUX_CTRL, phy_reg | 0x4000);
} }
tg3_phy_set_wirespeed(tp); tg3_phy_set_wirespeed(tp);
...@@ -1244,7 +1252,7 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8 ...@@ -1244,7 +1252,7 @@ static void tg3_aux_stat_to_speed_duplex(struct tg3 *tp, u32 val, u16 *speed, u8
}; };
} }
static int tg3_phy_copper_begin(struct tg3 *tp) static void tg3_phy_copper_begin(struct tg3 *tp)
{ {
u32 new_adv; u32 new_adv;
int i; int i;
...@@ -1359,15 +1367,16 @@ static int tg3_phy_copper_begin(struct tg3 *tp) ...@@ -1359,15 +1367,16 @@ static int tg3_phy_copper_begin(struct tg3 *tp)
if (tp->link_config.duplex == DUPLEX_FULL) if (tp->link_config.duplex == DUPLEX_FULL)
bmcr |= BMCR_FULLDPLX; bmcr |= BMCR_FULLDPLX;
tg3_readphy(tp, MII_BMCR, &orig_bmcr); if (!tg3_readphy(tp, MII_BMCR, &orig_bmcr) &&
if (bmcr != orig_bmcr) { (bmcr != orig_bmcr)) {
tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK); tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK);
for (i = 0; i < 1500; i++) { for (i = 0; i < 1500; i++) {
u32 tmp; u32 tmp;
udelay(10); udelay(10);
tg3_readphy(tp, MII_BMSR, &tmp); if (tg3_readphy(tp, MII_BMSR, &tmp) ||
tg3_readphy(tp, MII_BMSR, &tmp); tg3_readphy(tp, MII_BMSR, &tmp))
continue;
if (!(tmp & BMSR_LSTATUS)) { if (!(tmp & BMSR_LSTATUS)) {
udelay(40); udelay(40);
break; break;
...@@ -1380,8 +1389,6 @@ static int tg3_phy_copper_begin(struct tg3 *tp) ...@@ -1380,8 +1389,6 @@ static int tg3_phy_copper_begin(struct tg3 *tp)
tg3_writephy(tp, MII_BMCR, tg3_writephy(tp, MII_BMCR,
BMCR_ANENABLE | BMCR_ANRESTART); BMCR_ANENABLE | BMCR_ANRESTART);
} }
return 0;
} }
static int tg3_init_5401phy_dsp(struct tg3 *tp) static int tg3_init_5401phy_dsp(struct tg3 *tp)
...@@ -1416,7 +1423,9 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp) ...@@ -1416,7 +1423,9 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp)
{ {
u32 adv_reg, all_mask; u32 adv_reg, all_mask;
tg3_readphy(tp, MII_ADVERTISE, &adv_reg); if (tg3_readphy(tp, MII_ADVERTISE, &adv_reg))
return 0;
all_mask = (ADVERTISE_10HALF | ADVERTISE_10FULL | all_mask = (ADVERTISE_10HALF | ADVERTISE_10FULL |
ADVERTISE_100HALF | ADVERTISE_100FULL); ADVERTISE_100HALF | ADVERTISE_100FULL);
if ((adv_reg & all_mask) != all_mask) if ((adv_reg & all_mask) != all_mask)
...@@ -1424,7 +1433,9 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp) ...@@ -1424,7 +1433,9 @@ static int tg3_copper_is_advertising_all(struct tg3 *tp)
if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) { if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) {
u32 tg3_ctrl; u32 tg3_ctrl;
tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl); if (tg3_readphy(tp, MII_TG3_CTRL, &tg3_ctrl))
return 0;
all_mask = (MII_TG3_CTRL_ADV_1000_HALF | all_mask = (MII_TG3_CTRL_ADV_1000_HALF |
MII_TG3_CTRL_ADV_1000_FULL); MII_TG3_CTRL_ADV_1000_FULL);
if ((tg3_ctrl & all_mask) != all_mask) if ((tg3_ctrl & all_mask) != all_mask)
...@@ -1464,8 +1475,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1464,8 +1475,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) && GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) &&
netif_carrier_ok(tp->dev)) { netif_carrier_ok(tp->dev)) {
tg3_readphy(tp, MII_BMSR, &bmsr); tg3_readphy(tp, MII_BMSR, &bmsr);
tg3_readphy(tp, MII_BMSR, &bmsr); if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
if (!(bmsr & BMSR_LSTATUS)) !(bmsr & BMSR_LSTATUS))
force_reset = 1; force_reset = 1;
} }
if (force_reset) if (force_reset)
...@@ -1473,9 +1484,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1473,9 +1484,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) { if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) {
tg3_readphy(tp, MII_BMSR, &bmsr); tg3_readphy(tp, MII_BMSR, &bmsr);
tg3_readphy(tp, MII_BMSR, &bmsr); if (tg3_readphy(tp, MII_BMSR, &bmsr) ||
!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE))
if (!(tp->tg3_flags & TG3_FLAG_INIT_COMPLETE))
bmsr = 0; bmsr = 0;
if (!(bmsr & BMSR_LSTATUS)) { if (!(bmsr & BMSR_LSTATUS)) {
...@@ -1486,8 +1496,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1486,8 +1496,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
tg3_readphy(tp, MII_BMSR, &bmsr); tg3_readphy(tp, MII_BMSR, &bmsr);
for (i = 0; i < 1000; i++) { for (i = 0; i < 1000; i++) {
udelay(10); udelay(10);
tg3_readphy(tp, MII_BMSR, &bmsr); if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
if (bmsr & BMSR_LSTATUS) { (bmsr & BMSR_LSTATUS)) {
udelay(40); udelay(40);
break; break;
} }
...@@ -1549,8 +1559,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1549,8 +1559,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
bmsr = 0; bmsr = 0;
for (i = 0; i < 100; i++) { for (i = 0; i < 100; i++) {
tg3_readphy(tp, MII_BMSR, &bmsr); tg3_readphy(tp, MII_BMSR, &bmsr);
tg3_readphy(tp, MII_BMSR, &bmsr); if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
if (bmsr & BMSR_LSTATUS) (bmsr & BMSR_LSTATUS))
break; break;
udelay(40); udelay(40);
} }
...@@ -1561,8 +1571,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1561,8 +1571,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat);
for (i = 0; i < 2000; i++) { for (i = 0; i < 2000; i++) {
udelay(10); udelay(10);
tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat); if (!tg3_readphy(tp, MII_TG3_AUX_STAT, &aux_stat) &&
if (aux_stat) aux_stat)
break; break;
} }
...@@ -1573,7 +1583,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1573,7 +1583,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
bmcr = 0; bmcr = 0;
for (i = 0; i < 200; i++) { for (i = 0; i < 200; i++) {
tg3_readphy(tp, MII_BMCR, &bmcr); tg3_readphy(tp, MII_BMCR, &bmcr);
tg3_readphy(tp, MII_BMCR, &bmcr); if (tg3_readphy(tp, MII_BMCR, &bmcr))
continue;
if (bmcr && bmcr != 0x7fff) if (bmcr && bmcr != 0x7fff)
break; break;
udelay(10); udelay(10);
...@@ -1610,10 +1621,13 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1610,10 +1621,13 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
(tp->link_config.autoneg == AUTONEG_ENABLE)) { (tp->link_config.autoneg == AUTONEG_ENABLE)) {
u32 local_adv, remote_adv; u32 local_adv, remote_adv;
tg3_readphy(tp, MII_ADVERTISE, &local_adv); if (tg3_readphy(tp, MII_ADVERTISE, &local_adv))
local_adv = 0;
local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); local_adv &= (ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
tg3_readphy(tp, MII_LPA, &remote_adv); if (tg3_readphy(tp, MII_LPA, &remote_adv))
remote_adv = 0;
remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM); remote_adv &= (LPA_PAUSE_CAP | LPA_PAUSE_ASYM);
/* If we are not advertising full pause capability, /* If we are not advertising full pause capability,
...@@ -1632,8 +1646,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset) ...@@ -1632,8 +1646,8 @@ static int tg3_setup_copper_phy(struct tg3 *tp, int force_reset)
tg3_phy_copper_begin(tp); tg3_phy_copper_begin(tp);
tg3_readphy(tp, MII_BMSR, &tmp); tg3_readphy(tp, MII_BMSR, &tmp);
tg3_readphy(tp, MII_BMSR, &tmp); if (!tg3_readphy(tp, MII_BMSR, &tmp) &&
if (tmp & BMSR_LSTATUS) (tmp & BMSR_LSTATUS))
current_link_up = 1; current_link_up = 1;
} }
...@@ -5441,10 +5455,11 @@ static int tg3_reset_hw(struct tg3 *tp) ...@@ -5441,10 +5455,11 @@ static int tg3_reset_hw(struct tg3 *tp)
u32 tmp; u32 tmp;
/* Clear CRC stats. */ /* Clear CRC stats. */
tg3_readphy(tp, 0x1e, &tmp); if (!tg3_readphy(tp, 0x1e, &tmp)) {
tg3_writephy(tp, 0x1e, tmp | 0x8000); tg3_writephy(tp, 0x1e, tmp | 0x8000);
tg3_readphy(tp, 0x14, &tmp); tg3_readphy(tp, 0x14, &tmp);
} }
}
__tg3_set_rx_mode(tp->dev); __tg3_set_rx_mode(tp->dev);
...@@ -6033,9 +6048,11 @@ static unsigned long calc_crc_errors(struct tg3 *tp) ...@@ -6033,9 +6048,11 @@ static unsigned long calc_crc_errors(struct tg3 *tp)
u32 val; u32 val;
spin_lock_irqsave(&tp->lock, flags); spin_lock_irqsave(&tp->lock, flags);
tg3_readphy(tp, 0x1e, &val); if (!tg3_readphy(tp, 0x1e, &val)) {
tg3_writephy(tp, 0x1e, val | 0x8000); tg3_writephy(tp, 0x1e, val | 0x8000);
tg3_readphy(tp, 0x14, &val); tg3_readphy(tp, 0x14, &val);
} else
val = 0;
spin_unlock_irqrestore(&tp->lock, flags); spin_unlock_irqrestore(&tp->lock, flags);
tp->phy_crc_errors += val; tp->phy_crc_errors += val;
...@@ -6651,10 +6668,10 @@ static int tg3_nway_reset(struct net_device *dev) ...@@ -6651,10 +6668,10 @@ static int tg3_nway_reset(struct net_device *dev)
int r; int r;
spin_lock_irq(&tp->lock); spin_lock_irq(&tp->lock);
tg3_readphy(tp, MII_BMCR, &bmcr);
tg3_readphy(tp, MII_BMCR, &bmcr);
r = -EINVAL; r = -EINVAL;
if (bmcr & BMCR_ANENABLE) { tg3_readphy(tp, MII_BMCR, &bmcr);
if (!tg3_readphy(tp, MII_BMCR, &bmcr) &&
(bmcr & BMCR_ANENABLE)) {
tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART); tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART);
r = 0; r = 0;
} }
...@@ -7654,9 +7671,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp) ...@@ -7654,9 +7671,8 @@ static int __devinit tg3_phy_probe(struct tg3 *tp)
u32 bmsr, adv_reg, tg3_ctrl; u32 bmsr, adv_reg, tg3_ctrl;
tg3_readphy(tp, MII_BMSR, &bmsr); tg3_readphy(tp, MII_BMSR, &bmsr);
tg3_readphy(tp, MII_BMSR, &bmsr); if (!tg3_readphy(tp, MII_BMSR, &bmsr) &&
(bmsr & BMSR_LSTATUS))
if (bmsr & BMSR_LSTATUS)
goto skip_phy_reset; goto skip_phy_reset;
err = tg3_phy_reset(tp); err = tg3_phy_reset(tp);
......
...@@ -120,7 +120,7 @@ struct cmsghdr { ...@@ -120,7 +120,7 @@ struct cmsghdr {
* Now it always returns valid, not truncated ancillary object * Now it always returns valid, not truncated ancillary object
* HEADER. But caller still MUST check, that cmsg->cmsg_len is * HEADER. But caller still MUST check, that cmsg->cmsg_len is
* inside range, given by msg->msg_controllen before using * inside range, given by msg->msg_controllen before using
* ansillary object DATA. --ANK (980731) * ancillary object DATA. --ANK (980731)
*/ */
__KINLINE struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size, __KINLINE struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size,
......
...@@ -89,7 +89,8 @@ struct dst_ops ...@@ -89,7 +89,8 @@ struct dst_ops
int (*gc)(void); int (*gc)(void);
struct dst_entry * (*check)(struct dst_entry *, __u32 cookie); struct dst_entry * (*check)(struct dst_entry *, __u32 cookie);
void (*destroy)(struct dst_entry *); void (*destroy)(struct dst_entry *);
void (*ifdown)(struct dst_entry *, int how); void (*ifdown)(struct dst_entry *,
struct net_device *dev, int how);
struct dst_entry * (*negative_advice)(struct dst_entry *); struct dst_entry * (*negative_advice)(struct dst_entry *);
void (*link_failure)(struct sk_buff *); void (*link_failure)(struct sk_buff *);
void (*update_pmtu)(struct dst_entry *dst, u32 mtu); void (*update_pmtu)(struct dst_entry *dst, u32 mtu);
......
...@@ -220,17 +220,19 @@ struct dst_entry *dst_destroy(struct dst_entry * dst) ...@@ -220,17 +220,19 @@ struct dst_entry *dst_destroy(struct dst_entry * dst)
* *
* Commented and originally written by Alexey. * Commented and originally written by Alexey.
*/ */
static void dst_ifdown(struct dst_entry *dst, int unregister) static inline void dst_ifdown(struct dst_entry *dst, struct net_device *dev,
int unregister)
{ {
struct net_device *dev = dst->dev; if (dst->ops->ifdown)
dst->ops->ifdown(dst, dev, unregister);
if (dev != dst->dev)
return;
if (!unregister) { if (!unregister) {
dst->input = dst_discard_in; dst->input = dst_discard_in;
dst->output = dst_discard_out; dst->output = dst_discard_out;
} } else {
do {
if (unregister) {
dst->dev = &loopback_dev; dst->dev = &loopback_dev;
dev_hold(&loopback_dev); dev_hold(&loopback_dev);
dev_put(dev); dev_put(dev);
...@@ -240,11 +242,6 @@ static void dst_ifdown(struct dst_entry *dst, int unregister) ...@@ -240,11 +242,6 @@ static void dst_ifdown(struct dst_entry *dst, int unregister)
dev_hold(&loopback_dev); dev_hold(&loopback_dev);
} }
} }
if (dst->ops->ifdown)
dst->ops->ifdown(dst, unregister);
} while ((dst = dst->child) && dst->flags & DST_NOHASH &&
dst->dev == dev);
} }
static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr) static int dst_dev_event(struct notifier_block *this, unsigned long event, void *ptr)
...@@ -257,8 +254,7 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void ...@@ -257,8 +254,7 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, void
case NETDEV_DOWN: case NETDEV_DOWN:
spin_lock_bh(&dst_lock); spin_lock_bh(&dst_lock);
for (dst = dst_garbage_list; dst; dst = dst->next) { for (dst = dst_garbage_list; dst; dst = dst->next) {
if (dst->dev == dev) dst_ifdown(dst, dev, event != NETDEV_DOWN);
dst_ifdown(dst, event != NETDEV_DOWN);
} }
spin_unlock_bh(&dst_lock); spin_unlock_bh(&dst_lock);
break; break;
......
...@@ -138,7 +138,8 @@ static struct timer_list rt_secret_timer; ...@@ -138,7 +138,8 @@ static struct timer_list rt_secret_timer;
static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie); static struct dst_entry *ipv4_dst_check(struct dst_entry *dst, u32 cookie);
static void ipv4_dst_destroy(struct dst_entry *dst); static void ipv4_dst_destroy(struct dst_entry *dst);
static void ipv4_dst_ifdown(struct dst_entry *dst, int how); static void ipv4_dst_ifdown(struct dst_entry *dst,
struct net_device *dev, int how);
static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst); static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst);
static void ipv4_link_failure(struct sk_buff *skb); static void ipv4_link_failure(struct sk_buff *skb);
static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu); static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu);
...@@ -1342,11 +1343,12 @@ static void ipv4_dst_destroy(struct dst_entry *dst) ...@@ -1342,11 +1343,12 @@ static void ipv4_dst_destroy(struct dst_entry *dst)
} }
} }
static void ipv4_dst_ifdown(struct dst_entry *dst, int how) static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
int how)
{ {
struct rtable *rt = (struct rtable *) dst; struct rtable *rt = (struct rtable *) dst;
struct in_device *idev = rt->idev; struct in_device *idev = rt->idev;
if (idev && idev->dev != &loopback_dev) { if (dev != &loopback_dev && idev && idev->dev == dev) {
struct in_device *loopback_idev = in_dev_get(&loopback_dev); struct in_device *loopback_idev = in_dev_get(&loopback_dev);
if (loopback_idev) { if (loopback_idev) {
rt->idev = loopback_idev; rt->idev = loopback_idev;
......
...@@ -84,7 +84,8 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort); ...@@ -84,7 +84,8 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort);
static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie); static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie);
static struct dst_entry *ip6_negative_advice(struct dst_entry *); static struct dst_entry *ip6_negative_advice(struct dst_entry *);
static void ip6_dst_destroy(struct dst_entry *); static void ip6_dst_destroy(struct dst_entry *);
static void ip6_dst_ifdown(struct dst_entry *, int how); static void ip6_dst_ifdown(struct dst_entry *,
struct net_device *dev, int how);
static int ip6_dst_gc(void); static int ip6_dst_gc(void);
static int ip6_pkt_discard(struct sk_buff *skb); static int ip6_pkt_discard(struct sk_buff *skb);
...@@ -153,12 +154,13 @@ static void ip6_dst_destroy(struct dst_entry *dst) ...@@ -153,12 +154,13 @@ static void ip6_dst_destroy(struct dst_entry *dst)
} }
} }
static void ip6_dst_ifdown(struct dst_entry *dst, int how) static void ip6_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
int how)
{ {
struct rt6_info *rt = (struct rt6_info *)dst; struct rt6_info *rt = (struct rt6_info *)dst;
struct inet6_dev *idev = rt->rt6i_idev; struct inet6_dev *idev = rt->rt6i_idev;
if (idev != NULL && idev->dev != &loopback_dev) { if (dev != &loopback_dev && idev != NULL && idev->dev == dev) {
struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev); struct inet6_dev *loopback_idev = in6_dev_get(&loopback_dev);
if (loopback_idev != NULL) { if (loopback_idev != NULL) {
rt->rt6i_idev = loopback_idev; rt->rt6i_idev = loopback_idev;
......
...@@ -219,6 +219,7 @@ static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, ...@@ -219,6 +219,7 @@ static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
int noblock, int flags, int *addr_len) int noblock, int flags, int *addr_len)
{ {
struct ipv6_pinfo *np = inet6_sk(sk); struct ipv6_pinfo *np = inet6_sk(sk);
struct inet_sock *inet = inet_sk(sk);
struct sk_buff *skb; struct sk_buff *skb;
size_t copied; size_t copied;
int err; int err;
...@@ -268,21 +269,22 @@ static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk, ...@@ -268,21 +269,22 @@ static int udpv6_recvmsg(struct kiocb *iocb, struct sock *sk,
sin6->sin6_flowinfo = 0; sin6->sin6_flowinfo = 0;
sin6->sin6_scope_id = 0; sin6->sin6_scope_id = 0;
if (skb->protocol == htons(ETH_P_IP)) { if (skb->protocol == htons(ETH_P_IP))
struct inet_sock *inet = inet_sk(sk);
ipv6_addr_set(&sin6->sin6_addr, 0, 0, ipv6_addr_set(&sin6->sin6_addr, 0, 0,
htonl(0xffff), skb->nh.iph->saddr); htonl(0xffff), skb->nh.iph->saddr);
else {
ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
sin6->sin6_scope_id = IP6CB(skb)->iif;
}
}
if (skb->protocol == htons(ETH_P_IP)) {
if (inet->cmsg_flags) if (inet->cmsg_flags)
ip_cmsg_recv(msg, skb); ip_cmsg_recv(msg, skb);
} else { } else {
ipv6_addr_copy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr);
if (np->rxopt.all) if (np->rxopt.all)
datagram_recv_ctl(sk, msg, skb); datagram_recv_ctl(sk, msg, skb);
if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
sin6->sin6_scope_id = IP6CB(skb)->iif;
}
} }
err = copied; err = copied;
......
...@@ -46,7 +46,7 @@ ...@@ -46,7 +46,7 @@
int nr_rx_ip(struct sk_buff *skb, struct net_device *dev) int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
{ {
struct net_device_stats *stats = (struct net_device_stats *)dev->priv; struct net_device_stats *stats = netdev_priv(dev);
if (!netif_running(dev)) { if (!netif_running(dev)) {
stats->rx_errors++; stats->rx_errors++;
...@@ -73,7 +73,7 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev) ...@@ -73,7 +73,7 @@ int nr_rx_ip(struct sk_buff *skb, struct net_device *dev)
static int nr_rebuild_header(struct sk_buff *skb) static int nr_rebuild_header(struct sk_buff *skb)
{ {
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
struct net_device_stats *stats = (struct net_device_stats *)dev->priv; struct net_device_stats *stats = netdev_priv(dev);
struct sk_buff *skbn; struct sk_buff *skbn;
unsigned char *bp = skb->data; unsigned char *bp = skb->data;
int len; int len;
...@@ -186,7 +186,7 @@ static int nr_close(struct net_device *dev) ...@@ -186,7 +186,7 @@ static int nr_close(struct net_device *dev)
static int nr_xmit(struct sk_buff *skb, struct net_device *dev) static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct net_device_stats *stats = (struct net_device_stats *)dev->priv; struct net_device_stats *stats = netdev_priv(dev);
dev_kfree_skb(skb); dev_kfree_skb(skb);
stats->tx_errors++; stats->tx_errors++;
return 0; return 0;
...@@ -194,7 +194,7 @@ static int nr_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -194,7 +194,7 @@ static int nr_xmit(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *nr_get_stats(struct net_device *dev) static struct net_device_stats *nr_get_stats(struct net_device *dev)
{ {
return (struct net_device_stats *)dev->priv; return netdev_priv(dev);
} }
void nr_setup(struct net_device *dev) void nr_setup(struct net_device *dev)
......
...@@ -57,7 +57,7 @@ static int rose_header(struct sk_buff *skb, struct net_device *dev, unsigned sho ...@@ -57,7 +57,7 @@ static int rose_header(struct sk_buff *skb, struct net_device *dev, unsigned sho
static int rose_rebuild_header(struct sk_buff *skb) static int rose_rebuild_header(struct sk_buff *skb)
{ {
struct net_device *dev = skb->dev; struct net_device *dev = skb->dev;
struct net_device_stats *stats = (struct net_device_stats *)dev->priv; struct net_device_stats *stats = netdev_priv(dev);
unsigned char *bp = (unsigned char *)skb->data; unsigned char *bp = (unsigned char *)skb->data;
struct sk_buff *skbn; struct sk_buff *skbn;
...@@ -117,7 +117,7 @@ static int rose_close(struct net_device *dev) ...@@ -117,7 +117,7 @@ static int rose_close(struct net_device *dev)
static int rose_xmit(struct sk_buff *skb, struct net_device *dev) static int rose_xmit(struct sk_buff *skb, struct net_device *dev)
{ {
struct net_device_stats *stats = (struct net_device_stats *)dev->priv; struct net_device_stats *stats = netdev_priv(dev);
if (!netif_running(dev)) { if (!netif_running(dev)) {
printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n"); printk(KERN_ERR "ROSE: rose_xmit - called when iface is down\n");
...@@ -130,7 +130,7 @@ static int rose_xmit(struct sk_buff *skb, struct net_device *dev) ...@@ -130,7 +130,7 @@ static int rose_xmit(struct sk_buff *skb, struct net_device *dev)
static struct net_device_stats *rose_get_stats(struct net_device *dev) static struct net_device_stats *rose_get_stats(struct net_device *dev)
{ {
return (struct net_device_stats *)dev->priv; return netdev_priv(dev);
} }
void rose_setup(struct net_device *dev) void rose_setup(struct net_device *dev)
......
...@@ -1043,6 +1043,19 @@ static void xfrm_dst_destroy(struct dst_entry *dst) ...@@ -1043,6 +1043,19 @@ static void xfrm_dst_destroy(struct dst_entry *dst)
dst->xfrm = NULL; dst->xfrm = NULL;
} }
static void xfrm_dst_ifdown(struct dst_entry *dst, struct net_device *dev,
int unregister)
{
if (!unregister)
return;
while ((dst = dst->child) && dst->xfrm && dst->dev == dev) {
dst->dev = &loopback_dev;
dev_hold(&loopback_dev);
dev_put(dev);
}
}
static void xfrm_link_failure(struct sk_buff *skb) static void xfrm_link_failure(struct sk_buff *skb)
{ {
/* Impossible. Such dst must be popped before reaches point of failure. */ /* Impossible. Such dst must be popped before reaches point of failure. */
...@@ -1166,6 +1179,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) ...@@ -1166,6 +1179,8 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo)
dst_ops->check = xfrm_dst_check; dst_ops->check = xfrm_dst_check;
if (likely(dst_ops->destroy == NULL)) if (likely(dst_ops->destroy == NULL))
dst_ops->destroy = xfrm_dst_destroy; dst_ops->destroy = xfrm_dst_destroy;
if (likely(dst_ops->ifdown == NULL))
dst_ops->ifdown = xfrm_dst_ifdown;
if (likely(dst_ops->negative_advice == NULL)) if (likely(dst_ops->negative_advice == NULL))
dst_ops->negative_advice = xfrm_negative_advice; dst_ops->negative_advice = xfrm_negative_advice;
if (likely(dst_ops->link_failure == NULL)) if (likely(dst_ops->link_failure == NULL))
...@@ -1198,6 +1213,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) ...@@ -1198,6 +1213,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo)
dst_ops->kmem_cachep = NULL; dst_ops->kmem_cachep = NULL;
dst_ops->check = NULL; dst_ops->check = NULL;
dst_ops->destroy = NULL; dst_ops->destroy = NULL;
dst_ops->ifdown = NULL;
dst_ops->negative_advice = NULL; dst_ops->negative_advice = NULL;
dst_ops->link_failure = NULL; dst_ops->link_failure = NULL;
dst_ops->get_mss = NULL; dst_ops->get_mss = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment