diff options
author | Paul Mackerras <paulus@samba.org> | 2005-09-29 13:13:36 +1000 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2005-09-29 13:13:36 +1000 |
commit | ab11d1ea281e85895369ef57c5259ad8a432fabb (patch) | |
tree | 684147479c6a8bb2fbed21bdcf12de1dd519c730 /drivers | |
parent | 952ecef7a0479049c8abb7c34a688ec2981ceadd (diff) | |
parent | 664cceb0093b755739e56572b836a99104ee8a75 (diff) | |
download | linux-ab11d1ea281e85895369ef57c5259ad8a432fabb.tar.bz2 |
Merge by hand from Linus' tree.
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/char/ipmi/ipmi_poweroff.c | 2 | ||||
-rw-r--r-- | drivers/connector/cn_queue.c | 32 | ||||
-rw-r--r-- | drivers/connector/connector.c | 74 | ||||
-rw-r--r-- | drivers/ide/legacy/ide-cs.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs.h | 1 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_cmd.c | 120 | ||||
-rw-r--r-- | drivers/infiniband/core/uverbs_main.c | 27 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_cmd.c | 4 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_eq.c | 2 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_memfree.c | 19 | ||||
-rw-r--r-- | drivers/infiniband/hw/mthca/mthca_provider.c | 2 | ||||
-rw-r--r-- | drivers/md/dm-ioctl.c | 9 | ||||
-rw-r--r-- | drivers/md/dm-mpath.c | 16 | ||||
-rw-r--r-- | drivers/media/dvb/frontends/tda10021.c | 4 | ||||
-rw-r--r-- | drivers/net/cs89x0.c | 1 | ||||
-rw-r--r-- | drivers/net/tg3.c | 94 | ||||
-rw-r--r-- | drivers/net/tg3.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/orinoco.c | 2 | ||||
-rw-r--r-- | drivers/pcmcia/Kconfig | 2 | ||||
-rw-r--r-- | drivers/pcmcia/cardbus.c | 5 | ||||
-rw-r--r-- | drivers/pcmcia/ti113x.h | 115 | ||||
-rw-r--r-- | drivers/pcmcia/yenta_socket.c | 62 | ||||
-rw-r--r-- | drivers/serial/serial_cs.c | 1 |
23 files changed, 407 insertions, 190 deletions
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c index e82a96ba396b..f66947722e12 100644 --- a/drivers/char/ipmi/ipmi_poweroff.c +++ b/drivers/char/ipmi/ipmi_poweroff.c @@ -55,7 +55,7 @@ extern void (*pm_power_off)(void); static int poweroff_powercycle; /* parameter definition to allow user to flag power cycle */ -module_param(poweroff_powercycle, int, 0); +module_param(poweroff_powercycle, int, 0644); MODULE_PARM_DESC(poweroff_powercycles, " Set to non-zero to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down."); /* Stuff from the get device id command. */ diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c index 966632182e2d..9f2f00d82917 100644 --- a/drivers/connector/cn_queue.c +++ b/drivers/connector/cn_queue.c @@ -31,16 +31,19 @@ #include <linux/connector.h> #include <linux/delay.h> -static void cn_queue_wrapper(void *data) +void cn_queue_wrapper(void *data) { - struct cn_callback_entry *cbq = data; + struct cn_callback_data *d = data; - cbq->cb->callback(cbq->cb->priv); - cbq->destruct_data(cbq->ddata); - cbq->ddata = NULL; + d->callback(d->callback_priv); + + d->destruct_data(d->ddata); + d->ddata = NULL; + + kfree(d->free); } -static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callback *cb) +static struct cn_callback_entry *cn_queue_alloc_callback_entry(char *name, struct cb_id *id, void (*callback)(void *)) { struct cn_callback_entry *cbq; @@ -50,8 +53,11 @@ static struct cn_callback_entry *cn_queue_alloc_callback_entry(struct cn_callbac return NULL; } - cbq->cb = cb; - INIT_WORK(&cbq->work, &cn_queue_wrapper, cbq); + snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name); + memcpy(&cbq->id.id, id, sizeof(struct cb_id)); + cbq->data.callback = callback; + + INIT_WORK(&cbq->work, &cn_queue_wrapper, &cbq->data); return cbq; } @@ -68,12 +74,12 @@ int cn_cb_equal(struct cb_id *i1, struct cb_id *i2) return ((i1->idx == i2->idx) && (i1->val == i2->val)); } -int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) +int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id, void (*callback)(void *)) { struct cn_callback_entry *cbq, *__cbq; int found = 0; - cbq = cn_queue_alloc_callback_entry(cb); + cbq = cn_queue_alloc_callback_entry(name, id, callback); if (!cbq) return -ENOMEM; @@ -82,7 +88,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) spin_lock_bh(&dev->queue_lock); list_for_each_entry(__cbq, &dev->queue_list, callback_entry) { - if (cn_cb_equal(&__cbq->cb->id, &cb->id)) { + if (cn_cb_equal(&__cbq->id.id, id)) { found = 1; break; } @@ -99,7 +105,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, struct cn_callback *cb) cbq->nls = dev->nls; cbq->seq = 0; - cbq->group = cbq->cb->id.idx; + cbq->group = cbq->id.id.idx; return 0; } @@ -111,7 +117,7 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id) spin_lock_bh(&dev->queue_lock); list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) { - if (cn_cb_equal(&cbq->cb->id, id)) { + if (cn_cb_equal(&cbq->id.id, id)) { list_del(&cbq->callback_entry); found = 1; break; diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index aaf6d468a8b9..bb0b3a8de14b 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -84,7 +84,7 @@ int cn_netlink_send(struct cn_msg *msg, u32 __group, int gfp_mask) spin_lock_bh(&dev->cbdev->queue_lock); list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { - if (cn_cb_equal(&__cbq->cb->id, &msg->id)) { + if (cn_cb_equal(&__cbq->id.id, &msg->id)) { found = 1; group = __cbq->group; } @@ -127,42 +127,56 @@ static int cn_call_callback(struct cn_msg *msg, void (*destruct_data)(void *), v { struct cn_callback_entry *__cbq; struct cn_dev *dev = &cdev; - int found = 0; + int err = -ENODEV; spin_lock_bh(&dev->cbdev->queue_lock); list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { - if (cn_cb_equal(&__cbq->cb->id, &msg->id)) { - /* - * Let's scream if there is some magic and the - * data will arrive asynchronously here. - * [i.e. netlink messages will be queued]. - * After the first warning I will fix it - * quickly, but now I think it is - * impossible. --zbr (2004_04_27). - */ + if (cn_cb_equal(&__cbq->id.id, &msg->id)) { if (likely(!test_bit(0, &__cbq->work.pending) && - __cbq->ddata == NULL)) { - __cbq->cb->priv = msg; + __cbq->data.ddata == NULL)) { + __cbq->data.callback_priv = msg; - __cbq->ddata = data; - __cbq->destruct_data = destruct_data; + __cbq->data.ddata = data; + __cbq->data.destruct_data = destruct_data; if (queue_work(dev->cbdev->cn_queue, &__cbq->work)) - found = 1; + err = 0; } else { - printk("%s: cbq->data=%p, " - "work->pending=%08lx.\n", - __func__, __cbq->ddata, - __cbq->work.pending); - WARN_ON(1); + struct work_struct *w; + struct cn_callback_data *d; + + w = kzalloc(sizeof(*w) + sizeof(*d), GFP_ATOMIC); + if (w) { + d = (struct cn_callback_data *)(w+1); + + d->callback_priv = msg; + d->callback = __cbq->data.callback; + d->ddata = data; + d->destruct_data = destruct_data; + d->free = w; + + INIT_LIST_HEAD(&w->entry); + w->pending = 0; + w->func = &cn_queue_wrapper; + w->data = d; + init_timer(&w->timer); + + if (queue_work(dev->cbdev->cn_queue, w)) + err = 0; + else { + kfree(w); + err = -EINVAL; + } + } else + err = -ENOMEM; } break; } } spin_unlock_bh(&dev->cbdev->queue_lock); - return found ? 0 : -ENODEV; + return err; } /* @@ -291,22 +305,10 @@ int cn_add_callback(struct cb_id *id, char *name, void (*callback)(void *)) { int err; struct cn_dev *dev = &cdev; - struct cn_callback *cb; - - cb = kzalloc(sizeof(*cb), GFP_KERNEL); - if (!cb) - return -ENOMEM; - - scnprintf(cb->name, sizeof(cb->name), "%s", name); - memcpy(&cb->id, id, sizeof(cb->id)); - cb->callback = callback; - - err = cn_queue_add_callback(dev->cbdev, cb); - if (err) { - kfree(cb); + err = cn_queue_add_callback(dev->cbdev, name, id, callback); + if (err) return err; - } cn_notify(id, 0); diff --git a/drivers/ide/legacy/ide-cs.c b/drivers/ide/legacy/ide-cs.c index 0ccf85fcee34..a35a58bef1a4 100644 --- a/drivers/ide/legacy/ide-cs.c +++ b/drivers/ide/legacy/ide-cs.c @@ -477,7 +477,7 @@ static struct pcmcia_device_id ide_ids[] = { PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDE", 0x547e66dc, 0x5c5ab149), PCMCIA_DEVICE_PROD_ID12("IO DATA", "PCIDEII", 0x547e66dc, 0xb3662674), PCMCIA_DEVICE_PROD_ID12("LOOKMEET", "CBIDE2 ", 0xe37be2b5, 0x8671043b), - PCMCIA_DEVICE_PROD_ID12(" ", "NinjaATA-", 0x3b6e20c8, 0xebe0bd79), + PCMCIA_DEVICE_PROD_ID2("NinjaATA-", 0xebe0bd79), PCMCIA_DEVICE_PROD_ID12("PCMCIA", "CD-ROM", 0x281f1c5d, 0x66536591), PCMCIA_DEVICE_PROD_ID12("PCMCIA", "PnPIDE", 0x281f1c5d, 0x0c694728), PCMCIA_DEVICE_PROD_ID12("SHUTTLE TECHNOLOGY LTD.", "PCCARD-IDE/ATAPI Adapter", 0x4a3f0ba0, 0x322560e1), diff --git a/drivers/infiniband/core/uverbs.h b/drivers/infiniband/core/uverbs.h index b1897bed14ad..cc124344dd2c 100644 --- a/drivers/infiniband/core/uverbs.h +++ b/drivers/infiniband/core/uverbs.h @@ -69,6 +69,7 @@ struct ib_uverbs_event_file { struct ib_uverbs_file { struct kref ref; + struct semaphore mutex; struct ib_uverbs_device *device; struct ib_ucontext *ucontext; struct ib_event_handler event_handler; diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c index e91ebde46481..562445165d2b 100644 --- a/drivers/infiniband/core/uverbs_cmd.c +++ b/drivers/infiniband/core/uverbs_cmd.c @@ -76,8 +76,9 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, struct ib_uverbs_get_context_resp resp; struct ib_udata udata; struct ib_device *ibdev = file->device->ib_dev; + struct ib_ucontext *ucontext; int i; - int ret = in_len; + int ret; if (out_len < sizeof resp) return -ENOSPC; @@ -85,45 +86,56 @@ ssize_t ib_uverbs_get_context(struct ib_uverbs_file *file, if (copy_from_user(&cmd, buf, sizeof cmd)) return -EFAULT; + down(&file->mutex); + + if (file->ucontext) { + ret = -EINVAL; + goto err; + } + INIT_UDATA(&udata, buf + sizeof cmd, (unsigned long) cmd.response + sizeof resp, in_len - sizeof cmd, out_len - sizeof resp); - file->ucontext = ibdev->alloc_ucontext(ibdev, &udata); - if (IS_ERR(file->ucontext)) { - ret = PTR_ERR(file->ucontext); - file->ucontext = NULL; - return ret; - } + ucontext = ibdev->alloc_ucontext(ibdev, &udata); + if (IS_ERR(ucontext)) + return PTR_ERR(file->ucontext); - file->ucontext->device = ibdev; - INIT_LIST_HEAD(&file->ucontext->pd_list); - INIT_LIST_HEAD(&file->ucontext->mr_list); - INIT_LIST_HEAD(&file->ucontext->mw_list); - INIT_LIST_HEAD(&file->ucontext->cq_list); - INIT_LIST_HEAD(&file->ucontext->qp_list); - INIT_LIST_HEAD(&file->ucontext->srq_list); - INIT_LIST_HEAD(&file->ucontext->ah_list); - spin_lock_init(&file->ucontext->lock); + ucontext->device = ibdev; + INIT_LIST_HEAD(&ucontext->pd_list); + INIT_LIST_HEAD(&ucontext->mr_list); + INIT_LIST_HEAD(&ucontext->mw_list); + INIT_LIST_HEAD(&ucontext->cq_list); + INIT_LIST_HEAD(&ucontext->qp_list); + INIT_LIST_HEAD(&ucontext->srq_list); + INIT_LIST_HEAD(&ucontext->ah_list); resp.async_fd = file->async_file.fd; for (i = 0; i < file->device->num_comp; ++i) if (copy_to_user((void __user *) (unsigned long) cmd.cq_fd_tab + i * sizeof (__u32), - &file->comp_file[i].fd, sizeof (__u32))) - goto err; + &file->comp_file[i].fd, sizeof (__u32))) { + ret = -EFAULT; + goto err_free; + } if (copy_to_user((void __user *) (unsigned long) cmd.response, - &resp, sizeof resp)) - goto err; + &resp, sizeof resp)) { + ret = -EFAULT; + goto err_free; + } + + file->ucontext = ucontext; + up(&file->mutex); return in_len; -err: - ibdev->dealloc_ucontext(file->ucontext); - file->ucontext = NULL; +err_free: + ibdev->dealloc_ucontext(ucontext); - return -EFAULT; +err: + up(&file->mutex); + return ret; } ssize_t ib_uverbs_query_device(struct ib_uverbs_file *file, @@ -352,9 +364,9 @@ retry: if (ret) goto err_pd; - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_add_tail(&uobj->list, &file->ucontext->pd_list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); memset(&resp, 0, sizeof resp); resp.pd_handle = uobj->id; @@ -368,9 +380,9 @@ retry: return in_len; err_list: - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); down(&ib_uverbs_idr_mutex); idr_remove(&ib_uverbs_pd_idr, uobj->id); @@ -410,9 +422,9 @@ ssize_t ib_uverbs_dealloc_pd(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_pd_idr, cmd.pd_handle); - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); kfree(uobj); @@ -512,9 +524,9 @@ retry: resp.mr_handle = obj->uobject.id; - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_add_tail(&obj->uobject.list, &file->ucontext->mr_list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { @@ -527,9 +539,9 @@ retry: return in_len; err_list: - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&obj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); err_unreg: ib_dereg_mr(mr); @@ -570,9 +582,9 @@ ssize_t ib_uverbs_dereg_mr(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_mr_idr, cmd.mr_handle); - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&memobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); ib_umem_release(file->device->ib_dev, &memobj->umem); kfree(memobj); @@ -647,9 +659,9 @@ retry: if (ret) goto err_cq; - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->cq_list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); memset(&resp, 0, sizeof resp); resp.cq_handle = uobj->uobject.id; @@ -664,9 +676,9 @@ retry: return in_len; err_list: - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); down(&ib_uverbs_idr_mutex); idr_remove(&ib_uverbs_cq_idr, uobj->uobject.id); @@ -712,9 +724,9 @@ ssize_t ib_uverbs_destroy_cq(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_cq_idr, cmd.cq_handle); - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); spin_lock_irq(&file->comp_file[0].lock); list_for_each_entry_safe(evt, tmp, &uobj->comp_list, obj_list) { @@ -847,9 +859,9 @@ retry: resp.qp_handle = uobj->uobject.id; - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->qp_list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { @@ -862,9 +874,9 @@ retry: return in_len; err_list: - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); err_destroy: ib_destroy_qp(qp); @@ -989,9 +1001,9 @@ ssize_t ib_uverbs_destroy_qp(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_qp_idr, cmd.qp_handle); - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); spin_lock_irq(&file->async_file.lock); list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) { @@ -1136,9 +1148,9 @@ retry: resp.srq_handle = uobj->uobject.id; - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_add_tail(&uobj->uobject.list, &file->ucontext->srq_list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); if (copy_to_user((void __user *) (unsigned long) cmd.response, &resp, sizeof resp)) { @@ -1151,9 +1163,9 @@ retry: return in_len; err_list: - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); err_destroy: ib_destroy_srq(srq); @@ -1227,9 +1239,9 @@ ssize_t ib_uverbs_destroy_srq(struct ib_uverbs_file *file, idr_remove(&ib_uverbs_srq_idr, cmd.srq_handle); - spin_lock_irq(&file->ucontext->lock); + down(&file->mutex); list_del(&uobj->uobject.list); - spin_unlock_irq(&file->ucontext->lock); + up(&file->mutex); spin_lock_irq(&file->async_file.lock); list_for_each_entry_safe(evt, tmp, &uobj->event_list, obj_list) { diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c index ce5bdb7af306..12511808de21 100644 --- a/drivers/infiniband/core/uverbs_main.c +++ b/drivers/infiniband/core/uverbs_main.c @@ -448,7 +448,9 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf, if (hdr.in_words * 4 != count) return -EINVAL; - if (hdr.command < 0 || hdr.command >= ARRAY_SIZE(uverbs_cmd_table)) + if (hdr.command < 0 || + hdr.command >= ARRAY_SIZE(uverbs_cmd_table) || + !uverbs_cmd_table[hdr.command]) return -EINVAL; if (!file->ucontext && @@ -484,27 +486,29 @@ static int ib_uverbs_open(struct inode *inode, struct file *filp) file = kmalloc(sizeof *file + (dev->num_comp - 1) * sizeof (struct ib_uverbs_event_file), GFP_KERNEL); - if (!file) - return -ENOMEM; + if (!file) { + ret = -ENOMEM; + goto err; + } file->device = dev; kref_init(&file->ref); + init_MUTEX(&file->mutex); file->ucontext = NULL; + kref_get(&file->ref); ret = ib_uverbs_event_init(&file->async_file, file); if (ret) - goto err; + goto err_kref; file->async_file.is_async = 1; - kref_get(&file->ref); - for (i = 0; i < dev->num_comp; ++i) { + kref_get(&file->ref); ret = ib_uverbs_event_init(&file->comp_file[i], file); if (ret) goto err_async; - kref_get(&file->ref); file->comp_file[i].is_async = 0; } @@ -524,9 +528,16 @@ err_async: ib_uverbs_event_release(&file->async_file); -err: +err_kref: + /* + * One extra kref_put() because we took a reference before the + * event file creation that failed and got us here. + */ + kref_put(&file->ref, ib_uverbs_release_file); kref_put(&file->ref, ib_uverbs_release_file); +err: + module_put(dev->ib_dev->owner); return ret; } diff --git a/drivers/infiniband/hw/mthca/mthca_cmd.c b/drivers/infiniband/hw/mthca/mthca_cmd.c index cc758a2d2bc6..f6a8ac026557 100644 --- a/drivers/infiniband/hw/mthca/mthca_cmd.c +++ b/drivers/infiniband/hw/mthca/mthca_cmd.c @@ -605,7 +605,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, err = -EINVAL; goto out; } - for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i, ++nent) { + for (i = 0; i < mthca_icm_size(&iter) / (1 << lg); ++i) { if (virt != -1) { pages[nent * 2] = cpu_to_be64(virt); virt += 1 << lg; @@ -616,7 +616,7 @@ static int mthca_map_cmd(struct mthca_dev *dev, u16 op, struct mthca_icm *icm, ts += 1 << (lg - 10); ++tc; - if (nent == MTHCA_MAILBOX_SIZE / 16) { + if (++nent == MTHCA_MAILBOX_SIZE / 16) { err = mthca_cmd(dev, mailbox->dma, nent, 0, op, CMD_TIME_CLASS_B, status); if (err || *status) diff --git a/drivers/infiniband/hw/mthca/mthca_eq.c b/drivers/infiniband/hw/mthca/mthca_eq.c index 78152a8ad17d..c81fa8e975ef 100644 --- a/drivers/infiniband/hw/mthca/mthca_eq.c +++ b/drivers/infiniband/hw/mthca/mthca_eq.c @@ -836,7 +836,7 @@ int __devinit mthca_init_eq_table(struct mthca_dev *dev) dev->eq_table.clr_mask = swab32(1 << (dev->eq_table.inta_pin & 31)); dev->eq_table.clr_int = dev->clr_base + - (dev->eq_table.inta_pin < 31 ? 4 : 0); + (dev->eq_table.inta_pin < 32 ? 4 : 0); } dev->eq_table.arm_mask = 0; diff --git a/drivers/infiniband/hw/mthca/mthca_memfree.c b/drivers/infiniband/hw/mthca/mthca_memfree.c index 1827400f189b..7bd7a4bec7b4 100644 --- a/drivers/infiniband/hw/mthca/mthca_memfree.c +++ b/drivers/infiniband/hw/mthca/mthca_memfree.c @@ -290,7 +290,7 @@ struct mthca_icm_table *mthca_alloc_icm_table(struct mthca_dev *dev, int i; u8 status; - num_icm = obj_size * nobj / MTHCA_TABLE_CHUNK_SIZE; + num_icm = (obj_size * nobj + MTHCA_TABLE_CHUNK_SIZE - 1) / MTHCA_TABLE_CHUNK_SIZE; table = kmalloc(sizeof *table + num_icm * sizeof *table->icm, GFP_KERNEL); if (!table) @@ -529,12 +529,25 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db) goto found; } + for (i = start; i != end; i += dir) + if (!dev->db_tab->page[i].db_rec) { + page = dev->db_tab->page + i; + goto alloc; + } + if (dev->db_tab->max_group1 >= dev->db_tab->min_group2 - 1) { ret = -ENOMEM; goto out; } + if (group == 0) + ++dev->db_tab->max_group1; + else + --dev->db_tab->min_group2; + page = dev->db_tab->page + end; + +alloc: page->db_rec = dma_alloc_coherent(&dev->pdev->dev, 4096, &page->mapping, GFP_KERNEL); if (!page->db_rec) { @@ -554,10 +567,6 @@ int mthca_alloc_db(struct mthca_dev *dev, int type, u32 qn, __be32 **db) } bitmap_zero(page->used, MTHCA_DB_REC_PER_PAGE); - if (group == 0) - ++dev->db_tab->max_group1; - else - --dev->db_tab->min_group2; found: j = find_first_zero_bit(page->used, MTHCA_DB_REC_PER_PAGE); diff --git a/drivers/infiniband/hw/mthca/mthca_provider.c b/drivers/infiniband/hw/mthca/mthca_provider.c index 1c1c2e230871..3f5319a46577 100644 --- a/drivers/infiniband/hw/mthca/mthca_provider.c +++ b/drivers/infiniband/hw/mthca/mthca_provider.c @@ -84,7 +84,7 @@ static int mthca_query_device(struct ib_device *ibdev, props->vendor_id = be32_to_cpup((__be32 *) (out_mad->data + 36)) & 0xffffff; props->vendor_part_id = be16_to_cpup((__be16 *) (out_mad->data + 30)); - props->hw_ver = be16_to_cpup((__be16 *) (out_mad->data + 32)); + props->hw_ver = be32_to_cpup((__be32 *) (out_mad->data + 32)); memcpy(&props->sys_image_guid, out_mad->data + 4, 8); memcpy(&props->node_guid, out_mad->data + 12, 8); diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 200a0688f717..54ec737195e0 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -230,11 +230,20 @@ static int dm_hash_insert(const char *name, const char *uuid, struct mapped_devi static void __hash_remove(struct hash_cell *hc) { + struct dm_table *table; + /* remove from the dev hash */ list_del(&hc->uuid_list); list_del(&hc->name_list); unregister_with_devfs(hc); dm_set_mdptr(hc->md, NULL); + + table = dm_get_table(hc->md); + if (table) { + dm_table_event(table); + dm_table_put(table); + } + dm_put(hc->md); if (hc->new_map) dm_table_put(hc->new_map); diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c index 785806bdb248..f9b7b32d5d5c 100644 --- a/drivers/md/dm-mpath.c +++ b/drivers/md/dm-mpath.c @@ -329,13 +329,17 @@ static int map_io(struct multipath *m, struct bio *bio, struct mpath_io *mpio, /* * If we run out of usable paths, should we queue I/O or error it? */ -static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path) +static int queue_if_no_path(struct multipath *m, unsigned queue_if_no_path, + unsigned save_old_value) { unsigned long flags; spin_lock_irqsave(&m->lock, flags); - m->saved_queue_if_no_path = m->queue_if_no_path; + if (save_old_value) + m->saved_queue_if_no_path = m->queue_if_no_path; + else + m->saved_queue_if_no_path = queue_if_no_path; m->queue_if_no_path = queue_if_no_path; if (!m->queue_if_no_path && m->queue_size) queue_work(kmultipathd, &m->process_queued_ios); @@ -677,7 +681,7 @@ static int parse_features(struct arg_set *as, struct multipath *m, return 0; if (!strnicmp(shift(as), MESG_STR("queue_if_no_path"))) - return queue_if_no_path(m, 1); + return queue_if_no_path(m, 1, 0); else { ti->error = "Unrecognised multipath feature request"; return -EINVAL; @@ -1077,7 +1081,7 @@ static void multipath_presuspend(struct dm_target *ti) { struct multipath *m = (struct multipath *) ti->private; - queue_if_no_path(m, 0); + queue_if_no_path(m, 0, 1); } /* @@ -1222,9 +1226,9 @@ static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) if (argc == 1) { if (!strnicmp(argv[0], MESG_STR("queue_if_no_path"))) - return queue_if_no_path(m, 1); + return queue_if_no_path(m, 1, 0); else if (!strnicmp(argv[0], MESG_STR("fail_if_no_path"))) - return queue_if_no_path(m, 0); + return queue_if_no_path(m, 0, 0); } if (argc != 2) diff --git a/drivers/media/dvb/frontends/tda10021.c b/drivers/media/dvb/frontends/tda10021.c index 87d5f4d8790f..eaf130e666d8 100644 --- a/drivers/media/dvb/frontends/tda10021.c +++ b/drivers/media/dvb/frontends/tda10021.c @@ -100,8 +100,8 @@ static u8 tda10021_readreg (struct tda10021_state* state, u8 reg) ret = i2c_transfer (state->i2c, msg, 2); if (ret != 2) - printk("DVB: TDA10021(%d): %s: readreg error (ret == %i)\n", - state->frontend.dvb->num, __FUNCTION__, ret); + printk("DVB: TDA10021: %s: readreg error (ret == %i)\n", + __FUNCTION__, ret); return b1[0]; } diff --git a/drivers/net/cs89x0.c b/drivers/net/cs89x0.c index cdc07ccd7332..a6078ad9b654 100644 --- a/drivers/net/cs89x0.c +++ b/drivers/net/cs89x0.c @@ -140,6 +140,7 @@ #include <asm/system.h> #include <asm/io.h> +#include <asm/irq.h> #if ALLOW_DMA #include <asm/dma.h> #endif diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 81f4aedf534c..25f85fb9df46 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -67,8 +67,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.40" -#define DRV_MODULE_RELDATE "September 15, 2005" +#define DRV_MODULE_VERSION "3.41" +#define DRV_MODULE_RELDATE "September 27, 2005" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -3389,7 +3389,8 @@ static irqreturn_t tg3_test_isr(int irq, void *dev_id, struct tg3 *tp = netdev_priv(dev); struct tg3_hw_status *sblk = tp->hw_status; - if (sblk->status & SD_STATUS_UPDATED) { + if ((sblk->status & SD_STATUS_UPDATED) || + !(tr32(TG3PCI_PCISTATE) & PCISTATE_INT_NOT_ACTIVE)) { tw32_mailbox(MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW, 0x00000001); return IRQ_RETVAL(1); @@ -5395,6 +5396,9 @@ static int tg3_set_mac_addr(struct net_device *dev, void *p) struct tg3 *tp = netdev_priv(dev); struct sockaddr *addr = p; + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); spin_lock_bh(&tp->lock); @@ -5806,6 +5810,13 @@ static int tg3_reset_hw(struct tg3 *tp) } memset(tp->hw_status, 0, TG3_HW_STATUS_SIZE); + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { + tp->tg3_flags2 &= ~TG3_FLG2_PARALLEL_DETECT; + /* reset to prevent losing 1st rx packet intermittently */ + tw32_f(MAC_RX_MODE, RX_MODE_RESET); + udelay(10); + } + tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; tw32_f(MAC_MODE, tp->mac_mode | MAC_MODE_RXSTAT_CLEAR | MAC_MODE_TXSTAT_CLEAR); @@ -5937,7 +5948,7 @@ static int tg3_reset_hw(struct tg3 *tp) tw32(MAC_LED_CTRL, tp->led_ctrl); tw32(MAC_MI_STAT, MAC_MI_STAT_LNKSTAT_ATTN_ENAB); - if (tp->tg3_flags2 & TG3_FLG2_ANY_SERDES) { + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) { tw32_f(MAC_RX_MODE, RX_MODE_RESET); udelay(10); } @@ -7360,12 +7371,17 @@ static int tg3_nway_reset(struct net_device *dev) if (!netif_running(dev)) return -EAGAIN; + if (tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) + return -EINVAL; + spin_lock_bh(&tp->lock); r = -EINVAL; tg3_readphy(tp, MII_BMCR, &bmcr); if (!tg3_readphy(tp, MII_BMCR, &bmcr) && - (bmcr & BMCR_ANENABLE)) { - tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART); + ((bmcr & BMCR_ANENABLE) || + (tp->tg3_flags2 & TG3_FLG2_PARALLEL_DETECT))) { + tg3_writephy(tp, MII_BMCR, bmcr | BMCR_ANRESTART | + BMCR_ANENABLE); r = 0; } spin_unlock_bh(&tp->lock); @@ -7927,19 +7943,32 @@ static int tg3_run_loopback(struct tg3 *tp, int loopback_mode) struct tg3_rx_buffer_desc *desc; if (loopback_mode == TG3_MAC_LOOPBACK) { + /* HW errata - mac loopback fails in some cases on 5780. + * Normal traffic and PHY loopback are not affected by + * errata. + */ + if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780) + return 0; + mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | MAC_MODE_PORT_INT_LPBACK | MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII; tw32(MAC_MODE, mac_mode); } else if (loopback_mode == TG3_PHY_LOOPBACK) { + tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX | + BMCR_SPEED1000); + udelay(40); + /* reset to prevent losing 1st rx packet intermittently */ + if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { + tw32_f(MAC_RX_MODE, RX_MODE_RESET); + udelay(10); + tw32_f(MAC_RX_MODE, tp->rx_mode); + } mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) | MAC_MODE_LINK_POLARITY | MAC_MODE_PORT_MODE_GMII; if ((tp->phy_id & PHY_ID_MASK) == PHY_ID_BCM5401) mac_mode &= ~MAC_MODE_LINK_POLARITY; tw32(MAC_MODE, mac_mode); - - tg3_writephy(tp, MII_BMCR, BMCR_LOOPBACK | BMCR_FULLDPLX | - BMCR_SPEED1000); } else return -EINVAL; @@ -10324,6 +10353,44 @@ static char * __devinit tg3_phy_string(struct tg3 *tp) }; } +static char * __devinit tg3_bus_string(struct tg3 *tp, char *str) +{ + if (tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS) { + strcpy(str, "PCI Express"); + return str; + } else if (tp->tg3_flags & TG3_FLAG_PCIX_MODE) { + u32 clock_ctrl = tr32(TG3PCI_CLOCK_CTRL) & 0x1f; + + strcpy(str, "PCIX:"); + + if ((clock_ctrl == 7) || + ((tr32(GRC_MISC_CFG) & GRC_MISC_CFG_BOARD_ID_MASK) == + GRC_MISC_CFG_BOARD_ID_5704CIOBE)) + strcat(str, "133MHz"); + else if (clock_ctrl == 0) + strcat(str, "33MHz"); + else if (clock_ctrl == 2) + strcat(str, "50MHz"); + else if (clock_ctrl == 4) + strcat(str, "66MHz"); + else if (clock_ctrl == 6) + strcat(str, "100MHz"); + else if (clock_ctrl == 7) + strcat(str, "133MHz"); + } else { + strcpy(str, "PCI:"); + if (tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) + strcat(str, "66MHz"); + else + strcat(str, "33MHz"); + } + if (tp->tg3_flags & TG3_FLAG_PCI_32BIT) + strcat(str, ":32-bit"); + else + strcat(str, ":64-bit"); + return str; +} + static struct pci_dev * __devinit tg3_find_5704_peer(struct tg3 *tp) { struct pci_dev *peer; @@ -10386,6 +10453,7 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, struct net_device *dev; struct tg3 *tp; int i, err, pci_using_dac, pm_cap; + char str[40]; if (tg3_version_printed++ == 0) printk(KERN_INFO "%s", version); @@ -10631,16 +10699,12 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, pci_set_drvdata(pdev, dev); - printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (PCI%s:%s:%s) %sBaseT Ethernet ", + printk(KERN_INFO "%s: Tigon3 [partno(%s) rev %04x PHY(%s)] (%s) %sBaseT Ethernet ", dev->name, tp->board_part_number, tp->pci_chip_rev_id, tg3_phy_string(tp), - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "X" : ""), - ((tp->tg3_flags & TG3_FLAG_PCI_HIGH_SPEED) ? - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "133MHz" : "66MHz") : - ((tp->tg3_flags & TG3_FLAG_PCIX_MODE) ? "100MHz" : "33MHz")), - ((tp->tg3_flags & TG3_FLAG_PCI_32BIT) ? "32-bit" : "64-bit"), + tg3_bus_string(tp, str), (tp->tg3_flags & TG3_FLAG_10_100_ONLY) ? "10/100" : "10/100/1000"); for (i = 0; i < 6; i++) diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index c184b773e585..2e733c60bfa4 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2246,6 +2246,7 @@ struct tg3 { (X) == PHY_ID_BCM5411 || (X) == PHY_ID_BCM5701 || \ (X) == PHY_ID_BCM5703 || (X) == PHY_ID_BCM5704 || \ (X) == PHY_ID_BCM5705 || (X) == PHY_ID_BCM5750 || \ + (X) == PHY_ID_BCM5752 || (X) == PHY_ID_BCM5780 || \ (X) == PHY_ID_BCM8002) struct tg3_hw_stats *hw_stats; diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 8de49fe57233..6deb7cc810cc 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -2458,7 +2458,6 @@ struct net_device *alloc_orinocodev(int sizeof_card, dev->watchdog_timeo = HZ; /* 1 second timeout */ dev->get_stats = orinoco_get_stats; dev->ethtool_ops = &orinoco_ethtool_ops; - dev->get_wireless_stats = orinoco_get_wireless_stats; dev->wireless_handlers = (struct iw_handler_def *)&orinoco_handler_def; dev->change_mtu = orinoco_change_mtu; dev->set_multicast_list = orinoco_set_multicast_list; @@ -4399,6 +4398,7 @@ static const struct iw_handler_def orinoco_handler_def = { .standard = orinoco_handler, .private = orinoco_private_handler, .private_args = orinoco_privtab, + .get_wireless_stats = orinoco_get_wireless_stats, }; static void orinoco_get_drvinfo(struct net_device *dev, diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index ddc741e6ecbf..36cc9a96a338 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig @@ -146,7 +146,7 @@ config I82365 config TCIC tristate "Databook TCIC host bridge support" - depends on PCMCIA + depends on PCMCIA && ISA select PCCARD_NONSTATIC help Say Y here to include support for the Databook TCIC family of PCMCIA diff --git a/drivers/pcmcia/cardbus.c b/drivers/pcmcia/cardbus.c index 1d755e20880c..3f6d51d11374 100644 --- a/drivers/pcmcia/cardbus.c +++ b/drivers/pcmcia/cardbus.c @@ -228,6 +228,11 @@ int cb_alloc(struct pcmcia_socket * s) pci_bus_size_bridges(bus); pci_bus_assign_resources(bus); cardbus_assign_irqs(bus, s->pci_irq); + + /* socket specific tune function */ + if (s->tune_bridge) + s->tune_bridge(s, bus); + pci_enable_bridges(bus); pci_bus_add_devices(bus); diff --git a/drivers/pcmcia/ti113x.h b/drivers/pcmcia/ti113x.h index fbe233e19ceb..da0b404561c9 100644 --- a/drivers/pcmcia/ti113x.h +++ b/drivers/pcmcia/ti113x.h @@ -59,6 +59,7 @@ #define TI122X_SCR_SER_STEP 0xc0000000 #define TI122X_SCR_INTRTIE 0x20000000 +#define TIXX21_SCR_TIEALL 0x10000000 #define TI122X_SCR_CBRSVD 0x00400000 #define TI122X_SCR_MRBURSTDN 0x00008000 #define TI122X_SCR_MRBURSTUP 0x00004000 @@ -153,6 +154,12 @@ /* EnE test register */ #define ENE_TEST_C9 0xc9 /* 8bit */ #define ENE_TEST_C9_TLTENABLE 0x02 +#define ENE_TEST_C9_PFENABLE_F0 0x04 +#define ENE_TEST_C9_PFENABLE_F1 0x08 +#define ENE_TEST_C9_PFENABLE (ENE_TEST_C9_PFENABLE_F0 | ENE_TEST_C9_PFENABLE_F0) +#define ENE_TEST_C9_WPDISALBLE_F0 0x40 +#define ENE_TEST_C9_WPDISALBLE_F1 0x80 +#define ENE_TEST_C9_WPDISALBLE (ENE_TEST_C9_WPDISALBLE_F0 | ENE_TEST_C9_WPDISALBLE_F1) /* * Texas Instruments CardBus controller overrides. @@ -618,6 +625,7 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket) int devfn; unsigned int state; int ret = 1; + u32 sysctl; /* catch the two-slot controllers */ switch (socket->dev->device) { @@ -640,6 +648,24 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket) */ break; + case PCI_DEVICE_ID_TI_X515: + case PCI_DEVICE_ID_TI_X420: + case PCI_DEVICE_ID_TI_X620: + case PCI_DEVICE_ID_TI_XX21_XX11: + case PCI_DEVICE_ID_TI_7410: + case PCI_DEVICE_ID_TI_7610: + /* + * those are either single or dual slot CB with additional functions + * like 1394, smartcard reader, etc. check the TIEALL flag for them + * the TIEALL flag binds the IRQ of all functions toghether. + * we catch the single slot variants later. + */ + sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL); + if (sysctl & TIXX21_SCR_TIEALL) + return 0; + + break; + /* single-slot controllers have the 2nd slot empty always :) */ default: return 1; @@ -652,6 +678,15 @@ static int ti12xx_2nd_slot_empty(struct yenta_socket *socket) if (!func) return 1; + /* + * check that the device id of both slots match. this is needed for the + * XX21 and the XX11 controller that share the same device id for single + * and dual slot controllers. return '2nd slot empty'. we already checked + * if the interrupt is tied to another function. + */ + if (socket->dev->device != func->device) + goto out; + slot2 = pci_get_drvdata(func); if (!slot2) goto out; @@ -791,16 +826,6 @@ static int ti12xx_override(struct yenta_socket *socket) config_writel(socket, TI113X_SYSTEM_CONTROL, val); /* - * for EnE bridges only: clear testbit TLTEnable. this makes the - * RME Hammerfall DSP sound card working. - */ - if (socket->dev->vendor == PCI_VENDOR_ID_ENE) { - u8 test_c9 = config_readb(socket, ENE_TEST_C9); - test_c9 &= ~ENE_TEST_C9_TLTENABLE; - config_writeb(socket, ENE_TEST_C9, test_c9); - } - - /* * Yenta expects controllers to use CSCINT to route * CSC interrupts to PCI rather than INTVAL. */ @@ -841,5 +866,75 @@ static int ti1250_override(struct yenta_socket *socket) return ti12xx_override(socket); } + +/** + * EnE specific part. EnE bridges are register compatible with TI bridges but + * have their own test registers and more important their own little problems. + * Some fixup code to make everybody happy (TM). + */ + +/** + * set/clear various test bits: + * Defaults to clear the bit. + * - mask (u8) defines what bits to change + * - bits (u8) is the values to change them to + * -> it's + * current = (current & ~mask) | bits + */ +/* pci ids of devices that wants to have the bit set */ +#define DEVID(_vend,_dev,_subvend,_subdev,mask,bits) { \ + .vendor = _vend, \ + .device = _dev, \ + .subvendor = _subvend, \ + .subdevice = _subdev, \ + .driver_data = ((mask) << 8 | (bits)), \ + } +static struct pci_device_id ene_tune_tbl[] = { + /* Echo Audio products based on motorola DSP56301 and DSP56361 */ + DEVID(PCI_VENDOR_ID_MOTOROLA, 0x1801, 0xECC0, PCI_ANY_ID, + ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE), + DEVID(PCI_VENDOR_ID_MOTOROLA, 0x3410, 0xECC0, PCI_ANY_ID, + ENE_TEST_C9_TLTENABLE | ENE_TEST_C9_PFENABLE, ENE_TEST_C9_TLTENABLE), + + {} +}; + +static void ene_tune_bridge(struct pcmcia_socket *sock, struct pci_bus *bus) +{ + struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); + struct pci_dev *dev; + struct pci_device_id *id = NULL; + u8 test_c9, old_c9, mask, bits; + + list_for_each_entry(dev, &bus->devices, bus_list) { + id = (struct pci_device_id *) pci_match_id(ene_tune_tbl, dev); + if (id) + break; + } + + test_c9 = old_c9 = config_readb(socket, ENE_TEST_C9); + if (id) { + mask = (id->driver_data >> 8) & 0xFF; + bits = id->driver_data & 0xFF; + + test_c9 = (test_c9 & ~mask) | bits; + } + else + /* default to clear TLTEnable bit, old behaviour */ + test_c9 &= ~ENE_TEST_C9_TLTENABLE; + + printk(KERN_INFO "yenta EnE: chaning testregister 0xC9, %02x -> %02x\n", old_c9, test_c9); + config_writeb(socket, ENE_TEST_C9, test_c9); +} + + +static int ene_override(struct yenta_socket *socket) +{ + /* install tune_bridge() function */ + socket->socket.tune_bridge = ene_tune_bridge; + + return ti1250_override(socket); +} + #endif /* _LINUX_TI113X_H */ diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c index ba4d78e5b121..db9f952f9e3c 100644 --- a/drivers/pcmcia/yenta_socket.c +++ b/drivers/pcmcia/yenta_socket.c @@ -559,12 +559,6 @@ static void yenta_interrogate(struct yenta_socket *socket) static int yenta_sock_init(struct pcmcia_socket *sock) { struct yenta_socket *socket = container_of(sock, struct yenta_socket, socket); - u16 bridge; - - bridge = config_readw(socket, CB_BRIDGE_CONTROL) & ~CB_BRIDGE_INTR; - if (!socket->cb_irq) - bridge |= CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge); exca_writeb(socket, I365_GBLCTL, 0x00); exca_writeb(socket, I365_GENCTL, 0x00); @@ -819,6 +813,7 @@ enum { CARDBUS_TYPE_TOPIC95, CARDBUS_TYPE_TOPIC97, CARDBUS_TYPE_O2MICRO, + CARDBUS_TYPE_ENE, }; /* @@ -865,6 +860,12 @@ static struct cardbus_type cardbus_type[] = { .override = o2micro_override, .restore_state = o2micro_restore_state, }, + [CARDBUS_TYPE_ENE] = { + .override = ene_override, + .save_state = ti_save_state, + .restore_state = ti_restore_state, + .sock_init = ti_init, + }, }; @@ -883,16 +884,8 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas { int i; unsigned long val; - u16 bridge_ctrl; u32 mask; - /* Set up ISA irq routing to probe the ISA irqs.. */ - bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL); - if (!(bridge_ctrl & CB_BRIDGE_INTR)) { - bridge_ctrl |= CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl); - } - /* * Probe for usable interrupts using the force * register to generate bogus card status events. @@ -914,9 +907,6 @@ static unsigned int yenta_probe_irq(struct yenta_socket *socket, u32 isa_irq_mas mask = probe_irq_mask(val) & 0xffff; - bridge_ctrl &= ~CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl); - return mask; } @@ -944,18 +934,11 @@ static irqreturn_t yenta_probe_handler(int irq, void *dev_id, struct pt_regs *re /* probes the PCI interrupt, use only on override functions */ static int yenta_probe_cb_irq(struct yenta_socket *socket) { - u16 bridge_ctrl; - if (!socket->cb_irq) return -1; socket->probe_status = 0; - /* disable ISA interrupts */ - bridge_ctrl = config_readw(socket, CB_BRIDGE_CONTROL); - bridge_ctrl &= ~CB_BRIDGE_INTR; - config_writew(socket, CB_BRIDGE_CONTROL, bridge_ctrl); - if (request_irq(socket->cb_irq, yenta_probe_handler, SA_SHIRQ, "yenta", socket)) { printk(KERN_WARNING "Yenta: request_irq() in yenta_probe_cb_irq() failed!\n"); return -1; @@ -966,7 +949,7 @@ static int yenta_probe_cb_irq(struct yenta_socket *socket) cb_writel(socket, CB_SOCKET_EVENT, -1); cb_writel(socket, CB_SOCKET_MASK, CB_CSTSMASK); cb_writel(socket, CB_SOCKET_FORCE, CB_FCARDSTS); - + msleep(100); /* disable interrupts */ @@ -1004,11 +987,12 @@ static void yenta_config_init(struct yenta_socket *socket) { u16 bridge; struct pci_dev *dev = socket->dev; + struct pci_bus_region region; - pci_set_power_state(socket->dev, 0); + pcibios_resource_to_bus(socket->dev, ®ion, &dev->resource[0]); config_writel(socket, CB_LEGACY_MODE_BASE, 0); - config_writel(socket, PCI_BASE_ADDRESS_0, dev->resource[0].start); + config_writel(socket, PCI_BASE_ADDRESS_0, region.start); config_writew(socket, PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_MEMORY | @@ -1031,8 +1015,8 @@ static void yenta_config_init(struct yenta_socket *socket) * - PCI interrupts enabled if a PCI interrupt exists.. */ bridge = config_readw(socket, CB_BRIDGE_CONTROL); - bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_INTR | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); - bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN | CB_BRIDGE_INTR; + bridge &= ~(CB_BRIDGE_CRST | CB_BRIDGE_PREFETCH1 | CB_BRIDGE_ISAEN | CB_BRIDGE_VGAEN); + bridge |= CB_BRIDGE_PREFETCH0 | CB_BRIDGE_POSTEN; config_writew(socket, CB_BRIDGE_CONTROL, bridge); } @@ -1265,10 +1249,22 @@ static struct pci_device_id yenta_table [] = { CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1250, TI1250), CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_1410, TI1250), - CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, TI12XX), - CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, TI12XX), - CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, TI1250), - CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_XX21_XX11, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X515, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X420, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_X620, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7410, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7510, TI12XX), + CB_ID(PCI_VENDOR_ID_TI, PCI_DEVICE_ID_TI_7610, TI12XX), + + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_710, TI12XX), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_712, TI12XX), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_720, TI12XX), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_722, TI12XX), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1211, ENE), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1225, ENE), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1410, ENE), + CB_ID(PCI_VENDOR_ID_ENE, PCI_DEVICE_ID_ENE_1420, ENE), CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C465, RICOH), CB_ID(PCI_VENDOR_ID_RICOH, PCI_DEVICE_ID_RICOH_RL5C466, RICOH), diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c index 1ae0b381c162..2c7d3ef76e8e 100644 --- a/drivers/serial/serial_cs.c +++ b/drivers/serial/serial_cs.c @@ -859,6 +859,7 @@ static struct pcmcia_device_id serial_ids[] = { PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "DP83903.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "3CXEM556.cis"), PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "3CXEM556.cis"), + PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */ PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "MT5634ZLX.cis"), PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "COMpad4.cis"), PCMCIA_DEVICE_CIS_PROD_ID123("ADVANTECH", "COMpad-32/85", "1.0", 0x96913a85, 0x8fbe92ae, 0x0877b627, "COMpad2.cis"), |