diff --git a/MAINTAINERS b/MAINTAINERS index bd10b2af2223..92d696874965 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1899,6 +1899,12 @@ M: James.Bottomley@HansenPartnership.com L: linux-scsi@vger.kernel.org S: Maintained +NETEM NETWORK EMULATOR +P: Stephen Hemminger +M: shemminger@osdl.org +L: netem@osdl.org +S: Maintained + NETFILTER/IPTABLES/IPCHAINS P: Rusty Russell P: Marc Boucher diff --git a/Makefile b/Makefile index 3494c17c9fb9..435d209f42d8 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 17 -EXTRAVERSION =-rc4 -NAME=Sliding Snow Leopard +EXTRAVERSION =-rc5 +NAME=Lordi Rules # *DOCUMENTATION* # To see a list of typical targets execute "make help" diff --git a/arch/i386/kernel/syscall_table.S b/arch/i386/kernel/syscall_table.S index f48bef15b4f0..af56987f69b0 100644 --- a/arch/i386/kernel/syscall_table.S +++ b/arch/i386/kernel/syscall_table.S @@ -315,3 +315,4 @@ ENTRY(sys_call_table) .long sys_splice .long sys_sync_file_range .long sys_tee /* 315 */ + .long sys_vmsplice diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c index 4d15e396655c..b9200fb07815 100644 --- a/arch/powerpc/platforms/powermac/setup.c +++ b/arch/powerpc/platforms/powermac/setup.c @@ -463,11 +463,23 @@ static int pmac_pm_finish(suspend_state_t state) return 0; } +static int pmac_pm_valid(suspend_state_t state) +{ + switch (state) { + case PM_SUSPEND_DISK: + return 1; + /* can't do any other states via generic mechanism yet */ + default: + return 0; + } +} + static struct pm_ops pmac_pm_ops = { .pm_disk_mode = PM_DISK_SHUTDOWN, .prepare = pmac_pm_prepare, .enter = pmac_pm_enter, .finish = pmac_pm_finish, + .valid = pmac_pm_valid, }; #endif /* CONFIG_SOFTWARE_SUSPEND */ diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index ce19ad4e92ec..2a6c6efb6865 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -272,7 +272,7 @@ static inline void stop_hz_timer(void) next = next_timer_interrupt(); do { seq = read_seqbegin_irqsave(&xtime_lock, flags); - timer = (__u64 next) - (__u64 jiffies) + jiffies_64; + timer = ((__u64) next) - ((__u64) jiffies) + jiffies_64; } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); todval = -1ULL; /* Be careful about overflows. */ diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index f621168f38ae..8ea70625f7ea 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -457,10 +457,6 @@ static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, } vendor = ioread32(chip->vendor.iobase + TPM_DID_VID(0)); - if ((vendor & 0xFFFF) == 0xFFFF) { - rc = -ENODEV; - goto out_err; - } /* Default timeouts */ chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); diff --git a/drivers/i2c/busses/scx200_acb.c b/drivers/i2c/busses/scx200_acb.c index a140e4536a4e..766cc969c4d0 100644 --- a/drivers/i2c/busses/scx200_acb.c +++ b/drivers/i2c/busses/scx200_acb.c @@ -491,7 +491,7 @@ static struct pci_device_id divil_pci[] = { #define MSR_LBAR_SMB 0x5140000B -static int scx200_add_cs553x(void) +static __init int scx200_add_cs553x(void) { u32 low, hi; u32 smb_base; diff --git a/drivers/infiniband/hw/ipath/ipath_driver.c b/drivers/infiniband/hw/ipath/ipath_driver.c index 3697edafd6d2..dddcdae736ac 100644 --- a/drivers/infiniband/hw/ipath/ipath_driver.c +++ b/drivers/infiniband/hw/ipath/ipath_driver.c @@ -1905,19 +1905,19 @@ static void __exit infinipath_cleanup(void) } else ipath_dbg("irq is 0, not doing free_irq " "for unit %u\n", dd->ipath_unit); + + /* + * we check for NULL here, because it's outside + * the kregbase check, and we need to call it + * after the free_irq. Thus it's possible that + * the function pointers were never initialized. + */ + if (dd->ipath_f_cleanup) + /* clean up chip-specific stuff */ + dd->ipath_f_cleanup(dd); + dd->pcidev = NULL; } - - /* - * we check for NULL here, because it's outside the kregbase - * check, and we need to call it after the free_irq. Thus - * it's possible that the function pointers were never - * initialized. - */ - if (dd->ipath_f_cleanup) - /* clean up chip-specific stuff */ - dd->ipath_f_cleanup(dd); - spin_lock_irqsave(&ipath_devs_lock, flags); } diff --git a/drivers/infiniband/hw/ipath/ipath_eeprom.c b/drivers/infiniband/hw/ipath/ipath_eeprom.c index f11a900e8cd7..a2f1ceafcca9 100644 --- a/drivers/infiniband/hw/ipath/ipath_eeprom.c +++ b/drivers/infiniband/hw/ipath/ipath_eeprom.c @@ -505,11 +505,10 @@ static u8 flash_csum(struct ipath_flash *ifp, int adjust) * ipath_get_guid - get the GUID from the i2c device * @dd: the infinipath device * - * When we add the multi-chip support, we will probably have to add - * the ability to use the number of guids field, and get the guid from - * the first chip's flash, to use for all of them. + * We have the capability to use the ipath_nguid field, and get + * the guid from the first chip's flash, to use for all of them. */ -void ipath_get_guid(struct ipath_devdata *dd) +void ipath_get_eeprom_info(struct ipath_devdata *dd) { void *buf; struct ipath_flash *ifp; diff --git a/drivers/infiniband/hw/ipath/ipath_file_ops.c b/drivers/infiniband/hw/ipath/ipath_file_ops.c index c347191f02bf..ada267e41f6c 100644 --- a/drivers/infiniband/hw/ipath/ipath_file_ops.c +++ b/drivers/infiniband/hw/ipath/ipath_file_ops.c @@ -139,7 +139,7 @@ static int ipath_get_base_info(struct ipath_portdata *pd, kinfo->spi_piosize = dd->ipath_ibmaxlen; kinfo->spi_mtu = dd->ipath_ibmaxlen; /* maxlen, not ibmtu */ kinfo->spi_port = pd->port_port; - kinfo->spi_sw_version = IPATH_USER_SWVERSION; + kinfo->spi_sw_version = IPATH_KERN_SWVERSION; kinfo->spi_hw_version = dd->ipath_revision; if (copy_to_user(ubase, kinfo, sizeof(*kinfo))) @@ -1224,6 +1224,10 @@ static unsigned int ipath_poll(struct file *fp, if (tail == head) { set_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag); + if(dd->ipath_rhdrhead_intr_off) /* arm rcv interrupt */ + (void)ipath_write_ureg(dd, ur_rcvhdrhead, + dd->ipath_rhdrhead_intr_off + | head, pd->port_port); poll_wait(fp, &pd->port_wait, pt); if (test_bit(IPATH_PORT_WAITING_RCV, &pd->port_flag)) { diff --git a/drivers/infiniband/hw/ipath/ipath_ht400.c b/drivers/infiniband/hw/ipath/ipath_ht400.c index 4652435998f3..fac0a2b74de2 100644 --- a/drivers/infiniband/hw/ipath/ipath_ht400.c +++ b/drivers/infiniband/hw/ipath/ipath_ht400.c @@ -607,7 +607,12 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name, case 4: /* Ponderosa is one of the bringup boards */ n = "Ponderosa"; break; - case 5: /* HT-460 original production board */ + case 5: + /* + * HT-460 original production board; two production levels, with + * different serial number ranges. See ipath_ht_early_init() for + * case where we enable IPATH_GPIO_INTR for later serial # range. + */ n = "InfiniPath_HT-460"; break; case 6: @@ -642,7 +647,7 @@ static int ipath_ht_boardname(struct ipath_devdata *dd, char *name, if (n) snprintf(name, namelen, "%s", n); - if (dd->ipath_majrev != 3 || dd->ipath_minrev != 2) { + if (dd->ipath_majrev != 3 || (dd->ipath_minrev < 2 || dd->ipath_minrev > 3)) { /* * This version of the driver only supports the HT-400 * Rev 3.2 @@ -1520,6 +1525,18 @@ static int ipath_ht_early_init(struct ipath_devdata *dd) */ ipath_write_kreg(dd, dd->ipath_kregs->kr_sendctrl, INFINIPATH_S_ABORT); + + ipath_get_eeprom_info(dd); + if(dd->ipath_boardrev == 5 && dd->ipath_serial[0] == '1' && + dd->ipath_serial[1] == '2' && dd->ipath_serial[2] == '8') { + /* + * Later production HT-460 has same changes as HT-465, so + * can use GPIO interrupts. They have serial #'s starting + * with 128, rather than 112. + */ + dd->ipath_flags |= IPATH_GPIO_INTR; + dd->ipath_flags &= ~IPATH_POLL_RX_INTR; + } return 0; } diff --git a/drivers/infiniband/hw/ipath/ipath_init_chip.c b/drivers/infiniband/hw/ipath/ipath_init_chip.c index 16f640e1c16e..dc83250d26a6 100644 --- a/drivers/infiniband/hw/ipath/ipath_init_chip.c +++ b/drivers/infiniband/hw/ipath/ipath_init_chip.c @@ -879,7 +879,6 @@ int ipath_init_chip(struct ipath_devdata *dd, int reinit) done: if (!ret) { - ipath_get_guid(dd); *dd->ipath_statusp |= IPATH_STATUS_CHIP_PRESENT; if (!dd->ipath_f_intrsetup(dd)) { /* now we can enable all interrupts from the chip */ diff --git a/drivers/infiniband/hw/ipath/ipath_kernel.h b/drivers/infiniband/hw/ipath/ipath_kernel.h index e6507f8115bc..5d92d57b6f54 100644 --- a/drivers/infiniband/hw/ipath/ipath_kernel.h +++ b/drivers/infiniband/hw/ipath/ipath_kernel.h @@ -650,7 +650,7 @@ u32 __iomem *ipath_getpiobuf(struct ipath_devdata *, u32 *); void ipath_init_pe800_funcs(struct ipath_devdata *); /* init HT-400-specific func */ void ipath_init_ht400_funcs(struct ipath_devdata *); -void ipath_get_guid(struct ipath_devdata *); +void ipath_get_eeprom_info(struct ipath_devdata *); u64 ipath_snap_cntr(struct ipath_devdata *, ipath_creg); /* diff --git a/drivers/infiniband/hw/ipath/ipath_keys.c b/drivers/infiniband/hw/ipath/ipath_keys.c index aa33b0e9f2f6..5ae8761f9dd2 100644 --- a/drivers/infiniband/hw/ipath/ipath_keys.c +++ b/drivers/infiniband/hw/ipath/ipath_keys.c @@ -136,9 +136,7 @@ int ipath_lkey_ok(struct ipath_lkey_table *rkt, struct ipath_sge *isge, ret = 1; goto bail; } - spin_lock(&rkt->lock); mr = rkt->table[(sge->lkey >> (32 - ib_ipath_lkey_table_size))]; - spin_unlock(&rkt->lock); if (unlikely(mr == NULL || mr->lkey != sge->lkey)) { ret = 0; goto bail; @@ -184,8 +182,6 @@ bail: * @acc: access flags * * Return 1 if successful, otherwise 0. - * - * The QP r_rq.lock should be held. */ int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss, u32 len, u64 vaddr, u32 rkey, int acc) @@ -196,9 +192,7 @@ int ipath_rkey_ok(struct ipath_ibdev *dev, struct ipath_sge_state *ss, size_t off; int ret; - spin_lock(&rkt->lock); mr = rkt->table[(rkey >> (32 - ib_ipath_lkey_table_size))]; - spin_unlock(&rkt->lock); if (unlikely(mr == NULL || mr->lkey != rkey)) { ret = 0; goto bail; diff --git a/drivers/infiniband/hw/ipath/ipath_layer.c b/drivers/infiniband/hw/ipath/ipath_layer.c index 9cb5258ffed9..9ec4ac77b87f 100644 --- a/drivers/infiniband/hw/ipath/ipath_layer.c +++ b/drivers/infiniband/hw/ipath/ipath_layer.c @@ -872,12 +872,13 @@ static void copy_io(u32 __iomem *piobuf, struct ipath_sge_state *ss, update_sge(ss, len); length -= len; } + /* Update address before sending packet. */ + update_sge(ss, length); /* must flush early everything before trigger word */ ipath_flush_wc(); __raw_writel(last, piobuf); /* be sure trigger word is written */ ipath_flush_wc(); - update_sge(ss, length); } /** @@ -943,17 +944,18 @@ int ipath_verbs_send(struct ipath_devdata *dd, u32 hdrwords, if (likely(ss->num_sge == 1 && len <= ss->sge.length && !((unsigned long)ss->sge.vaddr & (sizeof(u32) - 1)))) { u32 w; + u32 *addr = (u32 *) ss->sge.vaddr; + /* Update address before sending packet. */ + update_sge(ss, len); /* Need to round up for the last dword in the packet. */ w = (len + 3) >> 2; - __iowrite32_copy(piobuf, ss->sge.vaddr, w - 1); + __iowrite32_copy(piobuf, addr, w - 1); /* must flush early everything before trigger word */ ipath_flush_wc(); - __raw_writel(((u32 *) ss->sge.vaddr)[w - 1], - piobuf + w - 1); + __raw_writel(addr[w - 1], piobuf + w - 1); /* be sure trigger word is written */ ipath_flush_wc(); - update_sge(ss, len); ret = 0; goto bail; } diff --git a/drivers/infiniband/hw/ipath/ipath_pe800.c b/drivers/infiniband/hw/ipath/ipath_pe800.c index 6318067ab5ec..02e8c75b24f6 100644 --- a/drivers/infiniband/hw/ipath/ipath_pe800.c +++ b/drivers/infiniband/hw/ipath/ipath_pe800.c @@ -1180,6 +1180,8 @@ static int ipath_pe_early_init(struct ipath_devdata *dd) */ dd->ipath_rhdrhead_intr_off = 1ULL<<32; + ipath_get_eeprom_info(dd); + return 0; } diff --git a/drivers/infiniband/hw/ipath/ipath_qp.c b/drivers/infiniband/hw/ipath/ipath_qp.c index 18890716db1e..9f8855d970c8 100644 --- a/drivers/infiniband/hw/ipath/ipath_qp.c +++ b/drivers/infiniband/hw/ipath/ipath_qp.c @@ -375,10 +375,10 @@ static void ipath_error_qp(struct ipath_qp *qp) spin_lock(&dev->pending_lock); /* XXX What if its already removed by the timeout code? */ - if (qp->timerwait.next != LIST_POISON1) - list_del(&qp->timerwait); - if (qp->piowait.next != LIST_POISON1) - list_del(&qp->piowait); + if (!list_empty(&qp->timerwait)) + list_del_init(&qp->timerwait); + if (!list_empty(&qp->piowait)) + list_del_init(&qp->piowait); spin_unlock(&dev->pending_lock); wc.status = IB_WC_WR_FLUSH_ERR; @@ -427,6 +427,7 @@ static void ipath_error_qp(struct ipath_qp *qp) int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, int attr_mask) { + struct ipath_ibdev *dev = to_idev(ibqp->device); struct ipath_qp *qp = to_iqp(ibqp); enum ib_qp_state cur_state, new_state; unsigned long flags; @@ -443,6 +444,19 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, attr_mask)) goto inval; + if (attr_mask & IB_QP_AV) + if (attr->ah_attr.dlid == 0 || + attr->ah_attr.dlid >= IPS_MULTICAST_LID_BASE) + goto inval; + + if (attr_mask & IB_QP_PKEY_INDEX) + if (attr->pkey_index >= ipath_layer_get_npkeys(dev->dd)) + goto inval; + + if (attr_mask & IB_QP_MIN_RNR_TIMER) + if (attr->min_rnr_timer > 31) + goto inval; + switch (new_state) { case IB_QPS_RESET: ipath_reset_qp(qp); @@ -457,13 +471,8 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, } - if (attr_mask & IB_QP_PKEY_INDEX) { - struct ipath_ibdev *dev = to_idev(ibqp->device); - - if (attr->pkey_index >= ipath_layer_get_npkeys(dev->dd)) - goto inval; + if (attr_mask & IB_QP_PKEY_INDEX) qp->s_pkey_index = attr->pkey_index; - } if (attr_mask & IB_QP_DEST_QPN) qp->remote_qpn = attr->dest_qp_num; @@ -479,12 +488,8 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, if (attr_mask & IB_QP_ACCESS_FLAGS) qp->qp_access_flags = attr->qp_access_flags; - if (attr_mask & IB_QP_AV) { - if (attr->ah_attr.dlid == 0 || - attr->ah_attr.dlid >= IPS_MULTICAST_LID_BASE) - goto inval; + if (attr_mask & IB_QP_AV) qp->remote_ah_attr = attr->ah_attr; - } if (attr_mask & IB_QP_PATH_MTU) qp->path_mtu = attr->path_mtu; @@ -499,11 +504,8 @@ int ipath_modify_qp(struct ib_qp *ibqp, struct ib_qp_attr *attr, qp->s_rnr_retry_cnt = qp->s_rnr_retry; } - if (attr_mask & IB_QP_MIN_RNR_TIMER) { - if (attr->min_rnr_timer > 31) - goto inval; + if (attr_mask & IB_QP_MIN_RNR_TIMER) qp->s_min_rnr_timer = attr->min_rnr_timer; - } if (attr_mask & IB_QP_QKEY) qp->qkey = attr->qkey; @@ -710,10 +712,8 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, init_attr->qp_type == IB_QPT_RC ? ipath_do_rc_send : ipath_do_uc_send, (unsigned long)qp); - qp->piowait.next = LIST_POISON1; - qp->piowait.prev = LIST_POISON2; - qp->timerwait.next = LIST_POISON1; - qp->timerwait.prev = LIST_POISON2; + INIT_LIST_HEAD(&qp->piowait); + INIT_LIST_HEAD(&qp->timerwait); qp->state = IB_QPS_RESET; qp->s_wq = swq; qp->s_size = init_attr->cap.max_send_wr + 1; @@ -734,7 +734,7 @@ struct ib_qp *ipath_create_qp(struct ib_pd *ibpd, ipath_reset_qp(qp); /* Tell the core driver that the kernel SMA is present. */ - if (qp->ibqp.qp_type == IB_QPT_SMI) + if (init_attr->qp_type == IB_QPT_SMI) ipath_layer_set_verbs_flags(dev->dd, IPATH_VERBS_KERNEL_SMA); break; @@ -783,10 +783,10 @@ int ipath_destroy_qp(struct ib_qp *ibqp) /* Make sure the QP isn't on the timeout list. */ spin_lock_irqsave(&dev->pending_lock, flags); - if (qp->timerwait.next != LIST_POISON1) - list_del(&qp->timerwait); - if (qp->piowait.next != LIST_POISON1) - list_del(&qp->piowait); + if (!list_empty(&qp->timerwait)) + list_del_init(&qp->timerwait); + if (!list_empty(&qp->piowait)) + list_del_init(&qp->piowait); spin_unlock_irqrestore(&dev->pending_lock, flags); /* @@ -855,10 +855,10 @@ void ipath_sqerror_qp(struct ipath_qp *qp, struct ib_wc *wc) spin_lock(&dev->pending_lock); /* XXX What if its already removed by the timeout code? */ - if (qp->timerwait.next != LIST_POISON1) - list_del(&qp->timerwait); - if (qp->piowait.next != LIST_POISON1) - list_del(&qp->piowait); + if (!list_empty(&qp->timerwait)) + list_del_init(&qp->timerwait); + if (!list_empty(&qp->piowait)) + list_del_init(&qp->piowait); spin_unlock(&dev->pending_lock); ipath_cq_enter(to_icq(qp->ibqp.send_cq), wc, 1); diff --git a/drivers/infiniband/hw/ipath/ipath_rc.c b/drivers/infiniband/hw/ipath/ipath_rc.c index a4055ca00614..493b1821a934 100644 --- a/drivers/infiniband/hw/ipath/ipath_rc.c +++ b/drivers/infiniband/hw/ipath/ipath_rc.c @@ -57,7 +57,7 @@ static void ipath_init_restart(struct ipath_qp *qp, struct ipath_swqe *wqe) qp->s_len = wqe->length - len; dev = to_idev(qp->ibqp.device); spin_lock(&dev->pending_lock); - if (qp->timerwait.next == LIST_POISON1) + if (list_empty(&qp->timerwait)) list_add_tail(&qp->timerwait, &dev->pending[dev->pending_index]); spin_unlock(&dev->pending_lock); @@ -356,7 +356,7 @@ static inline int ipath_make_rc_req(struct ipath_qp *qp, if ((int)(qp->s_psn - qp->s_next_psn) > 0) qp->s_next_psn = qp->s_psn; spin_lock(&dev->pending_lock); - if (qp->timerwait.next == LIST_POISON1) + if (list_empty(&qp->timerwait)) list_add_tail(&qp->timerwait, &dev->pending[dev->pending_index]); spin_unlock(&dev->pending_lock); @@ -726,8 +726,8 @@ void ipath_restart_rc(struct ipath_qp *qp, u32 psn, struct ib_wc *wc) */ dev = to_idev(qp->ibqp.device); spin_lock(&dev->pending_lock); - if (qp->timerwait.next != LIST_POISON1) - list_del(&qp->timerwait); + if (!list_empty(&qp->timerwait)) + list_del_init(&qp->timerwait); spin_unlock(&dev->pending_lock); if (wqe->wr.opcode == IB_WR_RDMA_READ) @@ -886,8 +886,8 @@ static int do_rc_ack(struct ipath_qp *qp, u32 aeth, u32 psn, int opcode) * just won't find anything to restart if we ACK everything. */ spin_lock(&dev->pending_lock); - if (qp->timerwait.next != LIST_POISON1) - list_del(&qp->timerwait); + if (!list_empty(&qp->timerwait)) + list_del_init(&qp->timerwait); spin_unlock(&dev->pending_lock); /* @@ -1194,8 +1194,7 @@ static inline void ipath_rc_rcv_resp(struct ipath_ibdev *dev, IB_WR_RDMA_READ)) goto ack_done; spin_lock(&dev->pending_lock); - if (qp->s_rnr_timeout == 0 && - qp->timerwait.next != LIST_POISON1) + if (qp->s_rnr_timeout == 0 && !list_empty(&qp->timerwait)) list_move_tail(&qp->timerwait, &dev->pending[dev->pending_index]); spin_unlock(&dev->pending_lock); diff --git a/drivers/infiniband/hw/ipath/ipath_ruc.c b/drivers/infiniband/hw/ipath/ipath_ruc.c index eb81424b3c5b..d38f4f3cfd1d 100644 --- a/drivers/infiniband/hw/ipath/ipath_ruc.c +++ b/drivers/infiniband/hw/ipath/ipath_ruc.c @@ -435,7 +435,7 @@ void ipath_no_bufs_available(struct ipath_qp *qp, struct ipath_ibdev *dev) unsigned long flags; spin_lock_irqsave(&dev->pending_lock, flags); - if (qp->piowait.next == LIST_POISON1) + if (list_empty(&qp->piowait)) list_add_tail(&qp->piowait, &dev->piowait); spin_unlock_irqrestore(&dev->pending_lock, flags); /* diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index cb9e387c301f..28fdbdaa789d 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c @@ -464,7 +464,7 @@ static void ipath_ib_timer(void *arg) last = &dev->pending[dev->pending_index]; while (!list_empty(last)) { qp = list_entry(last->next, struct ipath_qp, timerwait); - list_del(&qp->timerwait); + list_del_init(&qp->timerwait); qp->timer_next = resend; resend = qp; atomic_inc(&qp->refcount); @@ -474,7 +474,7 @@ static void ipath_ib_timer(void *arg) qp = list_entry(last->next, struct ipath_qp, timerwait); if (--qp->s_rnr_timeout == 0) { do { - list_del(&qp->timerwait); + list_del_init(&qp->timerwait); tasklet_hi_schedule(&qp->s_task); if (list_empty(last)) break; @@ -554,7 +554,7 @@ static int ipath_ib_piobufavail(void *arg) while (!list_empty(&dev->piowait)) { qp = list_entry(dev->piowait.next, struct ipath_qp, piowait); - list_del(&qp->piowait); + list_del_init(&qp->piowait); tasklet_hi_schedule(&qp->s_task); } spin_unlock_irqrestore(&dev->pending_lock, flags); @@ -951,6 +951,7 @@ static void *ipath_register_ib_device(int unit, struct ipath_devdata *dd) idev->dd = dd; strlcpy(dev->name, "ipath%d", IB_DEVICE_NAME_MAX); + dev->owner = THIS_MODULE; dev->node_guid = ipath_layer_get_guid(dd); dev->uverbs_abi_ver = IPATH_UVERBS_ABI_VERSION; dev->uverbs_cmd_mask = diff --git a/drivers/infiniband/hw/mthca/mthca_srq.c b/drivers/infiniband/hw/mthca/mthca_srq.c index 1ea433291fa7..b292fefa3b41 100644 --- a/drivers/infiniband/hw/mthca/mthca_srq.c +++ b/drivers/infiniband/hw/mthca/mthca_srq.c @@ -490,26 +490,7 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, first_ind = srq->first_free; - for (nreq = 0; wr; ++nreq, wr = wr->next) { - if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) { - nreq = 0; - - doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift); - doorbell[1] = cpu_to_be32(srq->srqn << 8); - - /* - * Make sure that descriptors are written - * before doorbell is rung. - */ - wmb(); - - mthca_write64(doorbell, - dev->kar + MTHCA_RECEIVE_DOORBELL, - MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); - - first_ind = srq->first_free; - } - + for (nreq = 0; wr; wr = wr->next) { ind = srq->first_free; if (ind < 0) { @@ -569,6 +550,26 @@ int mthca_tavor_post_srq_recv(struct ib_srq *ibsrq, struct ib_recv_wr *wr, srq->wrid[ind] = wr->wr_id; srq->first_free = next_ind; + + ++nreq; + if (unlikely(nreq == MTHCA_TAVOR_MAX_WQES_PER_RECV_DB)) { + nreq = 0; + + doorbell[0] = cpu_to_be32(first_ind << srq->wqe_shift); + doorbell[1] = cpu_to_be32(srq->srqn << 8); + + /* + * Make sure that descriptors are written + * before doorbell is rung. + */ + wmb(); + + mthca_write64(doorbell, + dev->kar + MTHCA_RECEIVE_DOORBELL, + MTHCA_GET_DOORBELL_LOCK(&dev->doorbell_lock)); + + first_ind = srq->first_free; + } } if (likely(nreq)) { diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 1494175ac6fe..161afddd0f44 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -36,13 +36,10 @@ /* - * This code has been tested on an ads7846 / N770 device. + * This code has been heavily tested on a Nokia 770, and lightly + * tested on other ads7846 devices (OSK/Mistral, Lubbock). * Support for ads7843 and ads7845 has only been stubbed in. * - * Not yet done: How accurate are the temperature and voltage - * readings? (System-specific calibration should support - * accuracy of 0.3 degrees C; otherwise it's 2.0 degrees.) - * * IRQ handling needs a workaround because of a shortcoming in handling * edge triggered IRQs on some platforms like the OMAP1/2. These * platforms don't handle the ARM lazy IRQ disabling properly, thus we @@ -248,10 +245,13 @@ static int ads7846_read12_ser(struct device *dev, unsigned command) if (req->msg.status) status = req->msg.status; - sample = be16_to_cpu(req->sample); - sample = sample >> 4; - kfree(req); + /* on-wire is a must-ignore bit, a BE12 value, then padding */ + sample = be16_to_cpu(req->sample); + sample = sample >> 3; + sample &= 0x0fff; + + kfree(req); return status ? status : sample; } @@ -336,13 +336,13 @@ static void ads7846_rx(void *ads) u16 x, y, z1, z2; unsigned long flags; - /* adjust: 12 bit samples (left aligned), built from - * two 8 bit values writen msb-first. + /* adjust: on-wire is a must-ignore bit, a BE12 value, then padding; + * built from two 8 bit values written msb-first. */ - x = be16_to_cpu(ts->tc.x) >> 4; - y = be16_to_cpu(ts->tc.y) >> 4; - z1 = be16_to_cpu(ts->tc.z1) >> 4; - z2 = be16_to_cpu(ts->tc.z2) >> 4; + x = (be16_to_cpu(ts->tc.x) >> 3) & 0x0fff; + y = (be16_to_cpu(ts->tc.y) >> 3) & 0x0fff; + z1 = (be16_to_cpu(ts->tc.z1) >> 3) & 0x0fff; + z2 = (be16_to_cpu(ts->tc.z2) >> 3) & 0x0fff; /* range filtering */ if (x == MAX_12BIT) @@ -420,7 +420,7 @@ static void ads7846_debounce(void *ads) m = &ts->msg[ts->msg_idx]; t = list_entry(m->transfers.prev, struct spi_transfer, transfer_list); - val = (*(u16 *)t->rx_buf) >> 3; + val = (be16_to_cpu(*(__be16 *)t->rx_buf) >> 3) & 0x0fff; if (!ts->read_cnt || (abs(ts->last_read - val) > ts->debounce_tol)) { /* Repeat it, if this was the first read or the read * wasn't consistent enough. */ @@ -469,7 +469,7 @@ static void ads7846_timer(unsigned long handle) spin_lock_irq(&ts->lock); if (unlikely(ts->msg_idx && !ts->pendown)) { - /* measurment cycle ended */ + /* measurement cycle ended */ if (!device_suspended(&ts->spi->dev)) { ts->irq_disabled = 0; enable_irq(ts->spi->irq); @@ -495,11 +495,10 @@ static irqreturn_t ads7846_irq(int irq, void *handle, struct pt_regs *regs) spin_lock_irqsave(&ts->lock, flags); if (likely(ts->get_pendown_state())) { if (!ts->irq_disabled) { - /* REVISIT irq logic for many ARM chips has cloned a - * bug wherein disabling an irq in its handler won't - * work;(it's disabled lazily, and too late to work. - * until all their irq logic is fixed, we must shadow - * that state here. + /* The ARM do_simple_IRQ() dispatcher doesn't act + * like the other dispatchers: it will report IRQs + * even after they've been disabled. We work around + * that here. (The "generic irq" framework may help...) */ ts->irq_disabled = 1; disable_irq(ts->spi->irq); @@ -609,16 +608,20 @@ static int __devinit ads7846_probe(struct spi_device *spi) return -EINVAL; } + /* REVISIT when the irq can be triggered active-low, or if for some + * reason the touchscreen isn't hooked up, we don't need to access + * the pendown state. + */ if (pdata->get_pendown_state == NULL) { dev_dbg(&spi->dev, "no get_pendown_state function?\n"); return -EINVAL; } - /* We'd set the wordsize to 12 bits ... except that some controllers - * will then treat the 8 bit command words as 12 bits (and drop the - * four MSBs of the 12 bit result). Result: inputs must be shifted - * to discard the four garbage LSBs. + /* We'd set TX wordsize 8 bits and RX wordsize to 13 bits ... except + * that even if the hardware can do that, the SPI controller driver + * may not. So we stick to very-portable 8 bit words, both RX and TX. */ + spi->bits_per_word = 8; ts = kzalloc(sizeof(struct ads7846), GFP_KERNEL); input_dev = input_allocate_device(); @@ -772,7 +775,7 @@ static int __devinit ads7846_probe(struct spi_device *spi) if (request_irq(spi->irq, ads7846_irq, SA_SAMPLE_RANDOM | SA_TRIGGER_FALLING, - spi->dev.bus_id, ts)) { + spi->dev.driver->name, ts)) { dev_dbg(&spi->dev, "irq %d busy?\n", spi->irq); err = -EBUSY; goto err_free_mem; diff --git a/drivers/md/md.c b/drivers/md/md.c index 3ca3cfb03a7e..ec802913f977 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -5028,8 +5028,10 @@ static int md_notify_reboot(struct notifier_block *this, printk(KERN_INFO "md: stopping all md devices.\n"); ITERATE_MDDEV(mddev,tmp) - if (mddev_trylock(mddev)) + if (mddev_trylock(mddev)) { do_md_stop (mddev, 1); + mddev_unlock(mddev); + } /* * certain more exotic SCSI devices are known to be * volatile wrt too early system reboots. While the diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index 9c45b983e0de..1a04db4552da 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig @@ -1,6 +1,6 @@ config VIDEO_SAA7146 tristate - select I2C + depends on I2C config VIDEO_SAA7146_VV tristate diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/dvb/pluto2/Kconfig index 48252e9ce586..7d8e6e87bdbb 100644 --- a/drivers/media/dvb/pluto2/Kconfig +++ b/drivers/media/dvb/pluto2/Kconfig @@ -1,7 +1,6 @@ config DVB_PLUTO2 tristate "Pluto2 cards" depends on DVB_CORE && PCI && I2C - select I2C select I2C_ALGOBIT select DVB_TDA1004X help diff --git a/drivers/mmc/mmc_block.c b/drivers/mmc/mmc_block.c index e39cc05c64c2..587458b370b9 100644 --- a/drivers/mmc/mmc_block.c +++ b/drivers/mmc/mmc_block.c @@ -353,7 +353,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) */ printk(KERN_ERR "%s: unable to select block size for " "writing (rb%u wb%u rp%u wp%u)\n", - md->disk->disk_name, + mmc_card_id(card), 1 << card->csd.read_blkbits, 1 << card->csd.write_blkbits, card->csd.read_partial, diff --git a/drivers/net/irda/Kconfig b/drivers/net/irda/Kconfig index 5e6d00752990..cff8598aa800 100644 --- a/drivers/net/irda/Kconfig +++ b/drivers/net/irda/Kconfig @@ -33,7 +33,7 @@ config DONGLE config ESI_DONGLE tristate "ESI JetEye PC dongle" - depends on DONGLE && IRDA + depends on IRTTY_SIR && DONGLE && IRDA help Say Y here if you want to build support for the Extended Systems JetEye PC dongle. To compile it as a module, choose M here. The ESI @@ -44,7 +44,7 @@ config ESI_DONGLE config ACTISYS_DONGLE tristate "ACTiSYS IR-220L and IR220L+ dongle" - depends on DONGLE && IRDA + depends on IRTTY_SIR && DONGLE && IRDA help Say Y here if you want to build support for the ACTiSYS IR-220L and IR220L+ dongles. To compile it as a module, choose M here. The @@ -55,7 +55,7 @@ config ACTISYS_DONGLE config TEKRAM_DONGLE tristate "Tekram IrMate 210B dongle" - depends on DONGLE && IRDA + depends on IRTTY_SIR && DONGLE && IRDA help Say Y here if you want to build support for the Tekram IrMate 210B dongle. To compile it as a module, choose M here. The Tekram dongle @@ -66,7 +66,7 @@ config TEKRAM_DONGLE config TOIM3232_DONGLE tristate "TOIM3232 IrDa dongle" - depends on DONGLE && IRDA + depends on IRTTY_SIR && DONGLE && IRDA help Say Y here if you want to build support for the Vishay/Temic TOIM3232 and TOIM4232 based dongles. @@ -74,7 +74,7 @@ config TOIM3232_DONGLE config LITELINK_DONGLE tristate "Parallax LiteLink dongle" - depends on DONGLE && IRDA + depends on IRTTY_SIR && DONGLE && IRDA help Say Y here if you want to build support for the Parallax Litelink dongle. To compile it as a module, choose M here. The Parallax @@ -85,7 +85,7 @@ config LITELINK_DONGLE config MA600_DONGLE tristate "Mobile Action MA600 dongle" - depends on DONGLE && IRDA && EXPERIMENTAL + depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL help Say Y here if you want to build support for the Mobile Action MA600 dongle. To compile it as a module, choose M here. The MA600 dongle @@ -98,7 +98,7 @@ config MA600_DONGLE config GIRBIL_DONGLE tristate "Greenwich GIrBIL dongle" - depends on DONGLE && IRDA && EXPERIMENTAL + depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL help Say Y here if you want to build support for the Greenwich GIrBIL dongle. If you want to compile it as a module, choose M here. @@ -109,7 +109,7 @@ config GIRBIL_DONGLE config MCP2120_DONGLE tristate "Microchip MCP2120" - depends on DONGLE && IRDA && EXPERIMENTAL + depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL help Say Y here if you want to build support for the Microchip MCP2120 dongle. If you want to compile it as a module, choose M here. @@ -123,7 +123,7 @@ config MCP2120_DONGLE config OLD_BELKIN_DONGLE tristate "Old Belkin dongle" - depends on DONGLE && IRDA && EXPERIMENTAL + depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL help Say Y here if you want to build support for the Adaptec Airport 1000 and 2000 dongles. If you want to compile it as a module, choose @@ -132,7 +132,7 @@ config OLD_BELKIN_DONGLE config ACT200L_DONGLE tristate "ACTiSYS IR-200L dongle" - depends on DONGLE && IRDA && EXPERIMENTAL + depends on IRTTY_SIR && DONGLE && IRDA && EXPERIMENTAL help Say Y here if you want to build support for the ACTiSYS IR-200L dongle. If you want to compile it as a module, choose M here. diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 60779ebf2ff6..959109609d85 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -979,6 +979,7 @@ static int sky2_rx_start(struct sky2_port *sky2) struct sky2_hw *hw = sky2->hw; unsigned rxq = rxqaddr[sky2->port]; int i; + unsigned thresh; sky2->rx_put = sky2->rx_next = 0; sky2_qset(hw, rxq); @@ -1003,9 +1004,21 @@ static int sky2_rx_start(struct sky2_port *sky2) sky2_rx_add(sky2, re->mapaddr); } - /* Truncate oversize frames */ - sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), sky2->rx_bufsize - 8); - sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON); + + /* + * The receiver hangs if it receives frames larger than the + * packet buffer. As a workaround, truncate oversize frames, but + * the register is limited to 9 bits, so if you do frames > 2052 + * you better get the MTU right! + */ + thresh = (sky2->rx_bufsize - 8) / sizeof(u32); + if (thresh > 0x1ff) + sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_OFF); + else { + sky2_write16(hw, SK_REG(sky2->port, RX_GMF_TR_THR), thresh); + sky2_write32(hw, SK_REG(sky2->port, RX_GMF_CTRL_T), RX_TRUNC_ON); + } + /* Tell chip about available buffers */ sky2_write16(hw, Y2_QADDR(rxq, PREF_UNIT_PUT_IDX), sky2->rx_put); diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c index 9de4b5a04d70..5fc14563ee3a 100644 --- a/drivers/spi/spi_s3c24xx.c +++ b/drivers/spi/spi_s3c24xx.c @@ -405,7 +405,7 @@ static int s3c24xx_spi_remove(struct platform_device *dev) static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg) { - struct s3c24xx_spi *hw = platform_get_drvdata(dev); + struct s3c24xx_spi *hw = platform_get_drvdata(pdev); clk_disable(hw->clk); return 0; @@ -413,7 +413,7 @@ static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg) static int s3c24xx_spi_resume(struct platform_device *pdev) { - struct s3c24xx_spi *hw = platform_get_drvdata(dev); + struct s3c24xx_spi *hw = platform_get_drvdata(pdev); clk_enable(hw->clk); return 0; diff --git a/fs/affs/namei.c b/fs/affs/namei.c index d4c2d636c479..a42143ca0169 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c @@ -416,10 +416,9 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry, return retval; } - retval = -EIO; bh = affs_bread(sb, old_dentry->d_inode->i_ino); if (!bh) - goto done; + return -EIO; /* Remove header from its parent directory. */ affs_lock_dir(old_dir); diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index f28696f235c4..2b220dd6b4e7 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -542,7 +542,7 @@ add_failed: static int metapage_releasepage(struct page *page, gfp_t gfp_mask) { struct metapage *mp; - int busy = 0; + int ret = 1; unsigned int offset; for (offset = 0; offset < PAGE_CACHE_SIZE; offset += PSIZE) { @@ -552,30 +552,20 @@ static int metapage_releasepage(struct page *page, gfp_t gfp_mask) continue; jfs_info("metapage_releasepage: mp = 0x%p", mp); - if (mp->count || mp->nohomeok) { + if (mp->count || mp->nohomeok || + test_bit(META_dirty, &mp->flag)) { jfs_info("count = %ld, nohomeok = %d", mp->count, mp->nohomeok); - busy = 1; + ret = 0; continue; } - wait_on_page_writeback(page); - //WARN_ON(test_bit(META_dirty, &mp->flag)); - if (test_bit(META_dirty, &mp->flag)) { - dump_mem("dirty mp in metapage_releasepage", mp, - sizeof(struct metapage)); - dump_mem("page", page, sizeof(struct page)); - dump_stack(); - } if (mp->lsn) remove_from_logsync(mp); remove_metapage(page, mp); INCREMENT(mpStat.pagefree); free_metapage(mp); } - if (busy) - return -1; - - return 0; + return ret; } static void metapage_invalidatepage(struct page *page, unsigned long offset) diff --git a/include/asm-alpha/termbits.h b/include/asm-alpha/termbits.h index f4837fa29420..5541101b58ae 100644 --- a/include/asm-alpha/termbits.h +++ b/include/asm-alpha/termbits.h @@ -148,6 +148,7 @@ struct termios { #define HUPCL 00040000 #define CLOCAL 00100000 +#define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ /* c_lflag bits */ diff --git a/include/asm-powerpc/termbits.h b/include/asm-powerpc/termbits.h index ebf6055481dc..6d533b07aaf5 100644 --- a/include/asm-powerpc/termbits.h +++ b/include/asm-powerpc/termbits.h @@ -153,6 +153,7 @@ struct termios { #define HUPCL 00040000 #define CLOCAL 00100000 +#define CMSPAR 010000000000 /* mark or space (stick) parity */ #define CRTSCTS 020000000000 /* flow control */ /* c_lflag bits */ diff --git a/net/core/dev.c b/net/core/dev.c index 2dce673a039b..4fba549caf29 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -127,7 +127,7 @@ * sure which should go first, but I bet it won't make much * difference if we are running VLANs. The good news is that * this protocol won't be in the list unless compiled in, so - * the average user (w/out VLANs) will not be adversly affected. + * the average user (w/out VLANs) will not be adversely affected. * --BLG * * 0800 IP @@ -149,7 +149,7 @@ static struct list_head ptype_base[16]; /* 16 way hashed list */ static struct list_head ptype_all; /* Taps */ /* - * The @dev_base list is protected by @dev_base_lock and the rtln + * The @dev_base list is protected by @dev_base_lock and the rtnl * semaphore. * * Pure readers hold dev_base_lock for reading. @@ -641,10 +641,12 @@ int dev_valid_name(const char *name) * @name: name format string * * Passed a format string - eg "lt%d" it will try and find a suitable - * id. Not efficient for many devices, not called a lot. The caller - * must hold the dev_base or rtnl lock while allocating the name and - * adding the device in order to avoid duplicates. Returns the number - * of the unit assigned or a negative errno code. + * id. It scans list of devices to build up a free map, then chooses + * the first empty slot. The caller must hold the dev_base or rtnl lock + * while allocating the name and adding the device in order to avoid + * duplicates. + * Limited to bits_per_byte * page size devices (ie 32K on most platforms). + * Returns the number of the unit assigned or a negative errno code. */ int dev_alloc_name(struct net_device *dev, const char *name) @@ -744,7 +746,7 @@ int dev_change_name(struct net_device *dev, char *newname) } /** - * netdev_features_change - device changes fatures + * netdev_features_change - device changes features * @dev: device to cause notification * * Called to indicate a device has changed features. @@ -2196,7 +2198,7 @@ int netdev_set_master(struct net_device *slave, struct net_device *master) * @dev: device * @inc: modifier * - * Add or remove promsicuity from a device. While the count in the device + * Add or remove promiscuity from a device. While the count in the device * remains above zero the interface remains promiscuous. Once it hits zero * the device reverts back to normal filtering operation. A negative inc * value is used to drop promiscuity on the device. @@ -3122,7 +3124,7 @@ EXPORT_SYMBOL(alloc_netdev); void free_netdev(struct net_device *dev) { #ifdef CONFIG_SYSFS - /* Compatiablity with error handling in drivers */ + /* Compatibility with error handling in drivers */ if (dev->reg_state == NETREG_UNINITIALIZED) { kfree((char *)dev - dev->padded); return; diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 0190e39096b9..8a777932786d 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -280,10 +280,13 @@ static int inline rt6_check_neigh(struct rt6_info *rt) { struct neighbour *neigh = rt->rt6i_nexthop; int m = 0; - if (neigh) { + if (rt->rt6i_flags & RTF_NONEXTHOP || + !(rt->rt6i_flags & RTF_GATEWAY)) + m = 1; + else if (neigh) { read_lock_bh(&neigh->lock); if (neigh->nud_state & NUD_VALID) - m = 1; + m = 2; read_unlock_bh(&neigh->lock); } return m; @@ -292,15 +295,18 @@ static int inline rt6_check_neigh(struct rt6_info *rt) static int rt6_score_route(struct rt6_info *rt, int oif, int strict) { - int m = rt6_check_dev(rt, oif); + int m, n; + + m = rt6_check_dev(rt, oif); if (!m && (strict & RT6_SELECT_F_IFACE)) return -1; #ifdef CONFIG_IPV6_ROUTER_PREF m |= IPV6_DECODE_PREF(IPV6_EXTRACT_PREF(rt->rt6i_flags)) << 2; #endif - if (rt6_check_neigh(rt)) + n = rt6_check_neigh(rt); + if (n > 1) m |= 16; - else if (strict & RT6_SELECT_F_REACHABLE) + else if (!n && strict & RT6_SELECT_F_REACHABLE) return -1; return m; }