From 3203f94a25ea04b3052d22c7be9518538862d88f Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Sun, 2 Apr 2006 04:14:57 -0300 Subject: V4L/DVB (3704): Fix some errors on bttv_risc_overlay There are tree mistakes on bttv_risc_overlay. 1) When skip_odd is true, the number of lines for which instructions are written is (height+1)/2, not height/2. 2) This occurs when clipping: the number of instruction bytes written can be as much as 8 + 12*nclips, not 8 + 8*nclips, as currently estimated. 3) Coverity check were wrong with nskips=0, since it means that it can clipped at most one line. Signed-off-by: Duncan Sands Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-risc.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/media/video/bt8xx/bttv-risc.c b/drivers/media/video/bt8xx/bttv-risc.c index 16323a5d68acc4..afcfe71e37928c 100644 --- a/drivers/media/video/bt8xx/bttv-risc.c +++ b/drivers/media/video/bt8xx/bttv-risc.c @@ -233,7 +233,7 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, const struct bttv_format *fmt, struct bttv_overlay *ov, int skip_even, int skip_odd) { - int instructions,rc,line,maxy,start,end,skip,nskips; + int dwords,rc,line,maxy,start,end,skip,nskips; struct btcx_skiplist *skips; u32 *rp,ri,ra; u32 addr; @@ -242,12 +242,12 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, if (NULL == (skips = kmalloc(sizeof(*skips) * ov->nclips,GFP_KERNEL))) return -ENOMEM; - /* estimate risc mem: worst case is (clip+1) * lines instructions + /* estimate risc mem: worst case is (1.5*clip+1) * lines instructions + sync + jump (all 2 dwords) */ - instructions = (ov->nclips + 1) * - ((skip_even || skip_odd) ? ov->w.height>>1 : ov->w.height); - instructions += 2; - if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,instructions*8)) < 0) { + dwords = (3 * ov->nclips + 2) * + ((skip_even || skip_odd) ? (ov->w.height+1)>>1 : ov->w.height); + dwords += 4; + if ((rc = btcx_riscmem_alloc(btv->c.pci,risc,dwords*4)) < 0) { kfree(skips); return rc; } @@ -276,8 +276,6 @@ bttv_risc_overlay(struct bttv *btv, struct btcx_riscmem *risc, if (line > maxy) btcx_calc_skips(line, ov->w.width, &maxy, skips, &nskips, ov->clips, ov->nclips); - else - nskips = 0; /* write out risc code */ for (start = 0, skip = 0; start < ov->w.width; start = end) { -- cgit 1.2.3-korg From f47f4763cde162656448fcd1ada9d5e8101a00d2 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Tue, 4 Apr 2006 09:41:47 -0300 Subject: V4L/DVB (3725): Fix mutex in dvb_register_device to work. This mutex is meant to stop two devices getting the same ID. dvbdev_get_free_id() scans the list of already allocated devices to find a free id. Unfortunately, since the mutex is unlocked before the card is added to the above list, it is still possible for two of them to get the same id. Its debatable whether this mutex lock is actually needed, but I'm unwilling to just remove it in case something does depend on it. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvbdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/dvb-core/dvbdev.c b/drivers/media/dvb/dvb-core/dvbdev.c index 96fe0ecae25089..3852430d0260e6 100644 --- a/drivers/media/dvb/dvb-core/dvbdev.c +++ b/drivers/media/dvb/dvb-core/dvbdev.c @@ -219,8 +219,6 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, return -ENOMEM; } - mutex_unlock(&dvbdev_register_lock); - memcpy(dvbdev, template, sizeof(struct dvb_device)); dvbdev->type = type; dvbdev->id = id; @@ -231,6 +229,8 @@ int dvb_register_device(struct dvb_adapter *adap, struct dvb_device **pdvbdev, list_add_tail (&dvbdev->list_head, &adap->device_list); + mutex_unlock(&dvbdev_register_lock); + devfs_mk_cdev(MKDEV(DVB_MAJOR, nums2minor(adap->num, type, id)), S_IFCHR | S_IRUSR | S_IWUSR, "dvb/adapter%d/%s%d", adap->num, dnames[type], id); -- cgit 1.2.3-korg From 96b194c12e1206e5cdccf55ea71bb38ce1124bd9 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Wed, 5 Apr 2006 14:09:45 -0300 Subject: V4L/DVB (3726): Fix TT budget-ci 1.1 CI slots It turns out the firmware on the TT budget-ci 1.1 slots doesn't generate interrupts. This patch adds support for this using polling mode on these slots. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-ci.c | 105 +++++++++++++++++++++++++++++------- 1 file changed, 85 insertions(+), 20 deletions(-) diff --git a/drivers/media/dvb/ttpci/budget-ci.c b/drivers/media/dvb/ttpci/budget-ci.c index 5f91036f5b874a..e64a609cf4ff48 100644 --- a/drivers/media/dvb/ttpci/budget-ci.c +++ b/drivers/media/dvb/ttpci/budget-ci.c @@ -71,6 +71,7 @@ struct budget_ci { struct tasklet_struct msp430_irq_tasklet; struct tasklet_struct ciintf_irq_tasklet; int slot_status; + int ci_irq; struct dvb_ca_en50221 ca; char ir_dev_name[50]; u8 tuner_pll_address; /* used for philips_tdm1316l configs */ @@ -276,8 +277,10 @@ static int ciintf_slot_reset(struct dvb_ca_en50221 *ca, int slot) if (slot != 0) return -EINVAL; - // trigger on RISING edge during reset so we know when READY is re-asserted - saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + if (budget_ci->ci_irq) { + // trigger on RISING edge during reset so we know when READY is re-asserted + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + } budget_ci->slot_status = SLOTSTATUS_RESET; ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0); msleep(1); @@ -370,11 +373,50 @@ static void ciintf_interrupt(unsigned long data) } } +static int ciintf_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open) +{ + struct budget_ci *budget_ci = (struct budget_ci *) ca->data; + unsigned int flags; + + // ensure we don't get spurious IRQs during initialisation + if (!budget_ci->budget.ci_present) + return -EINVAL; + + // read the CAM status + flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); + if (flags & CICONTROL_CAMDETECT) { + // mark it as present if it wasn't before + if (budget_ci->slot_status & SLOTSTATUS_NONE) { + budget_ci->slot_status = SLOTSTATUS_PRESENT; + } + + // during a RESET, we check if we can read from IO memory to see when CAM is ready + if (budget_ci->slot_status & SLOTSTATUS_RESET) { + if (ciintf_read_attribute_mem(ca, slot, 0) == 0x1d) { + budget_ci->slot_status = SLOTSTATUS_READY; + } + } + } else { + budget_ci->slot_status = SLOTSTATUS_NONE; + } + + if (budget_ci->slot_status != SLOTSTATUS_NONE) { + if (budget_ci->slot_status & SLOTSTATUS_READY) { + return DVB_CA_EN50221_POLL_CAM_PRESENT | DVB_CA_EN50221_POLL_CAM_READY; + } + return DVB_CA_EN50221_POLL_CAM_PRESENT; + } + + return 0; +} + static int ciintf_init(struct budget_ci *budget_ci) { struct saa7146_dev *saa = budget_ci->budget.dev; int flags; int result; + int ci_version; + int ca_flags; memset(&budget_ci->ca, 0, sizeof(struct dvb_ca_en50221)); @@ -382,16 +424,29 @@ static int ciintf_init(struct budget_ci *budget_ci) saa7146_write(saa, MC1, saa7146_read(saa, MC1) | (0x800 << 16) | 0x800); // test if it is there - if ((ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0) & 0xa0) != 0xa0) { + ci_version = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CIVERSION, 1, 1, 0); + if ((ci_version & 0xa0) != 0xa0) { result = -ENODEV; goto error; } + // determine whether a CAM is present or not flags = ttpci_budget_debiread(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 1, 0); budget_ci->slot_status = SLOTSTATUS_NONE; if (flags & CICONTROL_CAMDETECT) budget_ci->slot_status = SLOTSTATUS_PRESENT; + // version 0xa2 of the CI firmware doesn't generate interrupts + if (ci_version == 0xa2) { + ca_flags = 0; + budget_ci->ci_irq = 0; + } else { + ca_flags = DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | + DVB_CA_EN50221_FLAG_IRQ_FR | + DVB_CA_EN50221_FLAG_IRQ_DA; + budget_ci->ci_irq = 1; + } + // register CI interface budget_ci->ca.owner = THIS_MODULE; budget_ci->ca.read_attribute_mem = ciintf_read_attribute_mem; @@ -401,23 +456,27 @@ static int ciintf_init(struct budget_ci *budget_ci) budget_ci->ca.slot_reset = ciintf_slot_reset; budget_ci->ca.slot_shutdown = ciintf_slot_shutdown; budget_ci->ca.slot_ts_enable = ciintf_slot_ts_enable; + budget_ci->ca.poll_slot_status = ciintf_poll_slot_status; budget_ci->ca.data = budget_ci; if ((result = dvb_ca_en50221_init(&budget_ci->budget.dvb_adapter, &budget_ci->ca, - DVB_CA_EN50221_FLAG_IRQ_CAMCHANGE | - DVB_CA_EN50221_FLAG_IRQ_FR | - DVB_CA_EN50221_FLAG_IRQ_DA, 1)) != 0) { + ca_flags, 1)) != 0) { printk("budget_ci: CI interface detected, but initialisation failed.\n"); goto error; } + // Setup CI slot IRQ - tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci); - if (budget_ci->slot_status != SLOTSTATUS_NONE) { - saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); - } else { - saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + if (budget_ci->ci_irq) { + tasklet_init(&budget_ci->ciintf_irq_tasklet, ciintf_interrupt, (unsigned long) budget_ci); + if (budget_ci->slot_status != SLOTSTATUS_NONE) { + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQLO); + } else { + saa7146_setgpio(saa, 0, SAA7146_GPIO_IRQHI); + } + saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); } - saa7146_write(saa, IER, saa7146_read(saa, IER) | MASK_03); + + // enable interface ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, CICONTROL_RESET, 1, 0); @@ -426,10 +485,12 @@ static int ciintf_init(struct budget_ci *budget_ci) budget_ci->budget.ci_present = 1; // forge a fake CI IRQ so the CAM state is setup correctly - flags = DVB_CA_EN50221_CAMCHANGE_REMOVED; - if (budget_ci->slot_status != SLOTSTATUS_NONE) - flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; - dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags); + if (budget_ci->ci_irq) { + flags = DVB_CA_EN50221_CAMCHANGE_REMOVED; + if (budget_ci->slot_status != SLOTSTATUS_NONE) + flags = DVB_CA_EN50221_CAMCHANGE_INSERTED; + dvb_ca_en50221_camchange_irq(&budget_ci->ca, 0, flags); + } return 0; @@ -443,9 +504,13 @@ static void ciintf_deinit(struct budget_ci *budget_ci) struct saa7146_dev *saa = budget_ci->budget.dev; // disable CI interrupts - saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); - saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); - tasklet_kill(&budget_ci->ciintf_irq_tasklet); + if (budget_ci->ci_irq) { + saa7146_write(saa, IER, saa7146_read(saa, IER) & ~MASK_03); + saa7146_setgpio(saa, 0, SAA7146_GPIO_INPUT); + tasklet_kill(&budget_ci->ciintf_irq_tasklet); + } + + // reset interface ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, 0, 1, 0); msleep(1); ttpci_budget_debiwrite(&budget_ci->budget, DEBICICTL, DEBIADDR_CICONTROL, 1, @@ -473,7 +538,7 @@ static void budget_ci_irq(struct saa7146_dev *dev, u32 * isr) if (*isr & MASK_10) ttpci_budget_irq10_handler(dev, isr); - if ((*isr & MASK_03) && (budget_ci->budget.ci_present)) + if ((*isr & MASK_03) && (budget_ci->budget.ci_present) && (budget_ci->ci_irq)) tasklet_schedule(&budget_ci->ciintf_irq_tasklet); } -- cgit 1.2.3-korg From a7286033f951ebc78527e63f335516ea2f95e142 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 4 Apr 2006 22:23:04 -0300 Subject: V4L/DVB (3731): Kbuild: drivers/media/video/bt8xx: remove $(src) from include path - replaced '$(src)/..' with 'drivers/media/video' Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile index db641a36b197af..a096a03418aaf4 100644 --- a/drivers/media/video/bt8xx/Makefile +++ b/drivers/media/video/bt8xx/Makefile @@ -8,5 +8,5 @@ bttv-objs := bttv-driver.o bttv-cards.o bttv-if.o \ obj-$(CONFIG_VIDEO_BT848) += bttv.o -EXTRA_CFLAGS += -I$(src)/.. +EXTRA_CFLAGS += -Idrivers/media/video EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core -- cgit 1.2.3-korg From 7a766f9ddd74b50d6069f054a3004ece0439f5c1 Mon Sep 17 00:00:00 2001 From: Sergey Vlasov Date: Fri, 7 Apr 2006 10:04:56 -0300 Subject: V4L/DVB (3738): Saa7134: Fix oops with disable_ir=1 When disable_ir=1 parameter is used, or when saa7134_input_init1() fails for any other reason, dev->remote will remain NULL, and the driver will oops in saa7134_hwinit2(). Therefore dev->remote must be checked before dereferencing. Signed-off-by: Sergey Vlasov Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 13de05532e0ac7..f0c2111f14ad1f 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -548,6 +548,8 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) if (report & SAA7134_IRQ_REPORT_GPIO16) { switch (dev->has_remote) { case SAA7134_REMOTE_GPIO: + if (!dev->remote) + break; if (dev->remote->mask_keydown & 0x10000) { saa7134_input_irq(dev); } @@ -564,6 +566,8 @@ static irqreturn_t saa7134_irq(int irq, void *dev_id, struct pt_regs *regs) if (report & SAA7134_IRQ_REPORT_GPIO18) { switch (dev->has_remote) { case SAA7134_REMOTE_GPIO: + if (!dev->remote) + break; if ((dev->remote->mask_keydown & 0x40000) || (dev->remote->mask_keyup & 0x40000)) { saa7134_input_irq(dev); @@ -676,7 +680,7 @@ static int saa7134_hwinit2(struct saa7134_dev *dev) SAA7134_IRQ2_INTE_PE | SAA7134_IRQ2_INTE_AR; - if (dev->has_remote == SAA7134_REMOTE_GPIO) { + if (dev->has_remote == SAA7134_REMOTE_GPIO && dev->remote) { if (dev->remote->mask_keydown & 0x10000) irq2_mask |= SAA7134_IRQ2_INTE_GPIO16; else if (dev->remote->mask_keydown & 0x40000) -- cgit 1.2.3-korg From 71a8dffb07ae40af87b2f7b93dcd5810e2c558bf Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Thu, 6 Apr 2006 09:42:46 -0300 Subject: V4L/DVB (3740): Fix oops in budget-av with CI Now that the CI code reinitialises the frontend, need to move the CI initialisation to after the frontend init in order to ensure the frontend is always in a good state. Fixes an oops caused by the frontend being NULL as well. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/ttpci/budget-av.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/ttpci/budget-av.c b/drivers/media/dvb/ttpci/budget-av.c index 8efe3ce5f66c83..8a7cd7d505cf53 100644 --- a/drivers/media/dvb/ttpci/budget-av.c +++ b/drivers/media/dvb/ttpci/budget-av.c @@ -1190,8 +1190,6 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio SAA7146_HPS_SYNC_PORT_A); saa7113_setinput(budget_av, 0); - } else { - ciintf_init(budget_av); } /* fixme: find some sane values here... */ @@ -1211,6 +1209,10 @@ static int budget_av_attach(struct saa7146_dev *dev, struct saa7146_pci_extensio budget_av->budget.dvb_adapter.priv = budget_av; frontend_init(budget_av); + if (!budget_av->has_saa7113) { + ciintf_init(budget_av); + } + return 0; } -- cgit 1.2.3-korg From 6445401673fe486ba15a39370d41100df6d73b1f Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Thu, 6 Apr 2006 14:32:23 -0300 Subject: V4L/DVB (3742): Set tone/voltage again if the frontend was reinitialised Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 4f8f257e67951f..a051790161b095 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -106,6 +106,8 @@ struct dvb_frontend_private { unsigned long tune_mode_flags; unsigned int delay; unsigned int reinitialise; + int tone; + int voltage; /* swzigzag values */ unsigned int state; @@ -537,6 +539,12 @@ static int dvb_frontend_thread(void *data) if (fepriv->reinitialise) { dvb_frontend_init(fe); + if (fepriv->tone != -1) { + fe->ops->set_tone(fe, fepriv->tone); + } + if (fepriv->voltage != -1) { + fe->ops->set_voltage(fe, fepriv->voltage); + } fepriv->reinitialise = 0; } @@ -788,6 +796,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, case FE_SET_TONE: if (fe->ops->set_tone) { err = fe->ops->set_tone(fe, (fe_sec_tone_mode_t) parg); + fepriv->tone = (fe_sec_tone_mode_t) parg; fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } @@ -796,6 +805,7 @@ static int dvb_frontend_ioctl(struct inode *inode, struct file *file, case FE_SET_VOLTAGE: if (fe->ops->set_voltage) { err = fe->ops->set_voltage(fe, (fe_sec_voltage_t) parg); + fepriv->voltage = (fe_sec_voltage_t) parg; fepriv->state = FESTATE_DISEQC; fepriv->status = 0; } @@ -995,6 +1005,8 @@ static int dvb_frontend_open(struct inode *inode, struct file *file) /* normal tune mode when opened R/W */ fepriv->tune_mode_flags &= ~FE_TUNE_MODE_ONESHOT; + fepriv->tone = -1; + fepriv->voltage = -1; } return ret; -- cgit 1.2.3-korg From a064fad337e27cfe74c04509e88ef4d2c9138ec2 Mon Sep 17 00:00:00 2001 From: Andrew de Quincey Date: Thu, 6 Apr 2006 17:05:46 -0300 Subject: V4L/DVB (3743): Fix some more potential oopses Spotted a couple more places where it fails to check if dvb_register_adapter() fails. Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/cinergyT2/cinergyT2.c | 5 ++++- drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c | 6 +++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/media/dvb/cinergyT2/cinergyT2.c b/drivers/media/dvb/cinergyT2/cinergyT2.c index 71b575dc22bdb2..9325d039ea652c 100644 --- a/drivers/media/dvb/cinergyT2/cinergyT2.c +++ b/drivers/media/dvb/cinergyT2/cinergyT2.c @@ -902,7 +902,10 @@ static int cinergyt2_probe (struct usb_interface *intf, return -ENOMEM; } - dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE); + if ((err = dvb_register_adapter(&cinergyt2->adapter, DRIVER_NAME, THIS_MODULE)) < 0) { + kfree(cinergyt2); + return err; + } cinergyt2->demux.priv = cinergyt2; cinergyt2->demux.filternum = 256; diff --git a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c index 248fdc7accfb12..6ceae38125c754 100644 --- a/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c +++ b/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c @@ -1507,7 +1507,11 @@ static int ttusb_probe(struct usb_interface *intf, const struct usb_device_id *i mutex_unlock(&ttusb->semi2c); - dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE); + if ((result = dvb_register_adapter(&ttusb->adapter, "Technotrend/Hauppauge Nova-USB", THIS_MODULE)) < 0) { + ttusb_free_iso_urbs(ttusb); + kfree(ttusb); + return result; + } ttusb->adapter.priv = ttusb; /* i2c */ -- cgit 1.2.3-korg From f1de3e7c5c9d8e65937addce83b42331bdad15a1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 7 Apr 2006 18:50:09 -0300 Subject: V4L/DVB (3745): Fix a bug at pluto2 Makefile When pluto2 were selected, all other module dependencies were just discarded. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/pluto2/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile index 86ca84b2be6e1a..ce6a9aaf937e9e 100644 --- a/drivers/media/dvb/pluto2/Makefile +++ b/drivers/media/dvb/pluto2/Makefile @@ -1,3 +1,3 @@ -obj-$(CONFIG_DVB_PLUTO2) = pluto2.o +obj-$(CONFIG_DVB_PLUTO2) += pluto2.o EXTRA_CFLAGS = -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/ -- cgit 1.2.3-korg From 9175b8544ff7b73b158df370acc1d828b28b80b7 Mon Sep 17 00:00:00 2001 From: Trent Piepho Date: Mon, 10 Apr 2006 09:40:37 -0300 Subject: V4L/DVB (3763): Bug fix: Wrong tuner was used pcHDTV HD-3000 card It looks like the HD3000 was prototyped with the 7610 tuner when the driver was developed, but the cards appear to have always shipped with the 7612 tuner and the driver was never adjusted for it. The definition needs to be corrected. - The HD-3000 was prototyped with a Thomson DTT7610, but production versions used a DTT7612 tuner. - This patch changes both dvb-pll settings and V4L tuner type. Signed-off-by: Trent Piepho Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-cards.c | 2 +- drivers/media/video/cx88/cx88-dvb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index c7042cf4123182..f80154b87d2297 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -564,7 +564,7 @@ struct cx88_board cx88_boards[] = { }, [CX88_BOARD_PCHDTV_HD3000] = { .name = "pcHDTV HD3000 HDTV", - .tuner_type = TUNER_THOMSON_DTT7610, + .tuner_type = TUNER_THOMSON_DTT761X, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index f0ea9b5cdbc234..3619a449aefd91 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -372,7 +372,7 @@ static int or51132_set_ts_param(struct dvb_frontend* fe, static struct or51132_config pchdtv_hd3000 = { .demod_address = 0x15, .pll_address = 0x61, - .pll_desc = &dvb_pll_thomson_dtt7610, + .pll_desc = &dvb_pll_thomson_dtt761x, .set_ts_params = or51132_set_ts_param, }; #endif -- cgit 1.2.3-korg From bba3ad76a82eb458d31b136fa2414216e20c99cc Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Tue, 11 Apr 2006 10:18:57 -0300 Subject: V4L/DVB (3766): Correct buffer size calculations in cx88-core.c The computation in cx88_risc_buffer suffers from the mistake: a non-zero padding value can cause more page borders to be crossed, leading to big buffer over-runs. This patch changes the additive constant from 3 + 4 to 4 It also changees the constant in cx88_risc_databuffer from 3 + 4 to 2, because 2 dwords are the correct vaule. Signed-off-by: Duncan Sands Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx88/cx88-core.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/drivers/media/video/cx88/cx88-core.c b/drivers/media/video/cx88/cx88-core.c index 2c3d9f1999be6e..e1092d5d4628de 100644 --- a/drivers/media/video/cx88/cx88-core.c +++ b/drivers/media/video/cx88/cx88-core.c @@ -146,9 +146,11 @@ int cx88_risc_buffer(struct pci_dev *pci, struct btcx_riscmem *risc, fields++; /* estimate risc mem: worst case is one write per page border + - one write per scan line + syncs + jump (all 2 dwords) */ - instructions = (bpl * lines * fields) / PAGE_SIZE + lines * fields; - instructions += 3 + 4; + one write per scan line + syncs + jump (all 2 dwords). Padding + can cause next bpl to start close to a page border. First DMA + region may be smaller than PAGE_SIZE */ + instructions = fields * (1 + ((bpl + padding) * lines) / PAGE_SIZE + lines); + instructions += 2; if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0) return rc; @@ -176,9 +178,11 @@ int cx88_risc_databuffer(struct pci_dev *pci, struct btcx_riscmem *risc, int rc; /* estimate risc mem: worst case is one write per page border + - one write per scan line + syncs + jump (all 2 dwords) */ - instructions = (bpl * lines) / PAGE_SIZE + lines; - instructions += 3 + 4; + one write per scan line + syncs + jump (all 2 dwords). Here + there is no padding and no sync. First DMA region may be smaller + than PAGE_SIZE */ + instructions = 1 + (bpl * lines) / PAGE_SIZE + lines; + instructions += 1; if ((rc = btcx_riscmem_alloc(pci,risc,instructions*8)) < 0) return rc; -- cgit 1.2.3-korg From ea76ce526ec1af3e07f3dd9107ca93f0c82fc9c9 Mon Sep 17 00:00:00 2001 From: Jose Alberto Reguero Date: Tue, 11 Apr 2006 10:19:25 -0300 Subject: V4L/DVB (3767): Pvr350 tv out (saa7127) Witout this patch tv out don't work properly with my pvr350 card. Signed-off-by: Jose Alberto Reguero Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7127.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/saa7127.c b/drivers/media/video/saa7127.c index 133f9e5252fec0..c271e2e1410572 100644 --- a/drivers/media/video/saa7127.c +++ b/drivers/media/video/saa7127.c @@ -142,6 +142,7 @@ struct i2c_reg_value { static const struct i2c_reg_value saa7129_init_config_extra[] = { { SAA7127_REG_OUTPUT_PORT_CONTROL, 0x38 }, { SAA7127_REG_VTRIG, 0xfa }, + { 0, 0 } }; static const struct i2c_reg_value saa7127_init_config_common[] = { -- cgit 1.2.3-korg From cd41e28e2d0f198ad56840bf8ba13cb41b129bab Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 9 Apr 2006 15:43:41 -0300 Subject: V4L/DVB (3774): Create V4L1 config options V4L1 API is depreciated and should be removed soon from kernel. This patch adds two new options, one to disable V4L1 drivers, and another to disable V4L1 compat module. This way, it would be easy to check what still depends on V4L1 stuff, allowing also to test if app works fine with V4L2 only support. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/Kconfig | 45 ++++++++++++++++--- drivers/media/common/Kconfig | 1 + drivers/media/dvb/ttpci/Kconfig | 12 +++--- drivers/media/radio/Kconfig | 30 ++++++------- drivers/media/video/Kconfig | 67 +++++++++++++++-------------- drivers/media/video/Makefile | 3 +- drivers/media/video/bt8xx/Kconfig | 2 +- drivers/media/video/cx88/cx88-video.c | 2 + drivers/media/video/em28xx/Kconfig | 2 +- drivers/media/video/et61x251/Kconfig | 2 +- drivers/media/video/pwc/Kconfig | 2 +- drivers/media/video/saa7134/saa7134-video.c | 2 + drivers/media/video/sn9c102/Kconfig | 2 +- drivers/media/video/usbvideo/Kconfig | 6 +-- drivers/media/video/vivi.c | 4 ++ drivers/media/video/zc0301/Kconfig | 2 +- include/linux/videodev2.h | 5 +++ 17 files changed, 118 insertions(+), 71 deletions(-) diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig index fffc711c260cae..344d83aae3ec3b 100644 --- a/drivers/media/Kconfig +++ b/drivers/media/Kconfig @@ -8,22 +8,54 @@ config VIDEO_DEV tristate "Video For Linux" ---help--- Support for audio/video capture and overlay devices and FM radio - cards. The exact capabilities of each device vary. User tools for - this are available from - . + cards. The exact capabilities of each device vary. This kernel includes support for the new Video for Linux Two API, (V4L2) as well as the original system. Drivers and applications need to be rewritten to use V4L2, but drivers for popular cards and applications for most video capture functions already exist. - Documentation for the original API is included in the file - . Documentation for V4L2 is - available on the web at . + Additional info and docs are available on the web at + + + Documentation for V4L2 is also available on the web at + . To compile this driver as a module, choose M here: the module will be called videodev. +config VIDEO_V4L1 + boolean "Enable Video For Linux API 1 (DEPRECATED)" + depends on VIDEO_DEV + select VIDEO_V4L1_COMPAT + default y + ---help--- + Enables a compatibility API used by most V4L2 devices to allow + its usage with legacy applications that supports only V4L1 api. + + If you are unsure as to whether this is required, answer Y. + +config VIDEO_V4L1_COMPAT + boolean "Enable Video For Linux API 1 compatible Layer" + depends on VIDEO_DEV + default y + ---help--- + This api were developed to be used at Kernel 2.2 and 2.4, but + lacks support for several video standards. There are several + drivers at kernel that still depends on it. + + Documentation for the original API is included in the file + . + + User tools for this are available from + . + + If you are unsure as to whether this is required, answer Y. + +config VIDEO_V4L2 + tristate + default y + source "drivers/media/video/Kconfig" source "drivers/media/radio/Kconfig" @@ -65,4 +97,3 @@ config USB_DABUSB module will be called dabusb. endmenu - diff --git a/drivers/media/common/Kconfig b/drivers/media/common/Kconfig index 6a901a0268e174..9c45b983e0de0f 100644 --- a/drivers/media/common/Kconfig +++ b/drivers/media/common/Kconfig @@ -4,6 +4,7 @@ config VIDEO_SAA7146 config VIDEO_SAA7146_VV tristate + select VIDEO_V4L2 select VIDEO_BUF select VIDEO_VIDEOBUF select VIDEO_SAA7146 diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index 5b2aadb8385c2b..c26e23291511ea 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -1,8 +1,7 @@ config DVB_AV7110 tristate "AV7110 cards" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && VIDEO_V4L1 select FW_LOADER - select VIDEO_DEV select VIDEO_SAA7146_VV select DVB_VES1820 select DVB_VES1X93 @@ -59,7 +58,7 @@ config DVB_AV7110_OSD config DVB_BUDGET tristate "Budget cards" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && VIDEO_V4L1 select VIDEO_SAA7146 select DVB_STV0299 select DVB_VES1X93 @@ -80,7 +79,7 @@ config DVB_BUDGET config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && VIDEO_V4L1 select VIDEO_SAA7146 select DVB_STV0297 select DVB_STV0299 @@ -100,8 +99,7 @@ config DVB_BUDGET_CI config DVB_BUDGET_AV tristate "Budget cards with analog video inputs" - depends on DVB_CORE && PCI - select VIDEO_DEV + depends on DVB_CORE && PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV select DVB_STV0299 select DVB_TDA1004X @@ -119,7 +117,7 @@ config DVB_BUDGET_AV config DVB_BUDGET_PATCH tristate "AV7110 cards with Budget Patch" - depends on DVB_CORE && DVB_BUDGET + depends on DVB_CORE && DVB_BUDGET && VIDEO_V4L1 select DVB_AV7110 select DVB_STV0299 select DVB_VES1X93 diff --git a/drivers/media/radio/Kconfig b/drivers/media/radio/Kconfig index d318be383de6a0..3fff7576369323 100644 --- a/drivers/media/radio/Kconfig +++ b/drivers/media/radio/Kconfig @@ -7,7 +7,7 @@ menu "Radio Adapters" config RADIO_CADET tristate "ADS Cadet AM/FM Tuner" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these AM/FM radio cards, and then fill in the port address below. @@ -25,7 +25,7 @@ config RADIO_CADET config RADIO_RTRACK tristate "AIMSlab RadioTrack (aka RadioReveal) support" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards, and then fill in the port address below. @@ -59,7 +59,7 @@ config RADIO_RTRACK_PORT config RADIO_RTRACK2 tristate "AIMSlab RadioTrack II support" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have this FM radio card, and then fill in the port address below. @@ -82,7 +82,7 @@ config RADIO_RTRACK2_PORT config RADIO_AZTECH tristate "Aztech/Packard Bell Radio" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards, and then fill in the port address below. @@ -106,7 +106,7 @@ config RADIO_AZTECH_PORT config RADIO_GEMTEK tristate "GemTek Radio Card support" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have this FM radio card, and then fill in the port address below. @@ -131,7 +131,7 @@ config RADIO_GEMTEK_PORT config RADIO_GEMTEK_PCI tristate "GemTek PCI Radio Card support" - depends on VIDEO_DEV && PCI + depends on VIDEO_V4L1 && PCI ---help--- Choose Y here if you have this PCI FM radio card. @@ -145,7 +145,7 @@ config RADIO_GEMTEK_PCI config RADIO_MAXIRADIO tristate "Guillemot MAXI Radio FM 2000 radio" - depends on VIDEO_DEV && PCI + depends on VIDEO_V4L1 && PCI ---help--- Choose Y here if you have this radio card. This card may also be found as Gemtek PCI FM. @@ -160,7 +160,7 @@ config RADIO_MAXIRADIO config RADIO_MAESTRO tristate "Maestro on board radio" - depends on VIDEO_DEV + depends on VIDEO_V4L1 ---help--- Say Y here to directly support the on-board radio tuner on the Maestro 2 or 2E sound card. @@ -175,7 +175,7 @@ config RADIO_MAESTRO config RADIO_MIROPCM20 tristate "miroSOUND PCM20 radio" - depends on ISA && VIDEO_DEV && SOUND_ACI_MIXER + depends on ISA && VIDEO_V4L1 && SOUND_ACI_MIXER ---help--- Choose Y here if you have this FM radio card. You also need to say Y to "ACI mixer (miroSOUND PCM1-pro/PCM12/PCM20 radio)" (in "Sound") @@ -208,7 +208,7 @@ config RADIO_MIROPCM20_RDS config RADIO_SF16FMI tristate "SF16FMI Radio" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards. If you compile the driver into the kernel and your card is not PnP one, you @@ -225,7 +225,7 @@ config RADIO_SF16FMI config RADIO_SF16FMR2 tristate "SF16FMR2 Radio" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards. @@ -239,7 +239,7 @@ config RADIO_SF16FMR2 config RADIO_TERRATEC tristate "TerraTec ActiveRadio ISA Standalone" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have this FM radio card, and then fill in the port address below. (TODO) @@ -268,7 +268,7 @@ config RADIO_TERRATEC_PORT config RADIO_TRUST tristate "Trust FM radio card" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 help This is a driver for the Trust FM radio cards. Say Y if you have such a card and want to use it under Linux. @@ -286,7 +286,7 @@ config RADIO_TRUST_PORT config RADIO_TYPHOON tristate "Typhoon Radio (a.k.a. EcoRadio)" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards, and then fill in the port address and the frequency used for muting below. @@ -330,7 +330,7 @@ config RADIO_TYPHOON_MUTEFREQ config RADIO_ZOLTRIX tristate "Zoltrix Radio" - depends on ISA && VIDEO_DEV + depends on ISA && VIDEO_V4L1 ---help--- Choose Y here if you have one of these FM radio cards, and then fill in the port address below. diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 85888a8a93c9b1..bff9d8f51dab72 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -2,10 +2,10 @@ # Multimedia Video device configuration # -menu "Video For Linux" +menu "Video Capture Adapters" depends on VIDEO_DEV -comment "Video Adapters" +comment "Video Capture Adapters" config VIDEO_ADV_DEBUG bool "Enable advanced debug functionality" @@ -20,7 +20,7 @@ source "drivers/media/video/bt8xx/Kconfig" config VIDEO_SAA6588 tristate "SAA6588 Radio Chip RDS decoder support on BT848 cards" - depends on VIDEO_DEV && I2C && VIDEO_BT848 + depends on I2C && VIDEO_BT848 help Support for Radio Data System (RDS) decoder. This allows seeing @@ -32,7 +32,7 @@ config VIDEO_SAA6588 config VIDEO_PMS tristate "Mediavision Pro Movie Studio Video For Linux" - depends on VIDEO_DEV && ISA + depends on ISA && VIDEO_V4L1 help Say Y if you have such a thing. @@ -41,7 +41,7 @@ config VIDEO_PMS config VIDEO_PLANB tristate "PlanB Video-In on PowerMac" - depends on PPC_PMAC && VIDEO_DEV && BROKEN + depends on PPC_PMAC && VIDEO_V4L1 && BROKEN help PlanB is the V4L driver for the PowerMac 7x00/8x00 series video input hardware. If you want to experiment with this, say Y. @@ -52,7 +52,7 @@ config VIDEO_PLANB config VIDEO_BWQCAM tristate "Quickcam BW Video For Linux" - depends on VIDEO_DEV && PARPORT + depends on PARPORT && VIDEO_V4L1 help Say Y have if you the black and white version of the QuickCam camera. See the next option for the color version. @@ -62,7 +62,7 @@ config VIDEO_BWQCAM config VIDEO_CQCAM tristate "QuickCam Colour Video For Linux (EXPERIMENTAL)" - depends on EXPERIMENTAL && VIDEO_DEV && PARPORT + depends on EXPERIMENTAL && PARPORT && VIDEO_V4L1 help This is the video4linux driver for the colour version of the Connectix QuickCam. If you have one of these cameras, say Y here, @@ -73,7 +73,7 @@ config VIDEO_CQCAM config VIDEO_W9966 tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux" - depends on PARPORT_1284 && VIDEO_DEV && PARPORT + depends on PARPORT_1284 && PARPORT && VIDEO_V4L1 help Video4linux driver for Winbond's w9966 based Webcams. Currently tested with the LifeView FlyCam Supra. @@ -86,7 +86,7 @@ config VIDEO_W9966 config VIDEO_CPIA tristate "CPiA Video For Linux" - depends on VIDEO_DEV + depends on VIDEO_V4L1 ---help--- This is the video4linux driver for cameras based on Vision's CPiA (Colour Processor Interface ASIC), such as the Creative Labs Video @@ -123,7 +123,7 @@ source "drivers/media/video/cpia2/Kconfig" config VIDEO_SAA5246A tristate "SAA5246A, SAA5281 Teletext processor" - depends on VIDEO_DEV && I2C + depends on I2C && VIDEO_V4L1 help Support for I2C bus based teletext using the SAA5246A or SAA5281 chip. Useful only if you live in Europe. @@ -150,7 +150,7 @@ config TUNER_3036 config VIDEO_VINO tristate "SGI Vino Video For Linux (EXPERIMENTAL)" - depends on VIDEO_DEV && I2C && SGI_IP22 && EXPERIMENTAL + depends on I2C && SGI_IP22 && EXPERIMENTAL && VIDEO_V4L1 select I2C_ALGO_SGI help Say Y here to build in support for the Vino video input system found @@ -158,7 +158,7 @@ config VIDEO_VINO config VIDEO_STRADIS tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)" - depends on EXPERIMENTAL && VIDEO_DEV && PCI + depends on EXPERIMENTAL && PCI && VIDEO_V4L1 help Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video driver for PCI. There is a product page at @@ -166,7 +166,7 @@ config VIDEO_STRADIS config VIDEO_ZORAN tristate "Zoran ZR36057/36067 Video For Linux" - depends on VIDEO_DEV && PCI && I2C_ALGOBIT + depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 help Say Y for support for MJPEG capture cards based on the Zoran 36057/36067 PCI controller chipset. This includes the Iomega @@ -214,7 +214,7 @@ config VIDEO_ZORAN_LML33R10 config VIDEO_ZR36120 tristate "Zoran ZR36120/36125 Video For Linux" - depends on VIDEO_DEV && PCI && I2C && BROKEN + depends on PCI && I2C && VIDEO_V4L1 && BROKEN help Support for ZR36120/ZR36125 based frame grabber/overlay boards. This includes the Victor II, WaveWatcher, Video Wonder, Maxi-TV, @@ -226,7 +226,7 @@ config VIDEO_ZR36120 config VIDEO_MEYE tristate "Sony Vaio Picturebook Motion Eye Video For Linux" - depends on VIDEO_DEV && PCI && SONYPI + depends on PCI && SONYPI && VIDEO_V4L1 ---help--- This is the video4linux driver for the Motion Eye camera found in the Vaio Picturebook laptops. Please read the material in @@ -242,7 +242,7 @@ source "drivers/media/video/saa7134/Kconfig" config VIDEO_MXB tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" - depends on VIDEO_DEV && PCI + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV select VIDEO_TUNER ---help--- @@ -254,8 +254,9 @@ config VIDEO_MXB config VIDEO_DPC tristate "Philips-Semiconductors 'dpc7146 demonstration board'" - depends on VIDEO_DEV && PCI + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV + select VIDEO_V4L2 ---help--- This is a video4linux driver for the 'dpc7146 demonstration board' by Philips-Semiconductors. It's the reference design @@ -268,8 +269,9 @@ config VIDEO_DPC config VIDEO_HEXIUM_ORION tristate "Hexium HV-PCI6 and Orion frame grabber" - depends on VIDEO_DEV && PCI + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV + select VIDEO_V4L2 ---help--- This is a video4linux driver for the Hexium HV-PCI6 and Orion frame grabber cards by Hexium. @@ -279,8 +281,9 @@ config VIDEO_HEXIUM_ORION config VIDEO_HEXIUM_GEMINI tristate "Hexium Gemini frame grabber" - depends on VIDEO_DEV && PCI + depends on PCI && VIDEO_V4L1 select VIDEO_SAA7146_VV + select VIDEO_V4L2 ---help--- This is a video4linux driver for the Hexium Gemini frame grabber card by Hexium. Please note that the Gemini Dual @@ -293,7 +296,7 @@ source "drivers/media/video/cx88/Kconfig" config VIDEO_OVCAMCHIP tristate "OmniVision Camera Chip support" - depends on VIDEO_DEV && I2C + depends on I2C && VIDEO_V4L1 ---help--- Support for the OmniVision OV6xxx and OV7xxx series of camera chips. This driver is intended to be used with the ov511 and w9968cf USB @@ -304,7 +307,7 @@ config VIDEO_OVCAMCHIP config VIDEO_M32R_AR tristate "AR devices" - depends on M32R + depends on M32R && VIDEO_V4L1 ---help--- This is a video4linux driver for the Renesas AR (Artificial Retina) camera module. @@ -365,17 +368,17 @@ config VIDEO_WM8739 source "drivers/media/video/cx25840/Kconfig" config VIDEO_SAA711X - tristate "Philips SAA7113/4/5 video decoders" - depends on VIDEO_DEV && I2C && EXPERIMENTAL + tristate "Philips SAA7113/4/5 video decoders (OBSOLETED)" + depends on VIDEO_V4L1 && I2C && EXPERIMENTAL ---help--- - Support for the Philips SAA7113/4/5 video decoders. + Old support for the Philips SAA7113/4 video decoders. To compile this driver as a module, choose M here: the module will be called saa7115. config VIDEO_SAA7127 tristate "Philips SAA7127/9 digital video encoders" - depends on VIDEO_DEV && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && I2C && EXPERIMENTAL ---help--- Support for the Philips SAA7127/9 digital video encoders. @@ -384,7 +387,7 @@ config VIDEO_SAA7127 config VIDEO_UPD64031A tristate "NEC Electronics uPD64031A Ghost Reduction" - depends on VIDEO_DEV && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && I2C && EXPERIMENTAL ---help--- Support for the NEC Electronics uPD64031A Ghost Reduction video chip. It is most often found in NTSC TV cards made for @@ -396,7 +399,7 @@ config VIDEO_UPD64031A config VIDEO_UPD64083 tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation" - depends on VIDEO_DEV && I2C && EXPERIMENTAL + depends on VIDEO_V4L2 && I2C && EXPERIMENTAL ---help--- Support for the NEC Electronics uPD64083 3-Dimensional Y/C separation video chip. It is used to improve the quality of @@ -418,7 +421,7 @@ source "drivers/media/video/em28xx/Kconfig" config USB_DSBR tristate "D-Link USB FM radio support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && EXPERIMENTAL + depends on USB && VIDEO_V4L1 && EXPERIMENTAL ---help--- Say Y here if you want to connect this type of radio to your computer's USB port. Note that the audio is not digital, and @@ -434,7 +437,7 @@ source "drivers/media/video/et61x251/Kconfig" config USB_OV511 tristate "USB OV511 Camera support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. See @@ -445,7 +448,7 @@ config USB_OV511 config USB_SE401 tristate "USB SE401 Camera support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. See @@ -458,7 +461,7 @@ source "drivers/media/video/sn9c102/Kconfig" config USB_STV680 tristate "USB STV680 (Pencam) Camera support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want to connect this type of camera to your computer's USB port. This includes the Pencam line of cameras. @@ -470,7 +473,7 @@ config USB_STV680 config USB_W9968CF tristate "USB W996[87]CF JPEG Dual Mode Camera support" - depends on USB && VIDEO_DEV && I2C + depends on USB && VIDEO_V4L1 && I2C select VIDEO_OVCAMCHIP ---help--- Say Y here if you want support for cameras based on OV681 or diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index b3ea2d63db9b04..11b06dac347bc1 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -10,7 +10,8 @@ tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ msp3400-objs := msp3400-driver.o msp3400-kthreads.o -obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o v4l1-compat.o compat_ioctl32.o +obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o +obj-$(CONFIG_VIDEO_V4L1_COMPAT) += v4l1-compat.o obj-$(CONFIG_VIDEO_BT848) += bt8xx/ obj-$(CONFIG_VIDEO_BT848) += tvaudio.o tda7432.o tda9875.o ir-kbd-i2c.o diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig index 085477c12612af..153f6a4a96c990 100644 --- a/drivers/media/video/bt8xx/Kconfig +++ b/drivers/media/video/bt8xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_BT848 tristate "BT848 Video For Linux" - depends on VIDEO_DEV && PCI && I2C + depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2 select I2C_ALGOBIT select FW_LOADER select VIDEO_BTCX diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index 72a417b3174521..694d1d80ff3f2e 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -35,8 +35,10 @@ #include "cx88.h" #include +#ifdef CONFIG_VIDEO_V4L1_COMPAT /* Include V4L1 specific functions. Should be removed soon */ #include +#endif MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards"); MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); diff --git a/drivers/media/video/em28xx/Kconfig b/drivers/media/video/em28xx/Kconfig index 5a793ae7cc23d4..dfb15bfb83dcad 100644 --- a/drivers/media/video/em28xx/Kconfig +++ b/drivers/media/video/em28xx/Kconfig @@ -1,6 +1,6 @@ config VIDEO_EM28XX tristate "Empia EM2800/2820/2840 USB video capture support" - depends on VIDEO_DEV && USB && I2C + depends on VIDEO_V4L1 && USB && I2C select VIDEO_BUF select VIDEO_TUNER select VIDEO_TVEEPROM diff --git a/drivers/media/video/et61x251/Kconfig b/drivers/media/video/et61x251/Kconfig index 6c43a90c6569f4..c6bff705688d0e 100644 --- a/drivers/media/video/et61x251/Kconfig +++ b/drivers/media/video/et61x251/Kconfig @@ -1,6 +1,6 @@ config USB_ET61X251 tristate "USB ET61X[12]51 PC Camera Controller support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on Etoms ET61X151 or ET61X251 PC Camera Controllers. diff --git a/drivers/media/video/pwc/Kconfig b/drivers/media/video/pwc/Kconfig index 86376556f10830..53cbc950f95c6a 100644 --- a/drivers/media/video/pwc/Kconfig +++ b/drivers/media/video/pwc/Kconfig @@ -1,6 +1,6 @@ config USB_PWC tristate "USB Philips Cameras" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y or M here if you want to use one of these Philips & OEM webcams: diff --git a/drivers/media/video/saa7134/saa7134-video.c b/drivers/media/video/saa7134/saa7134-video.c index aeef80f88a6bb0..e4156ec9c6d7ed 100644 --- a/drivers/media/video/saa7134/saa7134-video.c +++ b/drivers/media/video/saa7134/saa7134-video.c @@ -31,8 +31,10 @@ #include "saa7134.h" #include +#ifdef CONFIG_VIDEO_V4L1_COMPAT /* Include V4L1 specific functions. Should be removed soon */ #include +#endif /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/sn9c102/Kconfig b/drivers/media/video/sn9c102/Kconfig index 55f2bc11964ba3..cf552e6b8ecfb2 100644 --- a/drivers/media/video/sn9c102/Kconfig +++ b/drivers/media/video/sn9c102/Kconfig @@ -1,6 +1,6 @@ config USB_SN9C102 tristate "USB SN9C10x PC Camera Controller support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on SONiX SN9C101, SN9C102 or SN9C103 PC Camera Controllers. diff --git a/drivers/media/video/usbvideo/Kconfig b/drivers/media/video/usbvideo/Kconfig index 08a5d20bb2c0dd..39269a2c563591 100644 --- a/drivers/media/video/usbvideo/Kconfig +++ b/drivers/media/video/usbvideo/Kconfig @@ -3,7 +3,7 @@ config VIDEO_USBVIDEO config USB_VICAM tristate "USB 3com HomeConnect (aka vicam) support (EXPERIMENTAL)" - depends on USB && VIDEO_DEV && EXPERIMENTAL + depends on USB && VIDEO_V4L1 && EXPERIMENTAL select VIDEO_USBVIDEO ---help--- Say Y here if you have 3com homeconnect camera (vicam). @@ -13,7 +13,7 @@ config USB_VICAM config USB_IBMCAM tristate "USB IBM (Xirlink) C-it Camera support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want to connect a IBM "C-It" camera, also known as @@ -28,7 +28,7 @@ config USB_IBMCAM config USB_KONICAWC tristate "USB Konica Webcam support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 select VIDEO_USBVIDEO ---help--- Say Y here if you want support for webcams based on a Konica diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 5e813404d06813..9e42224b46b6cd 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -26,6 +26,10 @@ #include #include #include +#ifdef CONFIG_VIDEO_V4L1_COMPAT +/* Include V4L1 specific functions. Should be removed soon */ +#include +#endif #include #include #include diff --git a/drivers/media/video/zc0301/Kconfig b/drivers/media/video/zc0301/Kconfig index c3bf886b80cdb5..115833e4f4dd3b 100644 --- a/drivers/media/video/zc0301/Kconfig +++ b/drivers/media/video/zc0301/Kconfig @@ -1,6 +1,6 @@ config USB_ZC0301 tristate "USB ZC0301 Image Processor and Control Chip support" - depends on USB && VIDEO_DEV + depends on USB && VIDEO_V4L1 ---help--- Say Y here if you want support for cameras based on the ZC0301 Image Processor and Control Chip. diff --git a/include/linux/videodev2.h b/include/linux/videodev2.h index d7670ec1ec1e1d..ad7fa9c86c1008 100644 --- a/include/linux/videodev2.h +++ b/include/linux/videodev2.h @@ -1141,8 +1141,13 @@ extern char *v4l2_type_names[]; /* Compatibility layer interface -- v4l1-compat module */ typedef int (*v4l2_kioctl)(struct inode *inode, struct file *file, unsigned int cmd, void *arg); + +#ifdef CONFIG_VIDEO_V4L1_COMPAT int v4l_compat_translate_ioctl(struct inode *inode, struct file *file, int cmd, void *arg, v4l2_kioctl driver_ioctl); +#else +#define v4l_compat_translate_ioctl(inode,file,cmd,arg,ioctl) -EINVAL +#endif /* 32 Bits compatibility layer for 64 bits processors */ extern long v4l_compat_ioctl32(struct file *file, unsigned int cmd, -- cgit 1.2.3-korg From c1d1ea9e0f83a89d7afa1c84fac8312e2e08c85e Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 9 Apr 2006 15:51:18 -0300 Subject: V4L/DVB (3775): Add VIVI Kconfig stuff Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 11 +++++++++++ drivers/media/video/Makefile | 2 ++ 2 files changed, 13 insertions(+) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index bff9d8f51dab72..0dce9ab03adad4 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -16,6 +16,17 @@ config VIDEO_ADV_DEBUG V4L devices. In doubt, say N. +config VIDEO_VIVI + tristate "Virtual Video Driver" + depends on VIDEO_V4L2 + default n + ---help--- + Enables a virtual video driver. This device shows a color bar + and a timestamp, as a real device would generate by using V4L2 + api. + Say Y here if you want to test video apps or debug V4L devices. + In doubt, say N. + source "drivers/media/video/bt8xx/Kconfig" config VIDEO_SAA6588 diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 11b06dac347bc1..18b844219c1f01 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -85,4 +85,6 @@ obj-$(CONFIG_USB_IBMCAM) += usbvideo/ obj-$(CONFIG_USB_KONICAWC) += usbvideo/ obj-$(CONFIG_USB_VICAM) += usbvideo/ +obj-$(CONFIG_VIDEO_VIVI) += vivi.o + EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core -- cgit 1.2.3-korg From 4fff598fc700a9f2089a3351a54e049d79faa631 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Sun, 9 Apr 2006 16:20:19 -0300 Subject: V4L/DVB (3782): Removed uneeded stuff from pwc Makefile Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/pwc/Makefile | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/drivers/media/video/pwc/Makefile b/drivers/media/video/pwc/Makefile index 8326684f49f321..33d60126c02499 100644 --- a/drivers/media/video/pwc/Makefile +++ b/drivers/media/video/pwc/Makefile @@ -1,20 +1,3 @@ -ifneq ($(KERNELRELEASE),) - pwc-objs := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-uncompress.o pwc-timon.o pwc-kiara.o obj-$(CONFIG_USB_PWC) += pwc.o - -else - -KDIR := /lib/modules/$(shell uname -r)/build -PWD := $(shell pwd) - -default: - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules - -endif - -clean: - rm -f *.[oas] .*.flags *.ko .*.cmd .*.d .*.tmp *.mod.c - rm -rf .tmp_versions - -- cgit 1.2.3-korg From b37492be25be5ff0551bff8b479e783498ebe838 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 11 Apr 2006 18:07:49 -0300 Subject: V4L/DVB (3788): Fix compilation with V4L1_COMPAT Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 18b844219c1f01..9debef9be8c887 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -88,3 +88,5 @@ obj-$(CONFIG_USB_VICAM) += usbvideo/ obj-$(CONFIG_VIDEO_VIVI) += vivi.o EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core +extra-cflags-$(CONFIG_VIDEO_V4L1_COMPAT) += -DCONFIG_VIDEO_V4L1_COMPAT + -- cgit 1.2.3-korg From 7c908fbb0139fa1080412d0590189abfe2df87eb Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Tue, 11 Apr 2006 18:19:33 -0300 Subject: V4L/DVB (3790): Use after free in drivers/media/video/em28xx/em28xx-video.c In several places we use dev->devno right after we kfree() dev. This fixes coverity bug id #1065 Signed-off-by: Eric Sesterhenn Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/em28xx/em28xx-video.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c index ddc92cbb5276b7..cf7cdf9ef6178e 100644 --- a/drivers/media/video/em28xx/em28xx-video.c +++ b/drivers/media/video/em28xx/em28xx-video.c @@ -1576,8 +1576,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, errCode = em28xx_config(dev); if (errCode) { em28xx_errdev("error configuring device\n"); - kfree(dev); em28xx_devused&=~(1<devno); + kfree(dev); return -ENOMEM; } @@ -1603,8 +1603,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, dev->vdev = video_device_alloc(); if (NULL == dev->vdev) { em28xx_errdev("cannot allocate video_device.\n"); - kfree(dev); em28xx_devused&=~(1<devno); + kfree(dev); return -ENOMEM; } @@ -1612,8 +1612,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, if (NULL == dev->vbi_dev) { em28xx_errdev("cannot allocate video_device.\n"); kfree(dev->vdev); - kfree(dev); em28xx_devused&=~(1<devno); + kfree(dev); return -ENOMEM; } @@ -1650,8 +1650,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, mutex_unlock(&dev->lock); list_del(&dev->devlist); video_device_release(dev->vdev); - kfree(dev); em28xx_devused&=~(1<devno); + kfree(dev); return -ENODEV; } @@ -1662,8 +1662,8 @@ static int em28xx_init_dev(struct em28xx **devhandle, struct usb_device *udev, list_del(&dev->devlist); video_device_release(dev->vbi_dev); video_device_release(dev->vdev); - kfree(dev); em28xx_devused&=~(1<devno); + kfree(dev); return -ENODEV; } else { printk("registered VBI\n"); -- cgit 1.2.3-korg From 3a63fc4bfd8579bda1f6a03b3fcb792f59cb15f8 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 11 Apr 2006 18:16:22 -0300 Subject: V4L/DVB (3792): Kbuild: DVB_BT8XX must select DVB_ZL10353 Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index 376ca48f1d1da6..f28d721b8bb549 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -7,6 +7,7 @@ config DVB_BT8XX select DVB_CX24110 select DVB_OR51211 select DVB_LGDT330X + select DVB_ZL10353 select FW_LOADER help Support for PCI cards based on the Bt8xx PCI bridge. Examples are -- cgit 1.2.3-korg From a74b51fca9d9b6774413d700ade1e9ae1f0c0e75 Mon Sep 17 00:00:00 2001 From: Vadim Catana Date: Thu, 13 Apr 2006 10:19:52 -0300 Subject: V4L/DVB (3795): Fix for CX24123 & low symbol rates - fixed the reception of channels with low symbol rates. ( The VGA1 and VGA2 offsets recommended by cx24109 docs for symbol rates from 1 to 5 MSps do not work. I changed them to values found experimentally. The charge pump current and FILTUNE voltage are now set to values recommended in the docs. This improves reception for symbol rates < 15 MSps. The values written in the SYSSymbolRate registers are calculated with better precision. ) - fixed the cx24123_get_fec() function. It was returning the values for DCII mode. - removed some unused variables Signed-off-by: Vadim Catana Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24123.c | 262 +++++++++++++++++++++++----------- 1 file changed, 181 insertions(+), 81 deletions(-) diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index d661c6f9cbe527..e430e6a508312d 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -29,6 +29,8 @@ #include "dvb_frontend.h" #include "cx24123.h" +#define XTAL 10111000 + static int debug; #define dprintk(args...) \ do { \ @@ -52,6 +54,7 @@ struct cx24123_state u32 VGAarg; u32 bandselectarg; u32 pllarg; + u32 FILTune; /* The Demod/Tuner can't easily provide these, we cache them */ u32 currentfreq; @@ -63,43 +66,33 @@ static struct { u32 symbolrate_low; u32 symbolrate_high; - u32 VCAslope; - u32 VCAoffset; - u32 VGA1offset; - u32 VGA2offset; u32 VCAprogdata; u32 VGAprogdata; + u32 FILTune; } cx24123_AGC_vals[] = { { .symbolrate_low = 1000000, .symbolrate_high = 4999999, - .VCAslope = 0x07, - .VCAoffset = 0x0f, - .VGA1offset = 0x1f8, - .VGA2offset = 0x1f8, - .VGAprogdata = (2 << 18) | (0x1f8 << 9) | 0x1f8, + /* the specs recommend other values for VGA offsets, + but tests show they are wrong */ + .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0, .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07, + .FILTune = 0x280 /* 0.41 V */ }, { .symbolrate_low = 5000000, .symbolrate_high = 14999999, - .VCAslope = 0x1f, - .VCAoffset = 0x1f, - .VGA1offset = 0x1e0, - .VGA2offset = 0x180, .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0, .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f, + .FILTune = 0x317 /* 0.90 V */ }, { .symbolrate_low = 15000000, .symbolrate_high = 45000000, - .VCAslope = 0x3f, - .VCAoffset = 0x3f, - .VGA1offset = 0x180, - .VGA2offset = 0x100, .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180, .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f, + .FILTune = 0x146 /* 2.70 V */ }, }; @@ -112,90 +105,68 @@ static struct { u32 freq_low; u32 freq_high; - u32 bandselect; u32 VCOdivider; - u32 VCOnumber; u32 progdata; } cx24123_bandselect_vals[] = { { .freq_low = 950000, .freq_high = 1018999, - .bandselect = 0x40, .VCOdivider = 4, - .VCOnumber = 7, .progdata = (0 << 18) | (0 << 9) | 0x40, }, { .freq_low = 1019000, .freq_high = 1074999, - .bandselect = 0x80, .VCOdivider = 4, - .VCOnumber = 8, .progdata = (0 << 18) | (0 << 9) | 0x80, }, { .freq_low = 1075000, .freq_high = 1227999, - .bandselect = 0x01, .VCOdivider = 2, - .VCOnumber = 1, .progdata = (0 << 18) | (1 << 9) | 0x01, }, { .freq_low = 1228000, .freq_high = 1349999, - .bandselect = 0x02, .VCOdivider = 2, - .VCOnumber = 2, .progdata = (0 << 18) | (1 << 9) | 0x02, }, { .freq_low = 1350000, .freq_high = 1481999, - .bandselect = 0x04, .VCOdivider = 2, - .VCOnumber = 3, .progdata = (0 << 18) | (1 << 9) | 0x04, }, { .freq_low = 1482000, .freq_high = 1595999, - .bandselect = 0x08, .VCOdivider = 2, - .VCOnumber = 4, .progdata = (0 << 18) | (1 << 9) | 0x08, }, { .freq_low = 1596000, .freq_high = 1717999, - .bandselect = 0x10, .VCOdivider = 2, - .VCOnumber = 5, .progdata = (0 << 18) | (1 << 9) | 0x10, }, { .freq_low = 1718000, .freq_high = 1855999, - .bandselect = 0x20, .VCOdivider = 2, - .VCOnumber = 6, .progdata = (0 << 18) | (1 << 9) | 0x20, }, { .freq_low = 1856000, .freq_high = 2035999, - .bandselect = 0x40, .VCOdivider = 2, - .VCOnumber = 7, .progdata = (0 << 18) | (1 << 9) | 0x40, }, { .freq_low = 2036000, .freq_high = 2149999, - .bandselect = 0x80, .VCOdivider = 2, - .VCOnumber = 8, .progdata = (0 << 18) | (1 << 9) | 0x80, }, }; @@ -207,7 +178,6 @@ static struct { { {0x00, 0x03}, /* Reset system */ {0x00, 0x00}, /* Clear reset */ - {0x01, 0x3b}, /* Apply sensible defaults, from an i2c sniffer */ {0x03, 0x07}, {0x04, 0x10}, {0x05, 0x04}, @@ -217,7 +187,6 @@ static struct { {0x0f, 0xfe}, {0x10, 0x01}, {0x14, 0x01}, - {0x15, 0x98}, {0x16, 0x00}, {0x17, 0x01}, {0x1b, 0x05}, @@ -226,8 +195,6 @@ static struct { {0x1e, 0x00}, {0x20, 0x41}, {0x21, 0x15}, - {0x27, 0x14}, - {0x28, 0x46}, {0x29, 0x00}, {0x2a, 0xb0}, {0x2b, 0x73}, @@ -375,55 +342,103 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec) static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) { int ret; - u8 val; ret = cx24123_readreg (state, 0x1b); if (ret < 0) return ret; - val = ret & 0x07; - switch (val) { + ret = ret & 0x07; + + switch (ret) { case 1: *fec = FEC_1_2; break; - case 3: + case 2: *fec = FEC_2_3; break; - case 4: + case 3: *fec = FEC_3_4; break; - case 5: + case 4: *fec = FEC_4_5; break; - case 6: + case 5: *fec = FEC_5_6; break; + case 6: + *fec = FEC_6_7; + break; case 7: *fec = FEC_7_8; break; - case 2: /* *fec = FEC_3_5; break; */ - case 0: /* *fec = FEC_5_11; break; */ - *fec = FEC_AUTO; - break; default: *fec = FEC_NONE; // can't happen + printk("FEC_NONE ?\n"); } return 0; } -/* fixme: Symbol rates < 3MSps may not work because of precision loss */ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) { - u32 val; + u32 tmp, sample_rate, ratio; + u8 pll_mult; + + /* check if symbol rate is within limits */ + if ((srate > state->ops.info.symbol_rate_max) || + (srate < state->ops.info.symbol_rate_min)) + return -EOPNOTSUPP;; + + /* choose the sampling rate high enough for the required operation, + while optimizing the power consumed by the demodulator */ + if (srate < (XTAL*2)/2) + pll_mult = 2; + else if (srate < (XTAL*3)/2) + pll_mult = 3; + else if (srate < (XTAL*4)/2) + pll_mult = 4; + else if (srate < (XTAL*5)/2) + pll_mult = 5; + else if (srate < (XTAL*6)/2) + pll_mult = 6; + else if (srate < (XTAL*7)/2) + pll_mult = 7; + else if (srate < (XTAL*8)/2) + pll_mult = 8; + else + pll_mult = 9; + + + sample_rate = pll_mult * XTAL; - val = (srate / 1185) * 100; + /* + SYSSymbolRate[21:0] = (srate << 23) / sample_rate - /* Compensate for scaling up, by removing 17 symbols per 1Msps */ - val = val - (17 * (srate / 1000000)); + We have to use 32 bit unsigned arithmetic without precision loss. + The maximum srate is 45000000 or 0x02AEA540. This number has + only 6 clear bits on top, hence we can shift it left only 6 bits + at a time. Borrowed from cx24110.c + */ - cx24123_writereg(state, 0x08, (val >> 16) & 0xff ); - cx24123_writereg(state, 0x09, (val >> 8) & 0xff ); - cx24123_writereg(state, 0x0a, (val ) & 0xff ); + tmp = srate << 6; + ratio = tmp / sample_rate; + + tmp = (tmp % sample_rate) << 6; + ratio = (ratio << 6) + (tmp / sample_rate); + + tmp = (tmp % sample_rate) << 6; + ratio = (ratio << 6) + (tmp / sample_rate); + + tmp = (tmp % sample_rate) << 5; + ratio = (ratio << 5) + (tmp / sample_rate); + + + cx24123_writereg(state, 0x01, pll_mult * 6); + + cx24123_writereg(state, 0x08, (ratio >> 16) & 0x3f ); + cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff ); + cx24123_writereg(state, 0x0a, (ratio ) & 0xff ); + + dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i\n", __FUNCTION__, srate, ratio, sample_rate); return 0; } @@ -437,6 +452,7 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa struct cx24123_state *state = fe->demodulator_priv; u32 ndiv = 0, adiv = 0, vco_div = 0; int i = 0; + int pump = 2; /* Defaults for low freq, low rate */ state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; @@ -444,13 +460,14 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa state->bandselectarg = cx24123_bandselect_vals[0].progdata; vco_div = cx24123_bandselect_vals[0].VCOdivider; - /* For the given symbolerate, determine the VCA and VGA programming bits */ + /* For the given symbol rate, determine the VCA, VGA and FILTUNE programming bits */ for (i = 0; i < sizeof(cx24123_AGC_vals) / sizeof(cx24123_AGC_vals[0]); i++) { if ((cx24123_AGC_vals[i].symbolrate_low <= p->u.qpsk.symbol_rate) && - (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { + (cx24123_AGC_vals[i].symbolrate_high >= p->u.qpsk.symbol_rate) ) { state->VCAarg = cx24123_AGC_vals[i].VCAprogdata; state->VGAarg = cx24123_AGC_vals[i].VGAprogdata; + state->FILTune = cx24123_AGC_vals[i].FILTune; } } @@ -458,24 +475,28 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++) { if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && - (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) { + (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) { state->bandselectarg = cx24123_bandselect_vals[i].progdata; vco_div = cx24123_bandselect_vals[i].VCOdivider; + + /* determine the charge pump current */ + if ( p->frequency < (cx24123_bandselect_vals[i].freq_low + cx24123_bandselect_vals[i].freq_high)/2 ) + pump = 0x01; + else + pump = 0x02; } } /* Determine the N/A dividers for the requested lband freq (in kHz). */ - /* Note: 10111 (kHz) is the Crystal Freq and divider of 10. */ - ndiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) / 32) & 0x1ff; - adiv = ( ((p->frequency * vco_div) / (10111 / 10) / 2) % 32) & 0x1f; + /* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */ + ndiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) / 32) & 0x1ff; + adiv = ( ((p->frequency * vco_div * 10) / (2 * XTAL / 1000)) % 32) & 0x1f; if (adiv == 0) - adiv++; + ndiv++; - /* determine the correct pll frequency values. */ - /* Command 11, refdiv 11, cpump polarity 1, cpump current 3mA 10. */ - state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (2 << 14); - state->pllarg |= (ndiv << 5) | adiv; + /* control bits 11, refdiv 11, charge pump polarity 1, charge pump current, ndiv, adiv */ + state->pllarg = (3 << 19) | (3 << 17) | (1 << 16) | (pump << 14) | (ndiv << 5) | adiv; return 0; } @@ -538,6 +559,9 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_parameters *p) { struct cx24123_state *state = fe->demodulator_priv; + u8 val; + + dprintk("frequency=%i\n", p->frequency); if (cx24123_pll_calculate(fe, p) != 0) { printk("%s: cx24123_pll_calcutate failed\n",__FUNCTION__); @@ -552,6 +576,11 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet cx24123_pll_writereg(fe, p, state->bandselectarg); cx24123_pll_writereg(fe, p, state->pllarg); + /* set the FILTUNE voltage */ + val = cx24123_readreg(state, 0x28) & ~0x3; + cx24123_writereg(state, 0x27, state->FILTune >> 2); + cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3)); + return 0; } @@ -624,13 +653,81 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage return 0; } -static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, - struct dvb_diseqc_master_cmd *cmd) +static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) { - /* fixme: Implement diseqc */ - printk("%s: No support yet\n",__FUNCTION__); + struct cx24123_state *state = fe->demodulator_priv; + int i, val; + unsigned long timeout; + + dprintk("%s:\n",__FUNCTION__); - return -ENOTSUPP; + /* check if continuous tone has been stoped */ + if (state->config->use_isl6421) + val = cx24123_readlnbreg(state, 0x00) & 0x10; + else + val = cx24123_readreg(state, 0x29) & 0x10; + + + if (val) { + printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); + return -ENOTSUPP; + } + + /* select tone mode */ + cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8); + + for (i = 0; i < cmd->msg_len; i++) + cx24123_writereg(state, 0x2C + i, cmd->msg[i]); + + val = cx24123_readreg(state, 0x29); + cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) | ((cmd->msg_len-3) & 3)); + + timeout = jiffies + msecs_to_jiffies(100); + while (!time_after(jiffies, timeout) && !(cx24123_readreg(state, 0x29) & 0x40)) + ; // wait for LNB ready + + return 0; +} + +static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t burst) +{ + struct cx24123_state *state = fe->demodulator_priv; + int val; + unsigned long timeout; + + dprintk("%s:\n", __FUNCTION__); + + /* check if continuous tone has been stoped */ + if (state->config->use_isl6421) + val = cx24123_readlnbreg(state, 0x00) & 0x10; + else + val = cx24123_readreg(state, 0x29) & 0x10; + + + if (val) { + printk("%s: ERROR: attempt to send diseqc command before tone is off\n", __FUNCTION__); + return -ENOTSUPP; + } + + /* select tone mode */ + val = cx24123_readreg(state, 0x2a) & 0xf8; + cx24123_writereg(state, 0x2a, val | 0x04); + + val = cx24123_readreg(state, 0x29); + + if (burst == SEC_MINI_A) + cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x00)); + else if (burst == SEC_MINI_B) + cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40 | 0x08)); + else + return -EINVAL; + + + timeout = jiffies + msecs_to_jiffies(100); + while (!time_after(jiffies, timeout) && !(cx24123_readreg(state, 0x29) & 0x40)) + ; // wait for LNB ready + + return 0; } static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) @@ -642,13 +739,15 @@ static int cx24123_read_status(struct dvb_frontend* fe, fe_status_t* status) *status = 0; if (lock & 0x01) - *status |= FE_HAS_CARRIER | FE_HAS_SIGNAL; + *status |= FE_HAS_SIGNAL; + if (sync & 0x02) + *status |= FE_HAS_CARRIER; if (sync & 0x04) *status |= FE_HAS_VITERBI; if (sync & 0x08) - *status |= FE_HAS_CARRIER; + *status |= FE_HAS_SYNC; if (sync & 0x80) - *status |= FE_HAS_SYNC | FE_HAS_LOCK; + *status |= FE_HAS_LOCK; return 0; } @@ -875,6 +974,7 @@ static struct dvb_frontend_ops cx24123_ops = { .read_snr = cx24123_read_snr, .read_ucblocks = cx24123_read_ucblocks, .diseqc_send_master_cmd = cx24123_send_diseqc_msg, + .diseqc_send_burst = cx24123_diseqc_send_burst, .set_tone = cx24123_set_tone, .set_voltage = cx24123_set_voltage, }; -- cgit 1.2.3-korg From caf970e09c42843eb3b8456fc0e815f9b5385873 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 13 Apr 2006 11:29:13 -0300 Subject: V4L/DVB (3796): Add several debug messages to cx24123 code Current debug messages at cx24123 are next to useless, since they don't print the values sent/read to registers. With this patch, debug=1 will show comprehensive messages. debug=2 will show also read/write operations at I2C bus. Signed-off-by: Mauro Carvalho Chehab Signed-off-by: Andrew de Quincey --- drivers/media/dvb/frontends/cx24123.c | 54 +++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index e430e6a508312d..115ec169b6414a 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -225,6 +225,10 @@ static int cx24123_writereg(struct cx24123_state* state, int reg, int data) struct i2c_msg msg = { .addr = state->config->demod_address, .flags = 0, .buf = buf, .len = 2 }; int err; + if (debug>1) + printk("cx24123: %s: write reg 0x%02x, value 0x%02x\n", + __FUNCTION__,reg, data); + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { printk("%s: writereg error(err == %i, reg == 0x%02x," " data == 0x%02x)\n", __FUNCTION__, err, reg, data); @@ -241,6 +245,10 @@ static int cx24123_writelnbreg(struct cx24123_state* state, int reg, int data) struct i2c_msg msg = { .addr = 0x08, .flags = 0, .buf = buf, .len = 2 }; int err; + if (debug>1) + printk("cx24123: %s: writeln addr=0x08, reg 0x%02x, value 0x%02x\n", + __FUNCTION__,reg, data); + if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1) { printk("%s: writelnbreg error (err == %i, reg == 0x%02x," " data == 0x%02x)\n", __FUNCTION__, err, reg, data); @@ -270,6 +278,9 @@ static int cx24123_readreg(struct cx24123_state* state, u8 reg) return ret; } + if (debug>1) + printk("cx24123: read reg 0x%02x, value 0x%02x\n",reg, ret); + return b1[0]; } @@ -282,14 +293,17 @@ static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_invers { switch (inversion) { case INVERSION_OFF: + dprintk("%s: inversion off\n",__FUNCTION__); cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f); cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80); break; case INVERSION_ON: + dprintk("%s: inversion on\n",__FUNCTION__); cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80); cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80); break; case INVERSION_AUTO: + dprintk("%s: inversion auto\n",__FUNCTION__); cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f); break; default: @@ -305,10 +319,13 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers val = cx24123_readreg(state, 0x1b) >> 7; - if (val == 0) + if (val == 0) { + dprintk("%s: read inversion off\n",__FUNCTION__); *inversion = INVERSION_OFF; - else + } else { + dprintk("%s: read inversion on\n",__FUNCTION__); *inversion = INVERSION_ON; + } return 0; } @@ -321,18 +338,25 @@ static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec) /* Hardware has 5/11 and 3/5 but are never unused */ switch (fec) { case FEC_NONE: + dprintk("%s: set FEC to none\n",__FUNCTION__); return cx24123_writereg(state, 0x0f, 0x01); case FEC_1_2: + dprintk("%s: set FEC to 1/2\n",__FUNCTION__); return cx24123_writereg(state, 0x0f, 0x02); case FEC_2_3: + dprintk("%s: set FEC to 2/3\n",__FUNCTION__); return cx24123_writereg(state, 0x0f, 0x04); case FEC_3_4: + dprintk("%s: set FEC to 3/4\n",__FUNCTION__); return cx24123_writereg(state, 0x0f, 0x08); case FEC_5_6: + dprintk("%s: set FEC to 4/5\n",__FUNCTION__); return cx24123_writereg(state, 0x0f, 0x20); case FEC_7_8: + dprintk("%s: set FEC to 5/6\n",__FUNCTION__); return cx24123_writereg(state, 0x0f, 0x80); case FEC_AUTO: + dprintk("%s: set FEC to auto\n",__FUNCTION__); return cx24123_writereg(state, 0x0f, 0xae); default: return -EOPNOTSUPP; @@ -510,6 +534,8 @@ static int cx24123_pll_writereg(struct dvb_frontend* fe, struct dvb_frontend_par struct cx24123_state *state = fe->demodulator_priv; unsigned long timeout; + dprintk("%s: pll writereg called, data=0x%08x\n",__FUNCTION__,data); + /* align the 21 bytes into to bit23 boundary */ data = data << 3; @@ -581,6 +607,9 @@ static int cx24123_pll_tune(struct dvb_frontend* fe, struct dvb_frontend_paramet cx24123_writereg(state, 0x27, state->FILTune >> 2); cx24123_writereg(state, 0x28, val | (state->FILTune & 0x3)); + dprintk("%s: pll tune VCA=%d, band=%d, pll=%d\n",__FUNCTION__,state->VCAarg, + state->bandselectarg,state->pllarg); + return 0; } @@ -589,6 +618,8 @@ static int cx24123_initfe(struct dvb_frontend* fe) struct cx24123_state *state = fe->demodulator_priv; int i; + dprintk("%s: init frontend\n",__FUNCTION__); + /* Configure the demod to a good set of defaults */ for (i = 0; i < sizeof(cx24123_regdata) / sizeof(cx24123_regdata[0]); i++) cx24123_writereg(state, cx24123_regdata[i].reg, cx24123_regdata[i].data); @@ -616,10 +647,13 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage switch (voltage) { case SEC_VOLTAGE_13: + dprintk("%s: isl6421 voltage = 13V\n",__FUNCTION__); return cx24123_writelnbreg(state, 0x0, val & 0x32); /* V 13v */ case SEC_VOLTAGE_18: + dprintk("%s: isl6421 voltage = 18V\n",__FUNCTION__); return cx24123_writelnbreg(state, 0x0, val | 0x04); /* H 18v */ case SEC_VOLTAGE_OFF: + dprintk("%s: isl5421 voltage off\n",__FUNCTION__); return cx24123_writelnbreg(state, 0x0, val & 0x30); default: return -EINVAL; @@ -780,6 +814,8 @@ static int cx24123_read_ber(struct dvb_frontend* fe, u32* ber) else state->snr = 0; + dprintk("%s: BER = %d, S/N index = %d\n",__FUNCTION__,state->lastber, state->snr); + *ber = state->lastber; return 0; @@ -790,6 +826,8 @@ static int cx24123_read_signal_strength(struct dvb_frontend* fe, u16* signal_str struct cx24123_state *state = fe->demodulator_priv; *signal_strength = cx24123_readreg(state, 0x3b) << 8; /* larger = better */ + dprintk("%s: Signal strength = %d\n",__FUNCTION__,*signal_strength); + return 0; } @@ -798,6 +836,8 @@ static int cx24123_read_snr(struct dvb_frontend* fe, u16* snr) struct cx24123_state *state = fe->demodulator_priv; *snr = state->snr; + dprintk("%s: read S/N index = %d\n",__FUNCTION__,*snr); + return 0; } @@ -806,6 +846,8 @@ static int cx24123_read_ucblocks(struct dvb_frontend* fe, u32* ucblocks) struct cx24123_state *state = fe->demodulator_priv; *ucblocks = state->lastber; + dprintk("%s: ucblocks (ber) = %d\n",__FUNCTION__,*ucblocks); + return 0; } @@ -813,6 +855,8 @@ static int cx24123_set_frontend(struct dvb_frontend* fe, struct dvb_frontend_par { struct cx24123_state *state = fe->demodulator_priv; + dprintk("%s: set_frontend\n",__FUNCTION__); + if (state->config->set_ts_params) state->config->set_ts_params(fe, 0); @@ -836,6 +880,8 @@ static int cx24123_get_frontend(struct dvb_frontend* fe, struct dvb_frontend_par { struct cx24123_state *state = fe->demodulator_priv; + dprintk("%s: get_frontend\n",__FUNCTION__); + if (cx24123_get_inversion(state, &p->inversion) != 0) { printk("%s: Failed to get inversion status\n",__FUNCTION__); return -EREMOTEIO; @@ -862,8 +908,10 @@ static int cx24123_set_tone(struct dvb_frontend* fe, fe_sec_tone_mode_t tone) switch (tone) { case SEC_TONE_ON: + dprintk("%s: isl6421 sec tone on\n",__FUNCTION__); return cx24123_writelnbreg(state, 0x0, val | 0x10); case SEC_TONE_OFF: + dprintk("%s: isl6421 sec tone off\n",__FUNCTION__); return cx24123_writelnbreg(state, 0x0, val & 0x2f); default: printk("%s: CASE reached default with tone=%d\n", __FUNCTION__, tone); @@ -980,7 +1028,7 @@ static struct dvb_frontend_ops cx24123_ops = { }; module_param(debug, int, 0644); -MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off)."); +MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware"); MODULE_AUTHOR("Steven Toth"); -- cgit 1.2.3-korg From dce1dfc2a5736bfc82df5d3fd6396022c7bbbbd8 Mon Sep 17 00:00:00 2001 From: Yeasah Pell Date: Thu, 13 Apr 2006 11:40:59 -0300 Subject: V4L/DVB (3797): Always wait for diseqc queue to become ready before transmitting a diseqc message The previous DISEQC code didn't wait, so it was unreliable Signed-off-by: Yeasah Pell Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24123.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index 115ec169b6414a..fa6cdba08d25e0 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -687,15 +687,27 @@ static int cx24123_set_voltage(struct dvb_frontend* fe, fe_sec_voltage_t voltage return 0; } +/* wait for diseqc queue to become ready (or timeout) */ +static void cx24123_wait_for_diseqc(struct cx24123_state *state) +{ + unsigned long timeout = jiffies + msecs_to_jiffies(200); + while (!(cx24123_readreg(state, 0x29) & 0x40)) { + if(time_after(jiffies, timeout)) { + printk("%s: diseqc queue not ready, command may be lost.\n", __FUNCTION__); + break; + } + msleep(10); + } +} + static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_master_cmd *cmd) { struct cx24123_state *state = fe->demodulator_priv; int i, val; - unsigned long timeout; dprintk("%s:\n",__FUNCTION__); - /* check if continuous tone has been stoped */ + /* check if continuous tone has been stopped */ if (state->config->use_isl6421) val = cx24123_readlnbreg(state, 0x00) & 0x10; else @@ -707,6 +719,9 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma return -ENOTSUPP; } + /* wait for diseqc queue ready */ + cx24123_wait_for_diseqc(state); + /* select tone mode */ cx24123_writereg(state, 0x2a, cx24123_readreg(state, 0x2a) & 0xf8); @@ -716,9 +731,8 @@ static int cx24123_send_diseqc_msg(struct dvb_frontend* fe, struct dvb_diseqc_ma val = cx24123_readreg(state, 0x29); cx24123_writereg(state, 0x29, ((val & 0x90) | 0x40) | ((cmd->msg_len-3) & 3)); - timeout = jiffies + msecs_to_jiffies(100); - while (!time_after(jiffies, timeout) && !(cx24123_readreg(state, 0x29) & 0x40)) - ; // wait for LNB ready + /* wait for diseqc message to finish sending */ + cx24123_wait_for_diseqc(state); return 0; } @@ -727,7 +741,6 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t { struct cx24123_state *state = fe->demodulator_priv; int val; - unsigned long timeout; dprintk("%s:\n", __FUNCTION__); @@ -743,6 +756,8 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t return -ENOTSUPP; } + cx24123_wait_for_diseqc(state); + /* select tone mode */ val = cx24123_readreg(state, 0x2a) & 0xf8; cx24123_writereg(state, 0x2a, val | 0x04); @@ -756,10 +771,7 @@ static int cx24123_diseqc_send_burst(struct dvb_frontend* fe, fe_sec_mini_cmd_t else return -EINVAL; - - timeout = jiffies + msecs_to_jiffies(100); - while (!time_after(jiffies, timeout) && !(cx24123_readreg(state, 0x29) & 0x40)) - ; // wait for LNB ready + cx24123_wait_for_diseqc(state); return 0; } -- cgit 1.2.3-korg From 0e4558ab4a89a127e0de36746552da9353e35f10 Mon Sep 17 00:00:00 2001 From: Yeasah Pell Date: Thu, 13 Apr 2006 17:24:13 -0300 Subject: V4L/DVB (3803): Various correctness fixes to tuning. *) Sets an additional tuner parameter (demodulator sample gain) that wasn't being set before. *) Removes the low symbol rate tuner parameter tweaks in the previous patch -- it appears those tweaks are not necessary with the demodulator sample gain set correctly. *) Cleanup and document the demodulator register initialization sequence. *) Change set_fec routine to disable FEC auto scan when a specific code rate is selected. *) Remove error message when reported FEC is invalid (which happens sometimes when the card has no signal) Signed-off-by: Yeasah Pell Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24123.c | 172 +++++++++++++++++++++------------- 1 file changed, 108 insertions(+), 64 deletions(-) diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index fa6cdba08d25e0..2aac17451d7582 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -76,23 +76,23 @@ static struct .symbolrate_high = 4999999, /* the specs recommend other values for VGA offsets, but tests show they are wrong */ - .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0, - .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x07, - .FILTune = 0x280 /* 0.41 V */ + .VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0, + .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x07, + .FILTune = 0x27f /* 0.41 V */ }, { .symbolrate_low = 5000000, .symbolrate_high = 14999999, - .VGAprogdata = (2 << 18) | (0x180 << 9) | 0x1e0, - .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x1f, + .VGAprogdata = (1 << 19) | (0x180 << 9) | 0x1e0, + .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x1f, .FILTune = 0x317 /* 0.90 V */ }, { .symbolrate_low = 15000000, .symbolrate_high = 45000000, - .VGAprogdata = (2 << 18) | (0x100 << 9) | 0x180, - .VCAprogdata = (4 << 18) | (0x07 << 9) | 0x3f, - .FILTune = 0x146 /* 2.70 V */ + .VGAprogdata = (1 << 19) | (0x100 << 9) | 0x180, + .VCAprogdata = (2 << 19) | (0x07 << 9) | 0x3f, + .FILTune = 0x145 /* 2.70 V */ }, }; @@ -178,45 +178,44 @@ static struct { { {0x00, 0x03}, /* Reset system */ {0x00, 0x00}, /* Clear reset */ - {0x03, 0x07}, - {0x04, 0x10}, - {0x05, 0x04}, - {0x06, 0x31}, - {0x0d, 0x02}, - {0x0e, 0x03}, - {0x0f, 0xfe}, - {0x10, 0x01}, - {0x14, 0x01}, - {0x16, 0x00}, - {0x17, 0x01}, - {0x1b, 0x05}, - {0x1c, 0x80}, - {0x1d, 0x00}, - {0x1e, 0x00}, - {0x20, 0x41}, - {0x21, 0x15}, - {0x29, 0x00}, - {0x2a, 0xb0}, - {0x2b, 0x73}, - {0x2c, 0x00}, + {0x03, 0x07}, /* QPSK, DVB, Auto Acquisition (default) */ + {0x04, 0x10}, /* MPEG */ + {0x05, 0x04}, /* MPEG */ + {0x06, 0x31}, /* MPEG (default) */ + {0x0b, 0x00}, /* Freq search start point (default) */ + {0x0c, 0x00}, /* Demodulator sample gain (default) */ + {0x0d, 0x02}, /* Frequency search range = Fsymbol / 4 (default) */ + {0x0e, 0x03}, /* Default non-inverted, FEC 3/4 (default) */ + {0x0f, 0xfe}, /* FEC search mask (all supported codes) */ + {0x10, 0x01}, /* Default search inversion, no repeat (default) */ + {0x16, 0x00}, /* Enable reading of frequency */ + {0x17, 0x01}, /* Enable EsNO Ready Counter */ + {0x1c, 0x80}, /* Enable error counter */ + {0x20, 0x00}, /* Tuner burst clock rate = 500KHz */ + {0x21, 0x15}, /* Tuner burst mode, word length = 0x15 */ + {0x28, 0x00}, /* Enable FILTERV with positive pol., DiSEqC 2.x off */ + {0x29, 0x00}, /* DiSEqC LNB_DC off */ + {0x2a, 0xb0}, /* DiSEqC Parameters (default) */ + {0x2b, 0x73}, /* DiSEqC Tone Frequency (default) */ + {0x2c, 0x00}, /* DiSEqC Message (0x2c - 0x31) */ {0x2d, 0x00}, {0x2e, 0x00}, {0x2f, 0x00}, {0x30, 0x00}, {0x31, 0x00}, - {0x32, 0x8c}, - {0x33, 0x00}, + {0x32, 0x8c}, /* DiSEqC Parameters (default) */ + {0x33, 0x00}, /* Interrupts off (0x33 - 0x34) */ {0x34, 0x00}, - {0x35, 0x03}, - {0x36, 0x02}, - {0x37, 0x3a}, - {0x3a, 0x00}, /* Enable AGC accumulator */ - {0x44, 0x00}, - {0x45, 0x00}, - {0x46, 0x05}, - {0x56, 0x41}, - {0x57, 0xff}, - {0x67, 0x83}, + {0x35, 0x03}, /* DiSEqC Tone Amplitude (default) */ + {0x36, 0x02}, /* DiSEqC Parameters (default) */ + {0x37, 0x3a}, /* DiSEqC Parameters (default) */ + {0x3a, 0x00}, /* Enable AGC accumulator (for signal strength) */ + {0x44, 0x00}, /* Constellation (default) */ + {0x45, 0x00}, /* Symbol count (default) */ + {0x46, 0x0d}, /* Symbol rate estimator on (default) */ + {0x56, 0x41}, /* Various (default) */ + {0x57, 0xff}, /* Error Counter Window (default) */ + {0x67, 0x83}, /* Non-DCII symbol clock */ }; static int cx24123_writereg(struct cx24123_state* state, int reg, int data) @@ -291,20 +290,23 @@ static int cx24123_readlnbreg(struct cx24123_state* state, u8 reg) static int cx24123_set_inversion(struct cx24123_state* state, fe_spectral_inversion_t inversion) { + u8 nom_reg = cx24123_readreg(state, 0x0e); + u8 auto_reg = cx24123_readreg(state, 0x10); + switch (inversion) { case INVERSION_OFF: dprintk("%s: inversion off\n",__FUNCTION__); - cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) & 0x7f); - cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80); + cx24123_writereg(state, 0x0e, nom_reg & ~0x80); + cx24123_writereg(state, 0x10, auto_reg | 0x80); break; case INVERSION_ON: dprintk("%s: inversion on\n",__FUNCTION__); - cx24123_writereg(state, 0x0e, cx24123_readreg(state, 0x0e) | 0x80); - cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) | 0x80); + cx24123_writereg(state, 0x0e, nom_reg | 0x80); + cx24123_writereg(state, 0x10, auto_reg | 0x80); break; case INVERSION_AUTO: dprintk("%s: inversion auto\n",__FUNCTION__); - cx24123_writereg(state, 0x10, cx24123_readreg(state, 0x10) & 0x7f); + cx24123_writereg(state, 0x10, auto_reg & ~0x80); break; default: return -EINVAL; @@ -332,35 +334,56 @@ static int cx24123_get_inversion(struct cx24123_state* state, fe_spectral_invers static int cx24123_set_fec(struct cx24123_state* state, fe_code_rate_t fec) { + u8 nom_reg = cx24123_readreg(state, 0x0e) & ~0x07; + if ( (fec < FEC_NONE) || (fec > FEC_AUTO) ) fec = FEC_AUTO; - /* Hardware has 5/11 and 3/5 but are never unused */ switch (fec) { - case FEC_NONE: - dprintk("%s: set FEC to none\n",__FUNCTION__); - return cx24123_writereg(state, 0x0f, 0x01); case FEC_1_2: dprintk("%s: set FEC to 1/2\n",__FUNCTION__); - return cx24123_writereg(state, 0x0f, 0x02); + cx24123_writereg(state, 0x0e, nom_reg | 0x01); + cx24123_writereg(state, 0x0f, 0x02); + break; case FEC_2_3: dprintk("%s: set FEC to 2/3\n",__FUNCTION__); - return cx24123_writereg(state, 0x0f, 0x04); + cx24123_writereg(state, 0x0e, nom_reg | 0x02); + cx24123_writereg(state, 0x0f, 0x04); + break; case FEC_3_4: dprintk("%s: set FEC to 3/4\n",__FUNCTION__); - return cx24123_writereg(state, 0x0f, 0x08); - case FEC_5_6: + cx24123_writereg(state, 0x0e, nom_reg | 0x03); + cx24123_writereg(state, 0x0f, 0x08); + break; + case FEC_4_5: dprintk("%s: set FEC to 4/5\n",__FUNCTION__); - return cx24123_writereg(state, 0x0f, 0x20); - case FEC_7_8: + cx24123_writereg(state, 0x0e, nom_reg | 0x04); + cx24123_writereg(state, 0x0f, 0x10); + break; + case FEC_5_6: dprintk("%s: set FEC to 5/6\n",__FUNCTION__); - return cx24123_writereg(state, 0x0f, 0x80); + cx24123_writereg(state, 0x0e, nom_reg | 0x05); + cx24123_writereg(state, 0x0f, 0x20); + break; + case FEC_6_7: + dprintk("%s: set FEC to 6/7\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x06); + cx24123_writereg(state, 0x0f, 0x40); + break; + case FEC_7_8: + dprintk("%s: set FEC to 7/8\n",__FUNCTION__); + cx24123_writereg(state, 0x0e, nom_reg | 0x07); + cx24123_writereg(state, 0x0f, 0x80); + break; case FEC_AUTO: dprintk("%s: set FEC to auto\n",__FUNCTION__); - return cx24123_writereg(state, 0x0f, 0xae); + cx24123_writereg(state, 0x0f, 0xfe); + break; default: return -EOPNOTSUPP; } + + return 0; } static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) @@ -395,16 +418,31 @@ static int cx24123_get_fec(struct cx24123_state* state, fe_code_rate_t *fec) *fec = FEC_7_8; break; default: - *fec = FEC_NONE; // can't happen - printk("FEC_NONE ?\n"); + /* this can happen when there's no lock */ + *fec = FEC_NONE; } return 0; } +/* Approximation of closest integer of log2(a/b). It actually gives the + lowest integer i such that 2^i >= round(a/b) */ +static u32 cx24123_int_log2(u32 a, u32 b) +{ + u32 exp, nearest = 0; + u32 div = a / b; + if(a % b >= b / 2) ++div; + if(div < (1 << 31)) + { + for(exp = 1; div > exp; nearest++) + exp += exp; + } + return nearest; +} + static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) { - u32 tmp, sample_rate, ratio; + u32 tmp, sample_rate, ratio, sample_gain; u8 pll_mult; /* check if symbol rate is within limits */ @@ -462,7 +500,12 @@ static int cx24123_set_symbolrate(struct cx24123_state* state, u32 srate) cx24123_writereg(state, 0x09, (ratio >> 8) & 0xff ); cx24123_writereg(state, 0x0a, (ratio ) & 0xff ); - dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i\n", __FUNCTION__, srate, ratio, sample_rate); + /* also set the demodulator sample gain */ + sample_gain = cx24123_int_log2(sample_rate, srate); + tmp = cx24123_readreg(state, 0x0c) & ~0xe0; + cx24123_writereg(state, 0x0c, tmp | sample_gain << 5); + + dprintk("%s: srate=%d, ratio=0x%08x, sample_rate=%i sample_gain=%d\n", __FUNCTION__, srate, ratio, sample_rate, sample_gain); return 0; } @@ -1014,12 +1057,13 @@ static struct dvb_frontend_ops cx24123_ops = { .frequency_min = 950000, .frequency_max = 2150000, .frequency_stepsize = 1011, /* kHz for QPSK frontends */ - .frequency_tolerance = 29500, + .frequency_tolerance = 5000, .symbol_rate_min = 1000000, .symbol_rate_max = 45000000, .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 | - FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | + FE_CAN_FEC_4_5 | FE_CAN_FEC_5_6 | FE_CAN_FEC_6_7 | + FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO | FE_CAN_QPSK | FE_CAN_RECOVER }, -- cgit 1.2.3-korg From 70047f9cca231126981f360c79cde98ea30410b2 Mon Sep 17 00:00:00 2001 From: Yeasah Pell Date: Thu, 13 Apr 2006 17:26:22 -0300 Subject: V4L/DVB (3804): Tweak bandselect setup fox cx24123 *) Allow forcing the bandselect value with a module parameter to facilitate determining the correct bandselect frequencies. *) Changes the bandselect frequency thresholds based on experiments with the above parameter in conjunction with the values in the spec. Signed-off-by: Yeasah Pell Signed-off-by: Andrew de Quincey Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/cx24123.c | 97 ++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 37 deletions(-) diff --git a/drivers/media/dvb/frontends/cx24123.c b/drivers/media/dvb/frontends/cx24123.c index 2aac17451d7582..691dc840dcc06e 100644 --- a/drivers/media/dvb/frontends/cx24123.c +++ b/drivers/media/dvb/frontends/cx24123.c @@ -31,6 +31,7 @@ #define XTAL 10111000 +static int force_band; static int debug; #define dprintk(args...) \ do { \ @@ -109,65 +110,76 @@ static struct u32 progdata; } cx24123_bandselect_vals[] = { + /* band 1 */ { .freq_low = 950000, - .freq_high = 1018999, - .VCOdivider = 4, - .progdata = (0 << 18) | (0 << 9) | 0x40, - }, - { - .freq_low = 1019000, .freq_high = 1074999, .VCOdivider = 4, - .progdata = (0 << 18) | (0 << 9) | 0x80, + .progdata = (0 << 19) | (0 << 9) | 0x40, }, + + /* band 2 */ { .freq_low = 1075000, - .freq_high = 1227999, - .VCOdivider = 2, - .progdata = (0 << 18) | (1 << 9) | 0x01, + .freq_high = 1177999, + .VCOdivider = 4, + .progdata = (0 << 19) | (0 << 9) | 0x80, }, + + /* band 3 */ { - .freq_low = 1228000, - .freq_high = 1349999, + .freq_low = 1178000, + .freq_high = 1295999, .VCOdivider = 2, - .progdata = (0 << 18) | (1 << 9) | 0x02, + .progdata = (0 << 19) | (1 << 9) | 0x01, }, + + /* band 4 */ { - .freq_low = 1350000, - .freq_high = 1481999, + .freq_low = 1296000, + .freq_high = 1431999, .VCOdivider = 2, - .progdata = (0 << 18) | (1 << 9) | 0x04, + .progdata = (0 << 19) | (1 << 9) | 0x02, }, + + /* band 5 */ { - .freq_low = 1482000, - .freq_high = 1595999, + .freq_low = 1432000, + .freq_high = 1575999, .VCOdivider = 2, - .progdata = (0 << 18) | (1 << 9) | 0x08, + .progdata = (0 << 19) | (1 << 9) | 0x04, }, + + /* band 6 */ { - .freq_low = 1596000, + .freq_low = 1576000, .freq_high = 1717999, .VCOdivider = 2, - .progdata = (0 << 18) | (1 << 9) | 0x10, + .progdata = (0 << 19) | (1 << 9) | 0x08, }, + + /* band 7 */ { .freq_low = 1718000, .freq_high = 1855999, .VCOdivider = 2, - .progdata = (0 << 18) | (1 << 9) | 0x20, + .progdata = (0 << 19) | (1 << 9) | 0x10, }, + + /* band 8 */ { .freq_low = 1856000, .freq_high = 2035999, .VCOdivider = 2, - .progdata = (0 << 18) | (1 << 9) | 0x40, + .progdata = (0 << 19) | (1 << 9) | 0x20, }, + + /* band 9 */ { .freq_low = 2036000, - .freq_high = 2149999, + .freq_high = 2150000, .VCOdivider = 2, - .progdata = (0 << 18) | (1 << 9) | 0x80, + .progdata = (0 << 19) | (1 << 9) | 0x40, }, }; @@ -520,6 +532,8 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa u32 ndiv = 0, adiv = 0, vco_div = 0; int i = 0; int pump = 2; + int band = 0; + int num_bands = sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); /* Defaults for low freq, low rate */ state->VCAarg = cx24123_AGC_vals[0].VCAprogdata; @@ -538,21 +552,27 @@ static int cx24123_pll_calculate(struct dvb_frontend* fe, struct dvb_frontend_pa } } - /* For the given frequency, determine the bandselect programming bits */ - for (i = 0; i < sizeof(cx24123_bandselect_vals) / sizeof(cx24123_bandselect_vals[0]); i++) + /* determine the band to use */ + if(force_band < 1 || force_band > num_bands) { - if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && - (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) { - state->bandselectarg = cx24123_bandselect_vals[i].progdata; - vco_div = cx24123_bandselect_vals[i].VCOdivider; - - /* determine the charge pump current */ - if ( p->frequency < (cx24123_bandselect_vals[i].freq_low + cx24123_bandselect_vals[i].freq_high)/2 ) - pump = 0x01; - else - pump = 0x02; + for (i = 0; i < num_bands; i++) + { + if ((cx24123_bandselect_vals[i].freq_low <= p->frequency) && + (cx24123_bandselect_vals[i].freq_high >= p->frequency) ) + band = i; } } + else + band = force_band - 1; + + state->bandselectarg = cx24123_bandselect_vals[band].progdata; + vco_div = cx24123_bandselect_vals[band].VCOdivider; + + /* determine the charge pump current */ + if ( p->frequency < (cx24123_bandselect_vals[band].freq_low + cx24123_bandselect_vals[band].freq_high)/2 ) + pump = 0x01; + else + pump = 0x02; /* Determine the N/A dividers for the requested lband freq (in kHz). */ /* Note: the reference divider R=10, frequency is in KHz, XTAL is in Hz */ @@ -1086,6 +1106,9 @@ static struct dvb_frontend_ops cx24123_ops = { module_param(debug, int, 0644); MODULE_PARM_DESC(debug, "Activates frontend debugging (default:0)"); +module_param(force_band, int, 0644); +MODULE_PARM_DESC(force_band, "Force a specific band select (1-9, default:off)."); + MODULE_DESCRIPTION("DVB Frontend module for Conexant cx24123/cx24109 hardware"); MODULE_AUTHOR("Steven Toth"); MODULE_LICENSE("GPL"); -- cgit 1.2.3-korg From 7157e2b6ff6fdd24d7e54d9856aa24ea88527ca9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 16 Apr 2006 17:17:42 -0300 Subject: V4L/DVB (3813): Add support for TCL M2523_5N_E tuner. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tveeprom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/tveeprom.c b/drivers/media/video/tveeprom.c index 431c3e2f6c4274..b463e996961adb 100644 --- a/drivers/media/video/tveeprom.c +++ b/drivers/media/video/tveeprom.c @@ -218,7 +218,7 @@ hauppauge_tuner[] = /* 110-119 */ { TUNER_ABSENT, "Thompson DTT75105"}, { TUNER_ABSENT, "Conexant_CX24109"}, - { TUNER_ABSENT, "TCL M2523_5N_E"}, + { TUNER_TCL_2002N, "TCL M2523_5N_E"}, { TUNER_ABSENT, "TCL M2523_3DB_E"}, { TUNER_ABSENT, "Philips 8275A"}, { TUNER_ABSENT, "Microtune MT2060"}, -- cgit 1.2.3-korg From 5691c8473936508c51639b6ff8467e55d8b129c1 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Wed, 19 Apr 2006 20:40:01 -0300 Subject: V4L/DVB (3819): Cxusb-bluebird: bug-fix: power down corrupts frontend This patch prevents a bug where the frontend is unable to tune after waking from powered down state. Now, the device remains powered on until it is disconnected, just like the windows driver. It seems that the bluebird firmware is unable to successfully handle tuning after a powered down state. This patch fixes all of the FusionHDTV Bluebird USB2 devices. The Medion MD95700 will still behave as before, since it was unaffected by this bug. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-usb/cxusb.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index 7edd6362b9cc67..1f0d3e995c8d67 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -150,6 +150,15 @@ static int cxusb_power_ctrl(struct dvb_usb_device *d, int onoff) return cxusb_ctrl_msg(d, CMD_POWER_OFF, &b, 1, NULL, 0); } +static int cxusb_bluebird_power_ctrl(struct dvb_usb_device *d, int onoff) +{ + u8 b = 0; + if (onoff) + return cxusb_ctrl_msg(d, CMD_POWER_ON, &b, 1, NULL, 0); + else + return 0; +} + static int cxusb_streaming_ctrl(struct dvb_usb_device *d, int onoff) { u8 buf[2] = { 0x03, 0x00 }; @@ -544,7 +553,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgh064f_properties = { .size_of_priv = sizeof(struct cxusb_state), .streaming_ctrl = cxusb_streaming_ctrl, - .power_ctrl = cxusb_power_ctrl, + .power_ctrl = cxusb_bluebird_power_ctrl, .frontend_attach = cxusb_lgdt3303_frontend_attach, .tuner_attach = cxusb_lgh064f_tuner_attach, @@ -589,7 +598,7 @@ static struct dvb_usb_properties cxusb_bluebird_dee1601_properties = { .size_of_priv = sizeof(struct cxusb_state), .streaming_ctrl = cxusb_streaming_ctrl, - .power_ctrl = cxusb_power_ctrl, + .power_ctrl = cxusb_bluebird_power_ctrl, .frontend_attach = cxusb_dee1601_frontend_attach, .tuner_attach = cxusb_dee1601_tuner_attach, @@ -638,7 +647,7 @@ static struct dvb_usb_properties cxusb_bluebird_lgz201_properties = { .size_of_priv = sizeof(struct cxusb_state), .streaming_ctrl = cxusb_streaming_ctrl, - .power_ctrl = cxusb_power_ctrl, + .power_ctrl = cxusb_bluebird_power_ctrl, .frontend_attach = cxusb_mt352_frontend_attach, .tuner_attach = cxusb_lgz201_tuner_attach, @@ -683,7 +692,7 @@ static struct dvb_usb_properties cxusb_bluebird_dtt7579_properties = { .size_of_priv = sizeof(struct cxusb_state), .streaming_ctrl = cxusb_streaming_ctrl, - .power_ctrl = cxusb_power_ctrl, + .power_ctrl = cxusb_bluebird_power_ctrl, .frontend_attach = cxusb_mt352_frontend_attach, .tuner_attach = cxusb_dtt7579_tuner_attach, -- cgit 1.2.3-korg From 7d16eaa3d0d41a6e871e5c82720bcd006b202d55 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Sun, 23 Apr 2006 05:54:56 -0300 Subject: V4L/DVB (3825): Remove broken 'fast firmware load' from cx25840. The fast firmware load hack in cx25840 uses private data. In fact, it breaks pvrusb2 and doesn't work at all with ivtv. It is a unsafe implementation and so it is removed. Signed-off-by: Hans Verkuil Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/cx25840/cx25840-firmware.c | 49 ++------------------------ 1 file changed, 2 insertions(+), 47 deletions(-) diff --git a/drivers/media/video/cx25840/cx25840-firmware.c b/drivers/media/video/cx25840/cx25840-firmware.c index f59ced181c553a..1958d4016ea15c 100644 --- a/drivers/media/video/cx25840/cx25840-firmware.c +++ b/drivers/media/video/cx25840/cx25840-firmware.c @@ -39,29 +39,12 @@ #define FWDEV(x) &((x)->adapter->dev) -static int fastfw = 1; static char *firmware = FWFILE; -module_param(fastfw, bool, 0444); module_param(firmware, charp, 0444); -MODULE_PARM_DESC(fastfw, "Load firmware fast [0=100MHz 1=333MHz (default)]"); MODULE_PARM_DESC(firmware, "Firmware image [default: " FWFILE "]"); -static void set_i2c_delay(struct i2c_client *client, int delay) -{ - struct i2c_algo_bit_data *algod = client->adapter->algo_data; - - /* We aren't guaranteed to be using algo_bit, - * so avoid the null pointer dereference - * and disable the 'fast firmware load' */ - if (algod) { - algod->udelay = delay; - } else { - fastfw = 0; - } -} - static void start_fw_load(struct i2c_client *client) { /* DL_ADDR_LB=0 DL_ADDR_HB=0 */ @@ -71,16 +54,10 @@ static void start_fw_load(struct i2c_client *client) cx25840_write(client, 0x803, 0x0b); /* AUTO_INC_DIS=1 */ cx25840_write(client, 0x000, 0x20); - - if (fastfw) - set_i2c_delay(client, 3); } static void end_fw_load(struct i2c_client *client) { - if (fastfw) - set_i2c_delay(client, 10); - /* AUTO_INC_DIS=0 */ cx25840_write(client, 0x000, 0x00); /* DL_ENABLE=0 */ @@ -107,30 +84,8 @@ static int fw_write(struct i2c_client *client, u8 * data, int size) int sent; if ((sent = i2c_master_send(client, data, size)) < size) { - - if (fastfw) { - v4l_err(client, "333MHz i2c firmware load failed\n"); - fastfw = 0; - set_i2c_delay(client, 10); - - if (sent > 2) { - u16 dl_addr = cx25840_read(client, 0x801) << 8; - dl_addr |= cx25840_read(client, 0x800); - dl_addr -= sent - 2; - cx25840_write(client, 0x801, dl_addr >> 8); - cx25840_write(client, 0x800, dl_addr & 0xff); - } - - if (i2c_master_send(client, data, size) < size) { - v4l_err(client, "100MHz i2c firmware load failed\n"); - return -ENOSYS; - } - - } else { - v4l_err(client, "firmware load i2c failure\n"); - return -ENOSYS; - } - + v4l_err(client, "firmware load i2c failure\n"); + return -ENOSYS; } return 0; -- cgit 1.2.3-korg From 7bbbc0a28e6cfcef66e2180206257b959dad2006 Mon Sep 17 00:00:00 2001 From: Mikhail Gusarov Date: Thu, 20 Apr 2006 13:18:50 -0300 Subject: V4L/DVB (3826): Saa7134: Missing 'break' in Terratec Cinergy 400 TV initialization There is a missing break in card initialization function. Might screw up initialization of Terratec Cinergy 400 TV. Signed-off-by: Mikhail Gusarov Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/saa7134/saa7134-cards.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index e666a4465ca460..86eae3528330bb 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3504,6 +3504,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x00040000, 0x00040000); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x00040000, 0x00000000); + break; case SAA7134_BOARD_PINNACLE_300I_DVBT_PAL: /* this turns the remote control chip off to work around a bug in it */ saa_writeb(SAA7134_GPIO_GPMODE1, 0x80); -- cgit 1.2.3-korg From dd31d5ac7345b2c728bf7eb37b06383776174232 Mon Sep 17 00:00:00 2001 From: Rusty Scott Date: Sat, 22 Apr 2006 16:15:07 -0300 Subject: V4L/DVB (3829): Fix frequency values in the ranges structures of the LG TDVS H06xF tuners Frequency range values in the current driver for the LG TDVS H06xF tuners appear to have been a transposing of the 5 in the mid range 160-455 instead of 165-450. This patch corrects the pll programming for these tuners as per the datasheet. Signed-off-by: Rusty Scott Signed-off-by: Mac Michaels Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/dvb-pll.c | 4 ++-- drivers/media/video/tuner-types.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/media/dvb/frontends/dvb-pll.c b/drivers/media/dvb/frontends/dvb-pll.c index b6e2c387a04cc0..791706ec1da39a 100644 --- a/drivers/media/dvb/frontends/dvb-pll.c +++ b/drivers/media/dvb/frontends/dvb-pll.c @@ -235,8 +235,8 @@ struct dvb_pll_desc dvb_pll_tdvs_tua6034 = { .max = 863000000, .count = 3, .entries = { - { 160000000, 44000000, 62500, 0xce, 0x01 }, - { 455000000, 44000000, 62500, 0xce, 0x02 }, + { 165000000, 44000000, 62500, 0xce, 0x01 }, + { 450000000, 44000000, 62500, 0xce, 0x02 }, { 999999999, 44000000, 62500, 0xce, 0x04 }, }, }; diff --git a/drivers/media/video/tuner-types.c b/drivers/media/video/tuner-types.c index 72e0f01db56359..a1ae036b44ec9c 100644 --- a/drivers/media/video/tuner-types.c +++ b/drivers/media/video/tuner-types.c @@ -877,8 +877,8 @@ static struct tuner_params tuner_philips_fmd1216me_mk3_params[] = { /* ------------ TUNER_LG_TDVS_H062F - INFINEON ATSC ------------ */ static struct tuner_range tuner_tua6034_ntsc_ranges[] = { - { 16 * 160.00 /*MHz*/, 0x8e, 0x01 }, - { 16 * 455.00 /*MHz*/, 0x8e, 0x02 }, + { 16 * 165.00 /*MHz*/, 0x8e, 0x01 }, + { 16 * 450.00 /*MHz*/, 0x8e, 0x02 }, { 16 * 999.99 , 0x8e, 0x04 }, }; -- cgit 1.2.3-korg From ba5f0a4e15e736d99d698ce498bd6f1f16d014cf Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Sun, 23 Apr 2006 01:55:38 -0300 Subject: V4L/DVB (3832): Get_dvb_firmware: download nxt2002 firmware from new driver location BBTI has updated their driver, and removed the old one from their website. This patch updates the get_dvb_firmware script to download the firmware from the new driver location. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/dvb/get_dvb_firmware | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/dvb/get_dvb_firmware b/Documentation/dvb/get_dvb_firmware index 15fc8fbef67e3f..4820366b6ae899 100644 --- a/Documentation/dvb/get_dvb_firmware +++ b/Documentation/dvb/get_dvb_firmware @@ -259,9 +259,9 @@ sub dibusb { } sub nxt2002 { - my $sourcefile = "Broadband4PC_4_2_11.zip"; + my $sourcefile = "Technisat_DVB-PC_4_4_COMPACT.zip"; my $url = "http://www.bbti.us/download/windows/$sourcefile"; - my $hash = "c6d2ea47a8f456d887ada0cfb718ff2a"; + my $hash = "476befae8c7c1bb9648954060b1eec1f"; my $outfile = "dvb-fe-nxt2002.fw"; my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1); @@ -269,8 +269,8 @@ sub nxt2002 { wgetfile($sourcefile, $url); unzip($sourcefile, $tmpdir); - verify("$tmpdir/SkyNETU.sys", $hash); - extract("$tmpdir/SkyNETU.sys", 375832, 5908, $outfile); + verify("$tmpdir/SkyNET.sys", $hash); + extract("$tmpdir/SkyNET.sys", 331624, 5908, $outfile); $outfile; } -- cgit 1.2.3-korg From 765bf9770fda950e6615451ad1a4b8866bda7dfa Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 27 Apr 2006 10:09:27 -0300 Subject: V4L/DVB (3912): Sparc32 vivi fix Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 0dce9ab03adad4..912791779cb4ed 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -18,7 +18,7 @@ config VIDEO_ADV_DEBUG config VIDEO_VIVI tristate "Virtual Video Driver" - depends on VIDEO_V4L2 + depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 default n ---help--- Enables a virtual video driver. This device shows a color bar -- cgit 1.2.3-korg From 1095136dee95d27d27cebc52bd502f7facee8600 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Thu, 27 Apr 2006 10:10:58 -0300 Subject: V4L/DVB (3914): Vivi build fix drivers/media/video/vivi.c: In function `vivi_map_sg': drivers/media/video/vivi.c:799: error: `DMA_NONE' undeclared (first use in this function) drivers/media/video/vivi.c:799: error: (Each undeclared identifier is reported only once drivers/media/video/vivi.c:799: error: for each function it appears in.) Signed-off-by: Andrew Morton Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/vivi.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/vivi.c b/drivers/media/video/vivi.c index 9e42224b46b6cd..779db26771c03b 100644 --- a/drivers/media/video/vivi.c +++ b/drivers/media/video/vivi.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef CONFIG_VIDEO_V4L1_COMPAT /* Include V4L1 specific functions. Should be removed soon */ #include -- cgit 1.2.3-korg From 68a26aecb3829d013f612def3c8995efdbad3306 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 28 Apr 2006 10:48:41 -0300 Subject: V4L/DVB (3964): Bt8xx/bttv-cards.c: fix off-by-one errors This patch fixes two off-by-one errors spotted by the Coverity checker. Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/bt8xx/bttv-cards.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index f209a749205104..2b64aa835b4236 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -2991,13 +2991,13 @@ void __devinit bttv_idcard(struct bttv *btv) if (UNSET != audiomux[0]) { gpiobits = 0; - for (i = 0; i < 5; i++) { + for (i = 0; i < 4; i++) { bttv_tvcards[btv->c.type].gpiomux[i] = audiomux[i]; gpiobits |= audiomux[i]; } } else { gpiobits = audioall; - for (i = 0; i < 5; i++) { + for (i = 0; i < 4; i++) { bttv_tvcards[btv->c.type].gpiomux[i] = audioall; } } -- cgit 1.2.3-korg From 8a2ae70a9b4dc88c83b4644c58d06d74f2cb70c9 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Tue, 2 May 2006 09:00:31 -0300 Subject: V4L/DVB (3965): Fix CONFIG_VIDEO_VIVI=y build bug CONFIG_VIDEO_VIVI depends on CONFIG_VIDEO_BUF. Signed-off-by: Ingo Molnar Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 912791779cb4ed..7124e534cc7fd4 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -19,6 +19,7 @@ config VIDEO_ADV_DEBUG config VIDEO_VIVI tristate "Virtual Video Driver" depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 + select VIDEO_BUF default n ---help--- Enables a virtual video driver. This device shows a color bar -- cgit 1.2.3-korg From bc519f30eb039f023c15167663d5a8a14fed7dcb Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Fri, 5 May 2006 17:38:27 +0100 Subject: [PATCH] bcm43xx: associate on 'ifconfig up' I still need this hack to work around the fact that softmac doesn't attempt to associate when we bring the device up... Signed-off-by: David Woodhouse Signed-off-by: John W. Linville --- drivers/net/wireless/bcm43xx/bcm43xx_main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c index e2982a83ae424c..7ed18cad29f756 100644 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ b/drivers/net/wireless/bcm43xx/bcm43xx_main.c @@ -3271,6 +3271,9 @@ static int bcm43xx_init_board(struct bcm43xx_private *bcm) bcm43xx_sysfs_register(bcm); //FIXME: check for bcm43xx_sysfs_register failure. This function is a bit messy regarding unwinding, though... + /*FIXME: This should be handled by softmac instead. */ + schedule_work(&bcm->softmac->associnfo.work); + assert(err == 0); out: return err; @@ -3946,9 +3949,6 @@ static int bcm43xx_resume(struct pci_dev *pdev) netif_device_attach(net_dev); - /*FIXME: This should be handled by softmac instead. */ - schedule_work(&bcm->softmac->associnfo.work); - dprintk(KERN_INFO PFX "Device resumed.\n"); return 0; -- cgit 1.2.3-korg From f34ba4e1edd82272dbc192e488c7dc9e56c4ec62 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 19 May 2006 02:13:21 -0700 Subject: [PATCH] revert "forcedeth: fix multi irq issues" Revert ebf34c9b6fcd22338ef764b039b3ac55ed0e297b. Maybe. Due to crashes at shutdown - see http://bugzilla.kernel.org/show_bug.cgi?id=6568. Cc: Ayaz Abdulla Cc: Manfred Spraul Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 312 +++++++++++++----------------------------------- 1 file changed, 84 insertions(+), 228 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index f7235c9bc42179..7e078b4cca7cd3 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -106,7 +106,6 @@ * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings. * 0.52: 20 Jan 2006: Add MSI/MSIX support. * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset. - * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -118,7 +117,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.54" +#define FORCEDETH_VERSION "0.53" #define DRV_NAME "forcedeth" #include @@ -711,72 +710,6 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags) } } -static int using_multi_irqs(struct net_device *dev) -{ - struct fe_priv *np = get_nvpriv(dev); - - if (!(np->msi_flags & NV_MSI_X_ENABLED) || - ((np->msi_flags & NV_MSI_X_ENABLED) && - ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) - return 0; - else - return 1; -} - -static void nv_enable_irq(struct net_device *dev) -{ - struct fe_priv *np = get_nvpriv(dev); - - if (!using_multi_irqs(dev)) { - if (np->msi_flags & NV_MSI_X_ENABLED) - enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); - else - enable_irq(dev->irq); - } else { - enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); - enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); - enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); - } -} - -static void nv_disable_irq(struct net_device *dev) -{ - struct fe_priv *np = get_nvpriv(dev); - - if (!using_multi_irqs(dev)) { - if (np->msi_flags & NV_MSI_X_ENABLED) - disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); - else - disable_irq(dev->irq); - } else { - disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); - disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); - disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); - } -} - -/* In MSIX mode, a write to irqmask behaves as XOR */ -static void nv_enable_hw_interrupts(struct net_device *dev, u32 mask) -{ - u8 __iomem *base = get_hwbase(dev); - - writel(mask, base + NvRegIrqMask); -} - -static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask) -{ - struct fe_priv *np = get_nvpriv(dev); - u8 __iomem *base = get_hwbase(dev); - - if (np->msi_flags & NV_MSI_X_ENABLED) { - writel(mask, base + NvRegIrqMask); - } else { - if (np->msi_flags & NV_MSI_ENABLED) - writel(0, base + NvRegMSIIrqMask); - writel(0, base + NvRegIrqMask); - } -} - #define MII_READ (-1) /* mii_rw: read/write a register on the PHY. * @@ -1086,25 +1019,24 @@ static void nv_do_rx_refill(unsigned long data) struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); - if (!using_multi_irqs(dev)) { - if (np->msi_flags & NV_MSI_X_ENABLED) - disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); - else - disable_irq(dev->irq); + + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + disable_irq(dev->irq); } else { disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); } if (nv_alloc_rx(dev)) { - spin_lock_irq(&np->lock); + spin_lock(&np->lock); if (!np->in_shutdown) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock_irq(&np->lock); + spin_unlock(&np->lock); } - if (!using_multi_irqs(dev)) { - if (np->msi_flags & NV_MSI_X_ENABLED) - enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); - else - enable_irq(dev->irq); + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + enable_irq(dev->irq); } else { enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); } @@ -1736,7 +1668,15 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) * guessed, there is probably a simpler approach. * Changing the MTU is a rare event, it shouldn't matter. */ - nv_disable_irq(dev); + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + disable_irq(dev->irq); + } else { + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); + } spin_lock_bh(&dev->xmit_lock); spin_lock(&np->lock); /* stop engines */ @@ -1769,7 +1709,15 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) nv_start_tx(dev); spin_unlock(&np->lock); spin_unlock_bh(&dev->xmit_lock); - nv_enable_irq(dev); + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + enable_irq(dev->irq); + } else { + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); + } } return 0; } @@ -2160,16 +2108,16 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) if (!(events & np->irqmask)) break; - spin_lock_irq(&np->lock); + spin_lock(&np->lock); nv_tx_done(dev); - spin_unlock_irq(&np->lock); + spin_unlock(&np->lock); if (events & (NVREG_IRQ_TX_ERR)) { dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dev->name, events); } if (i > max_interrupt_work) { - spin_lock_irq(&np->lock); + spin_lock(&np->lock); /* disable interrupts on the nic */ writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); pci_push(base); @@ -2179,7 +2127,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); - spin_unlock_irq(&np->lock); + spin_unlock(&np->lock); break; } @@ -2209,14 +2157,14 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) nv_rx_process(dev); if (nv_alloc_rx(dev)) { - spin_lock_irq(&np->lock); + spin_lock(&np->lock); if (!np->in_shutdown) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock_irq(&np->lock); + spin_unlock(&np->lock); } if (i > max_interrupt_work) { - spin_lock_irq(&np->lock); + spin_lock(&np->lock); /* disable interrupts on the nic */ writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); pci_push(base); @@ -2226,7 +2174,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); - spin_unlock_irq(&np->lock); + spin_unlock(&np->lock); break; } @@ -2255,14 +2203,14 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) break; if (events & NVREG_IRQ_LINK) { - spin_lock_irq(&np->lock); + spin_lock(&np->lock); nv_link_irq(dev); - spin_unlock_irq(&np->lock); + spin_unlock(&np->lock); } if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { - spin_lock_irq(&np->lock); + spin_lock(&np->lock); nv_linkchange(dev); - spin_unlock_irq(&np->lock); + spin_unlock(&np->lock); np->link_timeout = jiffies + LINK_TIMEOUT; } if (events & (NVREG_IRQ_UNKNOWN)) { @@ -2270,7 +2218,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) dev->name, events); } if (i > max_interrupt_work) { - spin_lock_irq(&np->lock); + spin_lock(&np->lock); /* disable interrupts on the nic */ writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); pci_push(base); @@ -2280,7 +2228,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); - spin_unlock_irq(&np->lock); + spin_unlock(&np->lock); break; } @@ -2303,11 +2251,10 @@ static void nv_do_nic_poll(unsigned long data) * nv_nic_irq because that may decide to do otherwise */ - if (!using_multi_irqs(dev)) { - if (np->msi_flags & NV_MSI_X_ENABLED) - disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); - else - disable_irq(dev->irq); + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + disable_irq(dev->irq); mask = np->irqmask; } else { if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { @@ -2330,12 +2277,11 @@ static void nv_do_nic_poll(unsigned long data) writel(mask, base + NvRegIrqMask); pci_push(base); - if (!using_multi_irqs(dev)) { + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL); - if (np->msi_flags & NV_MSI_X_ENABLED) - enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); - else - enable_irq(dev->irq); + enable_irq(dev->irq); } else { if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL); @@ -2682,113 +2628,6 @@ static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask) writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1); } -static int nv_request_irq(struct net_device *dev) -{ - struct fe_priv *np = get_nvpriv(dev); - u8 __iomem *base = get_hwbase(dev); - int ret = 1; - int i; - - if (np->msi_flags & NV_MSI_X_CAPABLE) { - for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { - np->msi_x_entry[i].entry = i; - } - if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) { - np->msi_flags |= NV_MSI_X_ENABLED; - if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) { - /* Request irq for rx handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_err; - } - /* Request irq for tx handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_free_rx; - } - /* Request irq for link and timer handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_free_tx; - } - /* map interrupts to their respective vector */ - writel(0, base + NvRegMSIXMap0); - writel(0, base + NvRegMSIXMap1); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER); - } else { - /* Request irq for all interrupts */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_err; - } - - /* map interrupts to vector 0 */ - writel(0, base + NvRegMSIXMap0); - writel(0, base + NvRegMSIXMap1); - } - } - } - if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { - if ((ret = pci_enable_msi(np->pci_dev)) == 0) { - np->msi_flags |= NV_MSI_ENABLED; - if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); - pci_disable_msi(np->pci_dev); - np->msi_flags &= ~NV_MSI_ENABLED; - goto out_err; - } - - /* map interrupts to vector 0 */ - writel(0, base + NvRegMSIMap0); - writel(0, base + NvRegMSIMap1); - /* enable msi vector 0 */ - writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); - } - } - if (ret != 0) { - if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) - goto out_err; - } - - return 0; -out_free_tx: - free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev); -out_free_rx: - free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev); -out_err: - return 1; -} - -static void nv_free_irq(struct net_device *dev) -{ - struct fe_priv *np = get_nvpriv(dev); - int i; - - if (np->msi_flags & NV_MSI_X_ENABLED) { - for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { - free_irq(np->msi_x_entry[i].vector, dev); - } - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - } else { - free_irq(np->pci_dev->irq, dev); - if (np->msi_flags & NV_MSI_ENABLED) { - pci_disable_msi(np->pci_dev); - np->msi_flags &= ~NV_MSI_ENABLED; - } - } -} - static int nv_open(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); @@ -2881,16 +2720,12 @@ static int nv_open(struct net_device *dev) udelay(10); writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState); - nv_disable_hw_interrupts(dev, np->irqmask); + writel(0, base + NvRegIrqMask); pci_push(base); writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); pci_push(base); - if (nv_request_irq(dev)) { - goto out_drain; - } - if (np->msi_flags & NV_MSI_X_CAPABLE) { for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { np->msi_x_entry[i].entry = i; @@ -2964,7 +2799,7 @@ static int nv_open(struct net_device *dev) } /* ask for interrupts */ - nv_enable_hw_interrupts(dev, np->irqmask); + writel(np->irqmask, base + NvRegIrqMask); spin_lock_irq(&np->lock); writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); @@ -3008,6 +2843,7 @@ static int nv_close(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base; + int i; spin_lock_irq(&np->lock); np->in_shutdown = 1; @@ -3025,13 +2861,31 @@ static int nv_close(struct net_device *dev) /* disable interrupts on the nic or we will lock up */ base = get_hwbase(dev); - nv_disable_hw_interrupts(dev, np->irqmask); + if (np->msi_flags & NV_MSI_X_ENABLED) { + writel(np->irqmask, base + NvRegIrqMask); + } else { + if (np->msi_flags & NV_MSI_ENABLED) + writel(0, base + NvRegMSIIrqMask); + writel(0, base + NvRegIrqMask); + } pci_push(base); dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name); spin_unlock_irq(&np->lock); - nv_free_irq(dev); + if (np->msi_flags & NV_MSI_X_ENABLED) { + for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { + free_irq(np->msi_x_entry[i].vector, dev); + } + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + } else { + free_irq(np->pci_dev->irq, dev); + if (np->msi_flags & NV_MSI_ENABLED) { + pci_disable_msi(np->pci_dev); + np->msi_flags &= ~NV_MSI_ENABLED; + } + } drain_ring(dev); @@ -3120,18 +2974,20 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i if (id->driver_data & DEV_HAS_HIGH_DMA) { /* packet format 3: supports 40-bit addressing */ np->desc_ver = DESC_VER_3; - np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", pci_name(pci_dev)); } else { - dev->features |= NETIF_F_HIGHDMA; - printk(KERN_INFO "forcedeth: using HIGHDMA\n"); - } - if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) { - printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n", - pci_name(pci_dev)); + if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) { + printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n", + pci_name(pci_dev)); + goto out_relreg; + } else { + dev->features |= NETIF_F_HIGHDMA; + printk(KERN_INFO "forcedeth: using HIGHDMA\n"); + } } + np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; } else if (id->driver_data & DEV_HAS_LARGEDESC) { /* packet format 2: supports jumbo frames */ np->desc_ver = DESC_VER_2; -- cgit 1.2.3-korg From 38bb6b288bf4fb954a3793e57c7339774c842a54 Mon Sep 17 00:00:00 2001 From: "John W. Linville" Date: Fri, 19 May 2006 10:51:21 -0400 Subject: [PATCH] via-rhine: revert "change mdelay to msleep and remove from ISR path" Revert previous patch with subject "change mdelay to msleep and remove from ISR path". This patch seems to have caused bigger problems than it solved, and it didn't solve much of a problem to begin with... Discussion about backing-out this patch can be found here: http://marc.theaimsgroup.com/?l=linux-netdev&m=114321570402396&w=2 The git commit associated w/ the original patch is: 6ba98d311d0a4ff7dc36d8f435ce60174f4c30ec Signed-off-by: John W. Linville --- drivers/net/via-rhine.c | 34 +++------------------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index a6dc53b4250d83..fdc21037f6dcf8 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c @@ -491,8 +491,6 @@ struct rhine_private { u8 tx_thresh, rx_thresh; struct mii_if_info mii_if; - struct work_struct tx_timeout_task; - struct work_struct check_media_task; void __iomem *base; }; @@ -500,8 +498,6 @@ static int mdio_read(struct net_device *dev, int phy_id, int location); static void mdio_write(struct net_device *dev, int phy_id, int location, int value); static int rhine_open(struct net_device *dev); static void rhine_tx_timeout(struct net_device *dev); -static void rhine_tx_timeout_task(struct net_device *dev); -static void rhine_check_media_task(struct net_device *dev); static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev); static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); static void rhine_tx(struct net_device *dev); @@ -856,12 +852,6 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, if (rp->quirks & rqRhineI) dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; - INIT_WORK(&rp->tx_timeout_task, - (void (*)(void *))rhine_tx_timeout_task, dev); - - INIT_WORK(&rp->check_media_task, - (void (*)(void *))rhine_check_media_task, dev); - /* dev->name not defined before register_netdev()! */ rc = register_netdev(dev); if (rc) @@ -1108,11 +1098,6 @@ static void rhine_set_carrier(struct mii_if_info *mii) netif_carrier_ok(mii->dev)); } -static void rhine_check_media_task(struct net_device *dev) -{ - rhine_check_media(dev, 0); -} - static void init_registers(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); @@ -1166,8 +1151,8 @@ static void rhine_disable_linkmon(void __iomem *ioaddr, u32 quirks) if (quirks & rqRhineI) { iowrite8(0x01, ioaddr + MIIRegAddr); // MII_BMSR - /* Do not call from ISR! */ - msleep(1); + /* Can be called from ISR. Evil. */ + mdelay(1); /* 0x80 must be set immediately before turning it off */ iowrite8(0x80, ioaddr + MIICmd); @@ -1255,16 +1240,6 @@ static int rhine_open(struct net_device *dev) } static void rhine_tx_timeout(struct net_device *dev) -{ - struct rhine_private *rp = netdev_priv(dev); - - /* - * Move bulk of work outside of interrupt context - */ - schedule_work(&rp->tx_timeout_task); -} - -static void rhine_tx_timeout_task(struct net_device *dev) { struct rhine_private *rp = netdev_priv(dev); void __iomem *ioaddr = rp->base; @@ -1677,7 +1652,7 @@ static void rhine_error(struct net_device *dev, int intr_status) spin_lock(&rp->lock); if (intr_status & IntrLinkChange) - schedule_work(&rp->check_media_task); + rhine_check_media(dev, 0); if (intr_status & IntrStatsMax) { rp->stats.rx_crc_errors += ioread16(ioaddr + RxCRCErrs); rp->stats.rx_missed_errors += ioread16(ioaddr + RxMissed); @@ -1927,9 +1902,6 @@ static int rhine_close(struct net_device *dev) spin_unlock_irq(&rp->lock); free_irq(rp->pdev->irq, dev); - - flush_scheduled_work(); - free_rbufs(dev); free_tbufs(dev); free_ring(dev); -- cgit 1.2.3-korg From ee7abb04df92b444069be8fe47d66d809de23782 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Thu, 18 May 2006 11:16:21 -0700 Subject: [PATCH] sky2: allow dual port usage If both ports are receiving on the SysKonnect dual port cards, then it appears the bus interface unit can give an interrupt status for frame before DMA has completed. This leads to bogus frames and general confusion. This is why receive checksumming is also messed up on dual port cards. A workaround for the out of order receive problem is to eliminating split transactions on PCI-X. This version is based of the current linux-2.6.git including earlier patch to disable dual ports. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 62be6d99d05cd3..277c57b3df9cfd 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1020,19 +1020,26 @@ static int sky2_up(struct net_device *dev) struct sky2_hw *hw = sky2->hw; unsigned port = sky2->port; u32 ramsize, rxspace, imask; - int err; + int cap, err = -ENOMEM; struct net_device *otherdev = hw->dev[sky2->port^1]; - /* Block bringing up both ports at the same time on a dual port card. - * There is an unfixed bug where receiver gets confused and picks up - * packets out of order. Until this is fixed, prevent data corruption. + /* + * On dual port PCI-X card, there is an problem where status + * can be received out of order due to split transactions */ - if (otherdev && netif_running(otherdev)) { - printk(KERN_INFO PFX "dual port support is disabled.\n"); - return -EBUSY; - } + if (otherdev && netif_running(otherdev) && + (cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PCIX))) { + struct sky2_port *osky2 = netdev_priv(otherdev); + u16 cmd; + + cmd = sky2_pci_read16(hw, cap + PCI_X_CMD); + cmd &= ~PCI_X_CMD_MAX_SPLIT; + sky2_pci_write16(hw, cap + PCI_X_CMD, cmd); + + sky2->rx_csum = 0; + osky2->rx_csum = 0; + } - err = -ENOMEM; if (netif_msg_ifup(sky2)) printk(KERN_INFO PFX "%s: enabling interface\n", dev->name); @@ -3078,12 +3085,7 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw, sky2->duplex = -1; sky2->speed = -1; sky2->advertising = sky2_supported_modes(hw); - - /* Receive checksum disabled for Yukon XL - * because of observed problems with incorrect - * values when multiple packets are received in one interrupt - */ - sky2->rx_csum = (hw->chip_id != CHIP_ID_YUKON_XL); + sky2->rx_csum = 1; spin_lock_init(&sky2->phy_lock); sky2->tx_pending = TX_DEF_PENDING; -- cgit 1.2.3-korg From 2d2a387199bf38c6628adb9c6184d7ab6e306148 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 17 May 2006 14:37:04 -0700 Subject: [PATCH] Subjec: sky2, skge: correct PCI id for DGE-560T The Dlink DGE-560T uses Yukon2 chipset so it needs sky2 driver; and the DGE-530T uses Yukon1 so it uses skge driver. Bug: http://bugzilla.kernel.org/show_bug.cgi?id=6544 Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 3 +-- drivers/net/sky2.c | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index a70c2b0cc10425..63a6b3dfc0951f 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -78,8 +78,7 @@ static const struct pci_device_id skge_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_GE) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, PCI_DEVICE_ID_SYSKONNECT_YU) }, { PCI_DEVICE(PCI_VENDOR_ID_DLINK, PCI_DEVICE_ID_DLINK_DGE510T), }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* DGE-530T */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ { PCI_DEVICE(PCI_VENDOR_ID_CNET, PCI_DEVICE_ID_CNET_GIGACARD) }, diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 277c57b3df9cfd..795adfad18bf60 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -105,6 +105,7 @@ MODULE_PARM_DESC(idle_timeout, "Idle timeout workaround for lost interrupts (ms) static const struct pci_device_id sky2_id_table[] = { { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9000) }, { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x9E00) }, + { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b00) }, /* DGE-560T */ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4340) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4341) }, { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4342) }, -- cgit 1.2.3-korg From 86a31a759f2117816b8c78a049c41ead3ef9ef1c Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 17 May 2006 14:37:05 -0700 Subject: [PATCH] sky2: more fixes for Yukon Ultra Logic error in the phy initialization code. Also, turn on wake on lan bit in status control. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 3 ++- drivers/net/sky2.h | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 795adfad18bf60..bb185e5efa3560 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -236,6 +236,7 @@ static int sky2_set_power_state(struct sky2_hw *hw, pci_power_t state) } if (hw->chip_id == CHIP_ID_YUKON_EC_U) { + sky2_write16(hw, B0_CTST, Y2_HW_WOL_ON); sky2_pci_write32(hw, PCI_DEV_REG3, 0); reg1 = sky2_pci_read32(hw, PCI_DEV_REG4); reg1 &= P_ASPM_CONTROL_MSK; @@ -307,7 +308,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) u16 ctrl, ct1000, adv, pg, ledctrl, ledover; if (sky2->autoneg == AUTONEG_ENABLE && - (hw->chip_id != CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { + !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index 8012994c9b9321..8a0bc5525f0a64 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h @@ -214,6 +214,8 @@ enum csr_regs { enum { Y2_VMAIN_AVAIL = 1<<17,/* VMAIN available (YUKON-2 only) */ Y2_VAUX_AVAIL = 1<<16,/* VAUX available (YUKON-2 only) */ + Y2_HW_WOL_ON = 1<<15,/* HW WOL On (Yukon-EC Ultra A1 only) */ + Y2_HW_WOL_OFF = 1<<14,/* HW WOL On (Yukon-EC Ultra A1 only) */ Y2_ASF_ENABLE = 1<<13,/* ASF Unit Enable (YUKON-2 only) */ Y2_ASF_DISABLE = 1<<12,/* ASF Unit Disable (YUKON-2 only) */ Y2_CLK_RUN_ENA = 1<<11,/* CLK_RUN Enable (YUKON-2 only) */ -- cgit 1.2.3-korg From 86fba6342dee30a1533b14da284d79e4eb66de26 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 17 May 2006 14:37:06 -0700 Subject: [PATCH] sky2: force NAPI repoll if busy If the status ring processing can't keep up with the incoming frames, it is more efficient to have NAPI keep scheduling the poll routine rather than causing another interrupt. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index bb185e5efa3560..9729062d1fbbf5 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -1919,6 +1919,12 @@ static inline void sky2_tx_done(struct net_device *dev, u16 last) } } +/* Is status ring empty or is there more to do? */ +static inline int sky2_more_work(const struct sky2_hw *hw) +{ + return (hw->st_idx != sky2_read16(hw, STAT_PUT_IDX)); +} + /* Process status response ring */ static int sky2_status_intr(struct sky2_hw *hw, int to_do) { @@ -2191,19 +2197,19 @@ static int sky2_poll(struct net_device *dev0, int *budget) if (status & Y2_IS_CHK_TXA2) sky2_descriptor_error(hw, 1, "transmit", Y2_IS_CHK_TXA2); - if (status & Y2_IS_STAT_BMU) - sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); - work_done = sky2_status_intr(hw, work_limit); *budget -= work_done; dev0->quota -= work_done; - if (work_done >= work_limit) + if (status & Y2_IS_STAT_BMU) + sky2_write32(hw, STAT_CTRL, SC_STAT_CLR_IRQ); + + if (sky2_more_work(hw)) return 1; netif_rx_complete(dev0); - status = sky2_read32(hw, B0_Y2_SP_LISR); + sky2_read32(hw, B0_Y2_SP_LISR); return 0; } -- cgit 1.2.3-korg From c9b84dcac6e20ec8e5424f3dff853daa863bfdd0 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 17 May 2006 14:37:07 -0700 Subject: [PATCH] sky2 version 1.4 Need to track impact of this group of changes. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 9729062d1fbbf5..60779ebf2ff6a9 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -51,7 +51,7 @@ #include "sky2.h" #define DRV_NAME "sky2" -#define DRV_VERSION "1.3" +#define DRV_VERSION "1.4" #define PFX DRV_NAME " " /* -- cgit 1.2.3-korg From 20e777a2a7dc9fad3d0b016c662c2fb60e6b20e7 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 15 May 2006 16:30:25 -0700 Subject: [PATCH] skge: bad checksums on big-endian platforms Skge driver always causes bad checksums on big-endian. The checksum in the receive control block was being swapped when it doesn't need to be. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 63a6b3dfc0951f..0dd42470136d7b 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -2716,8 +2716,7 @@ static int skge_poll(struct net_device *dev, int *budget) if (control & BMU_OWN) break; - skb = skge_rx_get(skge, e, control, rd->status, - le16_to_cpu(rd->csum2)); + skb = skge_rx_get(skge, e, control, rd->status, rd->csum2); if (likely(skb)) { dev->last_rx = jiffies; netif_receive_skb(skb); -- cgit 1.2.3-korg From a06631cbdc09fe33892f08238be498eaa84892ee Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 15 May 2006 16:32:39 -0700 Subject: [PATCH] skge: don't allow transmit ring to be too small The driver will get stuck (permanent transmit timeout), if the transmit ring size is set too small. It needs to have enough ring elements to hold one maximum size transmit. Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- drivers/net/skge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 0dd42470136d7b..5ca5a1b546a162 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c @@ -401,7 +401,7 @@ static int skge_set_ring_param(struct net_device *dev, int err; if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE || - p->tx_pending == 0 || p->tx_pending > MAX_TX_RING_SIZE) + p->tx_pending < MAX_SKB_FRAGS+1 || p->tx_pending > MAX_TX_RING_SIZE) return -EINVAL; skge->rx_ring.count = p->rx_pending; -- cgit 1.2.3-korg From f905703a93b7014a0fd95d0edac2b734bf0d1522 Mon Sep 17 00:00:00 2001 From: Komuro Date: Sun, 30 Apr 2006 09:54:13 +0900 Subject: [PATCH] network: axnet_cs: bug fix multicast code (support older ax88190 chipset) Dear Jeff axnet_cs: bug fix multicast code (support older ax88190 chipset) Signed-off-by: komurojun-mbn@nifty.com Best Regards Komuro Signed-off-by: Jeff Garzik --- drivers/net/pcmcia/axnet_cs.c | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/drivers/net/pcmcia/axnet_cs.c b/drivers/net/pcmcia/axnet_cs.c index 448a09488529f5..2ea66aca648b41 100644 --- a/drivers/net/pcmcia/axnet_cs.c +++ b/drivers/net/pcmcia/axnet_cs.c @@ -1691,17 +1691,6 @@ static void do_set_multicast_list(struct net_device *dev) memset(ei_local->mcfilter, 0xFF, 8); } - /* - * DP8390 manuals don't specify any magic sequence for altering - * the multicast regs on an already running card. To be safe, we - * ensure multicast mode is off prior to loading up the new hash - * table. If this proves to be not enough, we can always resort - * to stopping the NIC, loading the table and then restarting. - */ - - if (netif_running(dev)) - outb_p(E8390_RXCONFIG, e8390_base + EN0_RXCR); - outb_p(E8390_NODMA + E8390_PAGE1, e8390_base + E8390_CMD); for(i = 0; i < 8; i++) { @@ -1715,6 +1704,8 @@ static void do_set_multicast_list(struct net_device *dev) outb_p(E8390_RXCONFIG | 0x48, e8390_base + EN0_RXCR); else outb_p(E8390_RXCONFIG | 0x40, e8390_base + EN0_RXCR); + + outb_p(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); } /* -- cgit 1.2.3-korg From bb02aacc02c6002143a1cfc313d144a413eec8d0 Mon Sep 17 00:00:00 2001 From: "Erling A. Jacobsen" Date: Sun, 30 Apr 2006 21:46:56 +0200 Subject: [PATCH] winbond-840-remove-badness-in-pci_map_single Call pci_map_single() with the actual size of the receive buffers, not 0 (which skb->len is initialized to by dev_alloc_skb()). Signed-off-by: Erling A. Jacobsen Signed-off-by: Jeff Garzik --- drivers/net/tulip/winbond-840.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/tulip/winbond-840.c b/drivers/net/tulip/winbond-840.c index ba05dedf29d339..136a70c4d5e488 100644 --- a/drivers/net/tulip/winbond-840.c +++ b/drivers/net/tulip/winbond-840.c @@ -850,7 +850,7 @@ static void init_rxtx_rings(struct net_device *dev) break; skb->dev = dev; /* Mark as being used by this device. */ np->rx_addr[i] = pci_map_single(np->pci_dev,skb->data, - skb->len,PCI_DMA_FROMDEVICE); + np->rx_buf_sz,PCI_DMA_FROMDEVICE); np->rx_ring[i].buffer1 = np->rx_addr[i]; np->rx_ring[i].status = DescOwn; @@ -1316,7 +1316,7 @@ static int netdev_rx(struct net_device *dev) skb->dev = dev; /* Mark as being used by this device. */ np->rx_addr[entry] = pci_map_single(np->pci_dev, skb->data, - skb->len, PCI_DMA_FROMDEVICE); + np->rx_buf_sz, PCI_DMA_FROMDEVICE); np->rx_ring[entry].buffer1 = np->rx_addr[entry]; } wmb(); -- cgit 1.2.3-korg From 84b3932bf0fd8cdc8c75a5be77e1dded1e6479c6 Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Sat, 20 May 2006 14:59:48 -0700 Subject: [PATCH] forcedeth: fix multi irq issues With Manfred Spraul and Andrew Morton Bring back this recently-reverted patch, only fixed. Original changelog: From: Ayaz Abdulla This patch fixes the issues with multiple irqs. I am resending based on feedback. I decoupled the dma mask for consistent memory and fixed leak with multiple irq in error path. Thanks to Manfred for catching the spin lock problem. Fix it: From: Manfred Spraul Fix bug introduced by ebf34c9b6fcd22338ef764b039b3ac55ed0e297b, covered in http://bugzilla.kernel.org/show_bug.cgi?id=6568. Remove second instance of the request_irq() calls: they were moved from nv_open into nv_request_irq. Thanks to Alistair Strachan for reporting and persisting. Signed-off-by: Ayaz Abdulla Signed-off-by: Manfred Spraul Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/forcedeth.c | 380 ++++++++++++++++++++++++++++-------------------- 1 file changed, 226 insertions(+), 154 deletions(-) diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 7e078b4cca7cd3..705e1229d89db9 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -106,6 +106,7 @@ * 0.51: 20 Jan 2006: Add 64bit consistent memory allocation for rings. * 0.52: 20 Jan 2006: Add MSI/MSIX support. * 0.53: 19 Mar 2006: Fix init from low power mode and add hw reset. + * 0.54: 21 Mar 2006: Fix spin locks for multi irqs and cleanup. * * Known bugs: * We suspect that on some hardware no TX done interrupts are generated. @@ -117,7 +118,7 @@ * DEV_NEED_TIMERIRQ will not harm you on sane hardware, only generating a few * superfluous timer interrupts from the nic. */ -#define FORCEDETH_VERSION "0.53" +#define FORCEDETH_VERSION "0.54" #define DRV_NAME "forcedeth" #include @@ -710,6 +711,72 @@ static void setup_hw_rings(struct net_device *dev, int rxtx_flags) } } +static int using_multi_irqs(struct net_device *dev) +{ + struct fe_priv *np = get_nvpriv(dev); + + if (!(np->msi_flags & NV_MSI_X_ENABLED) || + ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) + return 0; + else + return 1; +} + +static void nv_enable_irq(struct net_device *dev) +{ + struct fe_priv *np = get_nvpriv(dev); + + if (!using_multi_irqs(dev)) { + if (np->msi_flags & NV_MSI_X_ENABLED) + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); + else + enable_irq(dev->irq); + } else { + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); + } +} + +static void nv_disable_irq(struct net_device *dev) +{ + struct fe_priv *np = get_nvpriv(dev); + + if (!using_multi_irqs(dev)) { + if (np->msi_flags & NV_MSI_X_ENABLED) + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); + else + disable_irq(dev->irq); + } else { + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); + } +} + +/* In MSIX mode, a write to irqmask behaves as XOR */ +static void nv_enable_hw_interrupts(struct net_device *dev, u32 mask) +{ + u8 __iomem *base = get_hwbase(dev); + + writel(mask, base + NvRegIrqMask); +} + +static void nv_disable_hw_interrupts(struct net_device *dev, u32 mask) +{ + struct fe_priv *np = get_nvpriv(dev); + u8 __iomem *base = get_hwbase(dev); + + if (np->msi_flags & NV_MSI_X_ENABLED) { + writel(mask, base + NvRegIrqMask); + } else { + if (np->msi_flags & NV_MSI_ENABLED) + writel(0, base + NvRegMSIIrqMask); + writel(0, base + NvRegIrqMask); + } +} + #define MII_READ (-1) /* mii_rw: read/write a register on the PHY. * @@ -1019,24 +1086,25 @@ static void nv_do_rx_refill(unsigned long data) struct net_device *dev = (struct net_device *) data; struct fe_priv *np = netdev_priv(dev); - - if (!(np->msi_flags & NV_MSI_X_ENABLED) || - ((np->msi_flags & NV_MSI_X_ENABLED) && - ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { - disable_irq(dev->irq); + if (!using_multi_irqs(dev)) { + if (np->msi_flags & NV_MSI_X_ENABLED) + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); + else + disable_irq(dev->irq); } else { disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); } if (nv_alloc_rx(dev)) { - spin_lock(&np->lock); + spin_lock_irq(&np->lock); if (!np->in_shutdown) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock(&np->lock); + spin_unlock_irq(&np->lock); } - if (!(np->msi_flags & NV_MSI_X_ENABLED) || - ((np->msi_flags & NV_MSI_X_ENABLED) && - ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { - enable_irq(dev->irq); + if (!using_multi_irqs(dev)) { + if (np->msi_flags & NV_MSI_X_ENABLED) + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); + else + enable_irq(dev->irq); } else { enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); } @@ -1668,15 +1736,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) * guessed, there is probably a simpler approach. * Changing the MTU is a rare event, it shouldn't matter. */ - if (!(np->msi_flags & NV_MSI_X_ENABLED) || - ((np->msi_flags & NV_MSI_X_ENABLED) && - ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { - disable_irq(dev->irq); - } else { - disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); - disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); - disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); - } + nv_disable_irq(dev); spin_lock_bh(&dev->xmit_lock); spin_lock(&np->lock); /* stop engines */ @@ -1709,15 +1769,7 @@ static int nv_change_mtu(struct net_device *dev, int new_mtu) nv_start_tx(dev); spin_unlock(&np->lock); spin_unlock_bh(&dev->xmit_lock); - if (!(np->msi_flags & NV_MSI_X_ENABLED) || - ((np->msi_flags & NV_MSI_X_ENABLED) && - ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { - enable_irq(dev->irq); - } else { - enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector); - enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector); - enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector); - } + nv_enable_irq(dev); } return 0; } @@ -2108,16 +2160,16 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) if (!(events & np->irqmask)) break; - spin_lock(&np->lock); + spin_lock_irq(&np->lock); nv_tx_done(dev); - spin_unlock(&np->lock); + spin_unlock_irq(&np->lock); if (events & (NVREG_IRQ_TX_ERR)) { dprintk(KERN_DEBUG "%s: received irq with events 0x%x. Probably TX fail.\n", dev->name, events); } if (i > max_interrupt_work) { - spin_lock(&np->lock); + spin_lock_irq(&np->lock); /* disable interrupts on the nic */ writel(NVREG_IRQ_TX_ALL, base + NvRegIrqMask); pci_push(base); @@ -2127,7 +2179,7 @@ static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs) mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_tx.\n", dev->name, i); - spin_unlock(&np->lock); + spin_unlock_irq(&np->lock); break; } @@ -2157,14 +2209,14 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) nv_rx_process(dev); if (nv_alloc_rx(dev)) { - spin_lock(&np->lock); + spin_lock_irq(&np->lock); if (!np->in_shutdown) mod_timer(&np->oom_kick, jiffies + OOM_REFILL); - spin_unlock(&np->lock); + spin_unlock_irq(&np->lock); } if (i > max_interrupt_work) { - spin_lock(&np->lock); + spin_lock_irq(&np->lock); /* disable interrupts on the nic */ writel(NVREG_IRQ_RX_ALL, base + NvRegIrqMask); pci_push(base); @@ -2174,7 +2226,7 @@ static irqreturn_t nv_nic_irq_rx(int foo, void *data, struct pt_regs *regs) mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_rx.\n", dev->name, i); - spin_unlock(&np->lock); + spin_unlock_irq(&np->lock); break; } @@ -2203,14 +2255,14 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) break; if (events & NVREG_IRQ_LINK) { - spin_lock(&np->lock); + spin_lock_irq(&np->lock); nv_link_irq(dev); - spin_unlock(&np->lock); + spin_unlock_irq(&np->lock); } if (np->need_linktimer && time_after(jiffies, np->link_timeout)) { - spin_lock(&np->lock); + spin_lock_irq(&np->lock); nv_linkchange(dev); - spin_unlock(&np->lock); + spin_unlock_irq(&np->lock); np->link_timeout = jiffies + LINK_TIMEOUT; } if (events & (NVREG_IRQ_UNKNOWN)) { @@ -2218,7 +2270,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) dev->name, events); } if (i > max_interrupt_work) { - spin_lock(&np->lock); + spin_lock_irq(&np->lock); /* disable interrupts on the nic */ writel(NVREG_IRQ_OTHER, base + NvRegIrqMask); pci_push(base); @@ -2228,7 +2280,7 @@ static irqreturn_t nv_nic_irq_other(int foo, void *data, struct pt_regs *regs) mod_timer(&np->nic_poll, jiffies + POLL_WAIT); } printk(KERN_DEBUG "%s: too many iterations (%d) in nv_nic_irq_other.\n", dev->name, i); - spin_unlock(&np->lock); + spin_unlock_irq(&np->lock); break; } @@ -2251,10 +2303,11 @@ static void nv_do_nic_poll(unsigned long data) * nv_nic_irq because that may decide to do otherwise */ - if (!(np->msi_flags & NV_MSI_X_ENABLED) || - ((np->msi_flags & NV_MSI_X_ENABLED) && - ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { - disable_irq(dev->irq); + if (!using_multi_irqs(dev)) { + if (np->msi_flags & NV_MSI_X_ENABLED) + disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); + else + disable_irq(dev->irq); mask = np->irqmask; } else { if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { @@ -2277,11 +2330,12 @@ static void nv_do_nic_poll(unsigned long data) writel(mask, base + NvRegIrqMask); pci_push(base); - if (!(np->msi_flags & NV_MSI_X_ENABLED) || - ((np->msi_flags & NV_MSI_X_ENABLED) && - ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) { + if (!using_multi_irqs(dev)) { nv_nic_irq((int) 0, (void *) data, (struct pt_regs *) NULL); - enable_irq(dev->irq); + if (np->msi_flags & NV_MSI_X_ENABLED) + enable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector); + else + enable_irq(dev->irq); } else { if (np->nic_poll_irq & NVREG_IRQ_RX_ALL) { nv_nic_irq_rx((int) 0, (void *) data, (struct pt_regs *) NULL); @@ -2628,6 +2682,113 @@ static void set_msix_vector_map(struct net_device *dev, u32 vector, u32 irqmask) writel(readl(base + NvRegMSIXMap1) | msixmap, base + NvRegMSIXMap1); } +static int nv_request_irq(struct net_device *dev) +{ + struct fe_priv *np = get_nvpriv(dev); + u8 __iomem *base = get_hwbase(dev); + int ret = 1; + int i; + + if (np->msi_flags & NV_MSI_X_CAPABLE) { + for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { + np->msi_x_entry[i].entry = i; + } + if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) { + np->msi_flags |= NV_MSI_X_ENABLED; + if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) { + /* Request irq for rx handling */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_err; + } + /* Request irq for tx handling */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_free_rx; + } + /* Request irq for link and timer handling */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_free_tx; + } + /* map interrupts to their respective vector */ + writel(0, base + NvRegMSIXMap0); + writel(0, base + NvRegMSIXMap1); + set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL); + set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL); + set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER); + } else { + /* Request irq for all interrupts */ + if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + goto out_err; + } + + /* map interrupts to vector 0 */ + writel(0, base + NvRegMSIXMap0); + writel(0, base + NvRegMSIXMap1); + } + } + } + if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { + if ((ret = pci_enable_msi(np->pci_dev)) == 0) { + np->msi_flags |= NV_MSI_ENABLED; + if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { + printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); + pci_disable_msi(np->pci_dev); + np->msi_flags &= ~NV_MSI_ENABLED; + goto out_err; + } + + /* map interrupts to vector 0 */ + writel(0, base + NvRegMSIMap0); + writel(0, base + NvRegMSIMap1); + /* enable msi vector 0 */ + writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); + } + } + if (ret != 0) { + if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) + goto out_err; + } + + return 0; +out_free_tx: + free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, dev); +out_free_rx: + free_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, dev); +out_err: + return 1; +} + +static void nv_free_irq(struct net_device *dev) +{ + struct fe_priv *np = get_nvpriv(dev); + int i; + + if (np->msi_flags & NV_MSI_X_ENABLED) { + for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { + free_irq(np->msi_x_entry[i].vector, dev); + } + pci_disable_msix(np->pci_dev); + np->msi_flags &= ~NV_MSI_X_ENABLED; + } else { + free_irq(np->pci_dev->irq, dev); + if (np->msi_flags & NV_MSI_ENABLED) { + pci_disable_msi(np->pci_dev); + np->msi_flags &= ~NV_MSI_ENABLED; + } + } +} + static int nv_open(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); @@ -2720,86 +2881,18 @@ static int nv_open(struct net_device *dev) udelay(10); writel(readl(base + NvRegPowerState) | NVREG_POWERSTATE_VALID, base + NvRegPowerState); - writel(0, base + NvRegIrqMask); + nv_disable_hw_interrupts(dev, np->irqmask); pci_push(base); writel(NVREG_MIISTAT_MASK2, base + NvRegMIIStatus); writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus); pci_push(base); - if (np->msi_flags & NV_MSI_X_CAPABLE) { - for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { - np->msi_x_entry[i].entry = i; - } - if ((ret = pci_enable_msix(np->pci_dev, np->msi_x_entry, (np->msi_flags & NV_MSI_X_VECTORS_MASK))) == 0) { - np->msi_flags |= NV_MSI_X_ENABLED; - if (optimization_mode == NV_OPTIMIZATION_MODE_THROUGHPUT) { - /* Request irq for rx handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector, &nv_nic_irq_rx, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for rx %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_drain; - } - /* Request irq for tx handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_TX].vector, &nv_nic_irq_tx, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for tx %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_drain; - } - /* Request irq for link and timer handling */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_OTHER].vector, &nv_nic_irq_other, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed for link %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_drain; - } - - /* map interrupts to their respective vector */ - writel(0, base + NvRegMSIXMap0); - writel(0, base + NvRegMSIXMap1); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_RX, NVREG_IRQ_RX_ALL); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_TX, NVREG_IRQ_TX_ALL); - set_msix_vector_map(dev, NV_MSI_X_VECTOR_OTHER, NVREG_IRQ_OTHER); - } else { - /* Request irq for all interrupts */ - if (request_irq(np->msi_x_entry[NV_MSI_X_VECTOR_ALL].vector, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - goto out_drain; - } - - /* map interrupts to vector 0 */ - writel(0, base + NvRegMSIXMap0); - writel(0, base + NvRegMSIXMap1); - } - } - } - if (ret != 0 && np->msi_flags & NV_MSI_CAPABLE) { - if ((ret = pci_enable_msi(np->pci_dev)) == 0) { - np->msi_flags |= NV_MSI_ENABLED; - if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) { - printk(KERN_INFO "forcedeth: request_irq failed %d\n", ret); - pci_disable_msi(np->pci_dev); - np->msi_flags &= ~NV_MSI_ENABLED; - goto out_drain; - } - - /* map interrupts to vector 0 */ - writel(0, base + NvRegMSIMap0); - writel(0, base + NvRegMSIMap1); - /* enable msi vector 0 */ - writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); - } - } - if (ret != 0) { - if (request_irq(np->pci_dev->irq, &nv_nic_irq, SA_SHIRQ, dev->name, dev) != 0) - goto out_drain; + if (nv_request_irq(dev)) { + goto out_drain; } /* ask for interrupts */ - writel(np->irqmask, base + NvRegIrqMask); + nv_enable_hw_interrupts(dev, np->irqmask); spin_lock_irq(&np->lock); writel(NVREG_MCASTADDRA_FORCE, base + NvRegMulticastAddrA); @@ -2843,7 +2936,6 @@ static int nv_close(struct net_device *dev) { struct fe_priv *np = netdev_priv(dev); u8 __iomem *base; - int i; spin_lock_irq(&np->lock); np->in_shutdown = 1; @@ -2861,31 +2953,13 @@ static int nv_close(struct net_device *dev) /* disable interrupts on the nic or we will lock up */ base = get_hwbase(dev); - if (np->msi_flags & NV_MSI_X_ENABLED) { - writel(np->irqmask, base + NvRegIrqMask); - } else { - if (np->msi_flags & NV_MSI_ENABLED) - writel(0, base + NvRegMSIIrqMask); - writel(0, base + NvRegIrqMask); - } + nv_disable_hw_interrupts(dev, np->irqmask); pci_push(base); dprintk(KERN_INFO "%s: Irqmask is zero again\n", dev->name); spin_unlock_irq(&np->lock); - if (np->msi_flags & NV_MSI_X_ENABLED) { - for (i = 0; i < (np->msi_flags & NV_MSI_X_VECTORS_MASK); i++) { - free_irq(np->msi_x_entry[i].vector, dev); - } - pci_disable_msix(np->pci_dev); - np->msi_flags &= ~NV_MSI_X_ENABLED; - } else { - free_irq(np->pci_dev->irq, dev); - if (np->msi_flags & NV_MSI_ENABLED) { - pci_disable_msi(np->pci_dev); - np->msi_flags &= ~NV_MSI_ENABLED; - } - } + nv_free_irq(dev); drain_ring(dev); @@ -2974,20 +3048,18 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i if (id->driver_data & DEV_HAS_HIGH_DMA) { /* packet format 3: supports 40-bit addressing */ np->desc_ver = DESC_VER_3; + np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; if (pci_set_dma_mask(pci_dev, DMA_39BIT_MASK)) { printk(KERN_INFO "forcedeth: 64-bit DMA failed, using 32-bit addressing for device %s.\n", pci_name(pci_dev)); } else { - if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) { - printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n", - pci_name(pci_dev)); - goto out_relreg; - } else { - dev->features |= NETIF_F_HIGHDMA; - printk(KERN_INFO "forcedeth: using HIGHDMA\n"); - } + dev->features |= NETIF_F_HIGHDMA; + printk(KERN_INFO "forcedeth: using HIGHDMA\n"); + } + if (pci_set_consistent_dma_mask(pci_dev, 0x0000007fffffffffULL)) { + printk(KERN_INFO "forcedeth: 64-bit DMA (consistent) failed for device %s.\n", + pci_name(pci_dev)); } - np->txrxctl_bits = NVREG_TXRXCTL_DESC_3; } else if (id->driver_data & DEV_HAS_LARGEDESC) { /* packet format 2: supports jumbo frames */ np->desc_ver = DESC_VER_2; -- cgit 1.2.3-korg From d64b1c878fc1e384ae53d1d40034239bc33848f4 Mon Sep 17 00:00:00 2001 From: Lin Feng Shen Date: Sat, 20 May 2006 14:59:49 -0700 Subject: [PATCH] NFS: fix error handling on access_ok in compat_sys_nfsservctl Functions compat_nfs_svc_trans, compat_nfs_clnt_trans, compat_nfs_exp_trans, compat_nfs_getfd_trans and compat_nfs_getfs_trans, which are called by compat_sys_nfsservctl(fs/compat.c), don't handle the return value of access_ok properly. access_ok return 1 when the addr is valid, and 0 when it's not, but these functions have the reversed understanding. When the address is valid, they always return -EFAULT to compat_sys_nfsservctl. An example is to run /usr/sbin/rpc.nfsd(32bit program on Power5). It doesn't function as expected. strace showes that nfsservctl returns -EFAULT. The patch fixes this by correcting the error handling on the return value of access_ok in the five functions. Signed-off-by: Lin Feng Shen Cc: Trond Myklebust Acked-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/compat.c | 177 +++++++++++++++++++++++++++++++----------------------------- 1 file changed, 92 insertions(+), 85 deletions(-) diff --git a/fs/compat.c b/fs/compat.c index 01f39f87f372ec..b1f64786a613e5 100644 --- a/fs/compat.c +++ b/fs/compat.c @@ -2030,109 +2030,115 @@ union compat_nfsctl_res { struct knfsd_fh cr32_getfs; }; -static int compat_nfs_svc_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg) -{ - int err; - - err = access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)); - err |= get_user(karg->ca_version, &arg->ca32_version); - err |= __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port); - err |= __get_user(karg->ca_svc.svc_nthreads, &arg->ca32_svc.svc32_nthreads); - return (err) ? -EFAULT : 0; +static int compat_nfs_svc_trans(struct nfsctl_arg *karg, + struct compat_nfsctl_arg __user *arg) +{ + if (!access_ok(VERIFY_READ, &arg->ca32_svc, sizeof(arg->ca32_svc)) || + get_user(karg->ca_version, &arg->ca32_version) || + __get_user(karg->ca_svc.svc_port, &arg->ca32_svc.svc32_port) || + __get_user(karg->ca_svc.svc_nthreads, + &arg->ca32_svc.svc32_nthreads)) + return -EFAULT; + return 0; } -static int compat_nfs_clnt_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg) -{ - int err; - - err = access_ok(VERIFY_READ, &arg->ca32_client, sizeof(arg->ca32_client)); - err |= get_user(karg->ca_version, &arg->ca32_version); - err |= __copy_from_user(&karg->ca_client.cl_ident[0], - &arg->ca32_client.cl32_ident[0], - NFSCLNT_IDMAX); - err |= __get_user(karg->ca_client.cl_naddr, &arg->ca32_client.cl32_naddr); - err |= __copy_from_user(&karg->ca_client.cl_addrlist[0], - &arg->ca32_client.cl32_addrlist[0], - (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)); - err |= __get_user(karg->ca_client.cl_fhkeytype, - &arg->ca32_client.cl32_fhkeytype); - err |= __get_user(karg->ca_client.cl_fhkeylen, - &arg->ca32_client.cl32_fhkeylen); - err |= __copy_from_user(&karg->ca_client.cl_fhkey[0], - &arg->ca32_client.cl32_fhkey[0], - NFSCLNT_KEYMAX); +static int compat_nfs_clnt_trans(struct nfsctl_arg *karg, + struct compat_nfsctl_arg __user *arg) +{ + if (!access_ok(VERIFY_READ, &arg->ca32_client, + sizeof(arg->ca32_client)) || + get_user(karg->ca_version, &arg->ca32_version) || + __copy_from_user(&karg->ca_client.cl_ident[0], + &arg->ca32_client.cl32_ident[0], + NFSCLNT_IDMAX) || + __get_user(karg->ca_client.cl_naddr, + &arg->ca32_client.cl32_naddr) || + __copy_from_user(&karg->ca_client.cl_addrlist[0], + &arg->ca32_client.cl32_addrlist[0], + (sizeof(struct in_addr) * NFSCLNT_ADDRMAX)) || + __get_user(karg->ca_client.cl_fhkeytype, + &arg->ca32_client.cl32_fhkeytype) || + __get_user(karg->ca_client.cl_fhkeylen, + &arg->ca32_client.cl32_fhkeylen) || + __copy_from_user(&karg->ca_client.cl_fhkey[0], + &arg->ca32_client.cl32_fhkey[0], + NFSCLNT_KEYMAX)) + return -EFAULT; - return (err) ? -EFAULT : 0; + return 0; } -static int compat_nfs_exp_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg) -{ - int err; - - err = access_ok(VERIFY_READ, &arg->ca32_export, sizeof(arg->ca32_export)); - err |= get_user(karg->ca_version, &arg->ca32_version); - err |= __copy_from_user(&karg->ca_export.ex_client[0], - &arg->ca32_export.ex32_client[0], - NFSCLNT_IDMAX); - err |= __copy_from_user(&karg->ca_export.ex_path[0], - &arg->ca32_export.ex32_path[0], - NFS_MAXPATHLEN); - err |= __get_user(karg->ca_export.ex_dev, - &arg->ca32_export.ex32_dev); - err |= __get_user(karg->ca_export.ex_ino, - &arg->ca32_export.ex32_ino); - err |= __get_user(karg->ca_export.ex_flags, - &arg->ca32_export.ex32_flags); - err |= __get_user(karg->ca_export.ex_anon_uid, - &arg->ca32_export.ex32_anon_uid); - err |= __get_user(karg->ca_export.ex_anon_gid, - &arg->ca32_export.ex32_anon_gid); +static int compat_nfs_exp_trans(struct nfsctl_arg *karg, + struct compat_nfsctl_arg __user *arg) +{ + if (!access_ok(VERIFY_READ, &arg->ca32_export, + sizeof(arg->ca32_export)) || + get_user(karg->ca_version, &arg->ca32_version) || + __copy_from_user(&karg->ca_export.ex_client[0], + &arg->ca32_export.ex32_client[0], + NFSCLNT_IDMAX) || + __copy_from_user(&karg->ca_export.ex_path[0], + &arg->ca32_export.ex32_path[0], + NFS_MAXPATHLEN) || + __get_user(karg->ca_export.ex_dev, + &arg->ca32_export.ex32_dev) || + __get_user(karg->ca_export.ex_ino, + &arg->ca32_export.ex32_ino) || + __get_user(karg->ca_export.ex_flags, + &arg->ca32_export.ex32_flags) || + __get_user(karg->ca_export.ex_anon_uid, + &arg->ca32_export.ex32_anon_uid) || + __get_user(karg->ca_export.ex_anon_gid, + &arg->ca32_export.ex32_anon_gid)) + return -EFAULT; SET_UID(karg->ca_export.ex_anon_uid, karg->ca_export.ex_anon_uid); SET_GID(karg->ca_export.ex_anon_gid, karg->ca_export.ex_anon_gid); - return (err) ? -EFAULT : 0; + return 0; } -static int compat_nfs_getfd_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg) -{ - int err; - - err = access_ok(VERIFY_READ, &arg->ca32_getfd, sizeof(arg->ca32_getfd)); - err |= get_user(karg->ca_version, &arg->ca32_version); - err |= __copy_from_user(&karg->ca_getfd.gd_addr, - &arg->ca32_getfd.gd32_addr, - (sizeof(struct sockaddr))); - err |= __copy_from_user(&karg->ca_getfd.gd_path, - &arg->ca32_getfd.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= __get_user(karg->ca_getfd.gd_version, - &arg->ca32_getfd.gd32_version); +static int compat_nfs_getfd_trans(struct nfsctl_arg *karg, + struct compat_nfsctl_arg __user *arg) +{ + if (!access_ok(VERIFY_READ, &arg->ca32_getfd, + sizeof(arg->ca32_getfd)) || + get_user(karg->ca_version, &arg->ca32_version) || + __copy_from_user(&karg->ca_getfd.gd_addr, + &arg->ca32_getfd.gd32_addr, + (sizeof(struct sockaddr))) || + __copy_from_user(&karg->ca_getfd.gd_path, + &arg->ca32_getfd.gd32_path, + (NFS_MAXPATHLEN+1)) || + __get_user(karg->ca_getfd.gd_version, + &arg->ca32_getfd.gd32_version)) + return -EFAULT; - return (err) ? -EFAULT : 0; + return 0; } -static int compat_nfs_getfs_trans(struct nfsctl_arg *karg, struct compat_nfsctl_arg __user *arg) +static int compat_nfs_getfs_trans(struct nfsctl_arg *karg, + struct compat_nfsctl_arg __user *arg) { - int err; - - err = access_ok(VERIFY_READ, &arg->ca32_getfs, sizeof(arg->ca32_getfs)); - err |= get_user(karg->ca_version, &arg->ca32_version); - err |= __copy_from_user(&karg->ca_getfs.gd_addr, - &arg->ca32_getfs.gd32_addr, - (sizeof(struct sockaddr))); - err |= __copy_from_user(&karg->ca_getfs.gd_path, - &arg->ca32_getfs.gd32_path, - (NFS_MAXPATHLEN+1)); - err |= __get_user(karg->ca_getfs.gd_maxlen, - &arg->ca32_getfs.gd32_maxlen); + if (!access_ok(VERIFY_READ,&arg->ca32_getfs,sizeof(arg->ca32_getfs)) || + get_user(karg->ca_version, &arg->ca32_version) || + __copy_from_user(&karg->ca_getfs.gd_addr, + &arg->ca32_getfs.gd32_addr, + (sizeof(struct sockaddr))) || + __copy_from_user(&karg->ca_getfs.gd_path, + &arg->ca32_getfs.gd32_path, + (NFS_MAXPATHLEN+1)) || + __get_user(karg->ca_getfs.gd_maxlen, + &arg->ca32_getfs.gd32_maxlen)) + return -EFAULT; - return (err) ? -EFAULT : 0; + return 0; } /* This really doesn't need translations, we are only passing * back a union which contains opaque nfs file handle data. */ -static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, union compat_nfsctl_res __user *res) +static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, + union compat_nfsctl_res __user *res) { int err; @@ -2141,8 +2147,9 @@ static int compat_nfs_getfh_res_trans(union nfsctl_res *kres, union compat_nfsct return (err) ? -EFAULT : 0; } -asmlinkage long compat_sys_nfsservctl(int cmd, struct compat_nfsctl_arg __user *arg, - union compat_nfsctl_res __user *res) +asmlinkage long compat_sys_nfsservctl(int cmd, + struct compat_nfsctl_arg __user *arg, + union compat_nfsctl_res __user *res) { struct nfsctl_arg *karg; union nfsctl_res *kres; -- cgit 1.2.3-korg From 6d39bedc47fbf18a940f5843981767c221d22cfe Mon Sep 17 00:00:00 2001 From: "Paul A. Clarke" Date: Sat, 20 May 2006 14:59:51 -0700 Subject: [PATCH] matroxfb: fix DVI setup to be more compatible There has been a longstanding problem with the Matrox G450 and perhaps other similar cards, with modes "above" 1280x1024-60 on ppc/ppc64 boxes running Linux. Higher resolutions and/or higher refresh rates resulted in a very noticably "jittery" display, and sometimes no display, depending on the physical monitor. This patch fixes that problem on the systems I have easy access to... I've tested with SLES9SP3 (2.6.5+ kernel) and 2.6.16-rc6 custom kernels on an IBM eServer p5 520 w/G450 (a.k.a GXT135P on IBM's ppc64 systems), and a colleague of mine (Ian Romanick) tested it successfully on an Apple ppc32 box (w/GXT135P). I also tested it on IA32 box I have with a GXT135P to verify that it didn't obviously break anything. In my testing, I covered single-card, single and dual-head setups using both HD15 and DVI-D signals, on both the IA32 and ppc64 boxes. While everything appeared fine on both boxes, I did encounter one problem: I can't get any signal on the DVI-D output on the ppc64 box. However, this is also the case without my patch. I just noticed that screen-blanking only occurs on the primary display as well. Signed-off-by: Paul A. Clarke Signed-off-by: Ian Romanick Signed-off-by: Petr Vandrovec Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/matrox/g450_pll.c | 23 +++++++++++++++++++++-- drivers/video/matrox/matroxfb_DAC1064.h | 2 ++ drivers/video/matrox/matroxfb_base.h | 2 ++ 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/video/matrox/g450_pll.c b/drivers/video/matrox/g450_pll.c index 8073a73f6f3508..440272ad10e725 100644 --- a/drivers/video/matrox/g450_pll.c +++ b/drivers/video/matrox/g450_pll.c @@ -316,14 +316,24 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, case M_PIXEL_PLL_B: case M_PIXEL_PLL_C: { - u_int8_t tmp; + u_int8_t tmp, xpwrctrl; unsigned long flags; matroxfb_DAC_lock_irqsave(flags); + + xpwrctrl = matroxfb_DAC_in(PMINFO M1064_XPWRCTRL); + matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl & ~M1064_XPWRCTRL_PANELPDN); + mga_outb(M_SEQ_INDEX, M_SEQ1); + mga_outb(M_SEQ_DATA, mga_inb(M_SEQ_DATA) | M_SEQ1_SCROFF); tmp = matroxfb_DAC_in(PMINFO M1064_XPIXCLKCTRL); + tmp |= M1064_XPIXCLKCTRL_DIS; if (!(tmp & M1064_XPIXCLKCTRL_PLL_UP)) { - matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp | M1064_XPIXCLKCTRL_PLL_UP); + tmp |= M1064_XPIXCLKCTRL_PLL_UP; } + matroxfb_DAC_out(PMINFO M1064_XPIXCLKCTRL, tmp); + matroxfb_DAC_out(PMINFO M1064_XDVICLKCTRL, 0); + matroxfb_DAC_out(PMINFO M1064_XPWRCTRL, xpwrctrl); + matroxfb_DAC_unlock_irqrestore(flags); } { @@ -418,6 +428,15 @@ static int __g450_setclk(WPMINFO unsigned int fout, unsigned int pll, frequency to higher - with <= lowest wins, while with < highest one wins */ if (delta <= deltaarray[idx-1]) { + /* all else being equal except VCO, + * choose VCO not near (within 1/16th or so) VCOmin + * (freqs near VCOmin aren't as stable) + */ + if (delta == deltaarray[idx-1] + && vco != g450_mnp2vco(PMINFO mnparray[idx-1]) + && vco < (pi->vcomin * 17 / 16)) { + break; + } mnparray[idx] = mnparray[idx-1]; deltaarray[idx] = deltaarray[idx-1]; } else { diff --git a/drivers/video/matrox/matroxfb_DAC1064.h b/drivers/video/matrox/matroxfb_DAC1064.h index 2e7238aa243209..56513a5d220b03 100644 --- a/drivers/video/matrox/matroxfb_DAC1064.h +++ b/drivers/video/matrox/matroxfb_DAC1064.h @@ -40,6 +40,7 @@ void DAC1064_global_restore(WPMINFO2); #define M1064_XCURCOL1RED 0x0C #define M1064_XCURCOL1GREEN 0x0D #define M1064_XCURCOL1BLUE 0x0E +#define M1064_XDVICLKCTRL 0x0F #define M1064_XCURCOL2RED 0x10 #define M1064_XCURCOL2GREEN 0x11 #define M1064_XCURCOL2BLUE 0x12 @@ -144,6 +145,7 @@ void DAC1064_global_restore(WPMINFO2); #define M1064_XVIDPLLN 0x8F #define M1064_XPWRCTRL 0xA0 +#define M1064_XPWRCTRL_PANELPDN 0x04 #define M1064_XPANMODE 0xA2 diff --git a/drivers/video/matrox/matroxfb_base.h b/drivers/video/matrox/matroxfb_base.h index 3a3e1804c56a50..b71737178d0d9b 100644 --- a/drivers/video/matrox/matroxfb_base.h +++ b/drivers/video/matrox/matroxfb_base.h @@ -672,6 +672,8 @@ void matroxfb_unregister_driver(struct matroxfb_driver* drv); #define M_SEQ_INDEX 0x1FC4 #define M_SEQ_DATA 0x1FC5 +#define M_SEQ1 0x01 +#define M_SEQ1_SCROFF 0x20 #define M_MISC_REG_READ 0x1FCC -- cgit 1.2.3-korg From c44b20d51142acdc9c66108b758c0454a7e2ce11 Mon Sep 17 00:00:00 2001 From: Chuck Ebbert <76306.1226@compuserve.com> Date: Sat, 20 May 2006 14:59:52 -0700 Subject: [PATCH] i386: remove junk from stack dump i386 stack dump has a "<0>" in the middle of the line and an extra space between columns in multicolumn mode. Remove those and also remove an extra blank line of source code. Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com> Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/traps.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/arch/i386/kernel/traps.c b/arch/i386/kernel/traps.c index 2d22f5761b1dc5..0e498369f35e91 100644 --- a/arch/i386/kernel/traps.c +++ b/arch/i386/kernel/traps.c @@ -130,9 +130,8 @@ static inline int print_addr_and_symbol(unsigned long addr, char *log_lvl, print_symbol("%s", addr); printed = (printed + 1) % CONFIG_STACK_BACKTRACE_COLS; - if (printed) - printk(" "); + printk(" "); else printk("\n"); @@ -212,7 +211,6 @@ static void show_stack_log_lvl(struct task_struct *task, unsigned long *esp, } stack = esp; - printk(log_lvl); for(i = 0; i < kstack_depth_to_print; i++) { if (kstack_end(stack)) break; -- cgit 1.2.3-korg From 22192ccd6d1dfea2a41e40442997ccad5b7b160e Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Sat, 20 May 2006 14:59:53 -0700 Subject: [PATCH] powerpc: Fix ide-pmac sysfs entry It looks like the generic ide code now wants ide_init_hwif_ports() to set the parent struct device into the ide_hw structure (new field ?). Without this, the mac ide code can cause the ide probing code to explode in flames in sysfs registration due to what looks like a stale pointer in there (happens when removing/re-inserting one of the hotswap media bays on some laptops). Signed-off-by: Benjamin Herrenschmidt Cc: Bartlomiej Zolnierkiewicz Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/ide/ppc/pmac.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/ide/ppc/pmac.c b/drivers/ide/ppc/pmac.c index 78e30f80367129..ffca8b63ee79af 100644 --- a/drivers/ide/ppc/pmac.c +++ b/drivers/ide/ppc/pmac.c @@ -553,6 +553,8 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw, if (irq != NULL) *irq = pmac_ide[ix].irq; + + hw->dev = &pmac_ide[ix].mdev->ofdev.dev; } #define PMAC_IDE_REG(x) ((void __iomem *)(IDE_DATA_REG+(x))) -- cgit 1.2.3-korg From ea6c20891eb25e4884b852c040136f44cb173f3e Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Sat, 20 May 2006 14:59:55 -0700 Subject: [PATCH] Kdump maintainer info update Update MAINTAINERS file for info regarding kdump maintainership. Signed-off-by: Vivek Goyal Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 753584cf4e7e30..0bd4fec95c2028 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1536,6 +1536,16 @@ M: zippel@linux-m68k.org L: kbuild-devel@lists.sourceforge.net S: Maintained +KDUMP +P: Vivek Goyal +M: vgoyal@in.ibm.com +P: Haren Myneni +M: hbabu@us.ibm.com +L: fastboot@lists.osdl.org +L: linux-kernel@vger.kernel.org +W: http://lse.sourceforge.net/kdump/ +S: Maintained + KERNEL AUTOMOUNTER (AUTOFS) P: H. Peter Anvin M: hpa@zytor.com -- cgit 1.2.3-korg From 8c7b389e532e964f07057dac8a56c43465544759 Mon Sep 17 00:00:00 2001 From: Peter Staubach Date: Sat, 20 May 2006 14:59:56 -0700 Subject: [PATCH] NFS server subtree_check returns dubious value Address a problem found when a Linux NFS server uses the "subtree_check" export option. The "subtree_check" NFS export option was designed to prohibit a client from using a file handle for which it should not have permission. The algorithm used is to ensure that the entire path to the file being referenced is accessible to the user attempting to use the file handle. If some part of the path is not accessible, then the operation is aborted and the appropriate version of ESTALE is returned to the NFS client. The error, ESTALE, is unfortunate in that it causes NFS clients to make certain assumptions about the continued existence of the file. They assume that the file no longer exists and refuse to attempt to access it again. In this case, the file really does exist, but access was denied by the server for a particular user. A better error to return would be an EACCES sort of error. This would inform the client that the particular operation that it was attempting was not allowed, without the nasty side effects of the ESTALE error. Signed-off-by: Peter Staubach Acked-By: NeilBrown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/exportfs/expfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/exportfs/expfs.c b/fs/exportfs/expfs.c index b06b54f1bbbbda..4c39009350f3e5 100644 --- a/fs/exportfs/expfs.c +++ b/fs/exportfs/expfs.c @@ -102,7 +102,7 @@ find_exported_dentry(struct super_block *sb, void *obj, void *parent, if (acceptable(context, result)) return result; if (S_ISDIR(result->d_inode->i_mode)) { - /* there is no other dentry, so fail */ + err = -EACCES; goto err_result; } -- cgit 1.2.3-korg From 2adc7d47c4dbf684e69ee3980c158ff684dc170e Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Sat, 20 May 2006 14:59:57 -0700 Subject: [PATCH] md: Fix inverted test for 'repair' directive. We should be able to write 'repair' to /sys/block/mdX/md/sync_action, however due to and inverted test, that always given EINVAL. Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/md.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index d7316b829a6268..3ca3cfb03a7e28 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -2252,7 +2252,7 @@ action_store(mddev_t *mddev, const char *page, size_t len) } else { if (cmd_match(page, "check")) set_bit(MD_RECOVERY_CHECK, &mddev->recovery); - else if (cmd_match(page, "repair")) + else if (!cmd_match(page, "repair")) return -EINVAL; set_bit(MD_RECOVERY_REQUESTED, &mddev->recovery); set_bit(MD_RECOVERY_SYNC, &mddev->recovery); -- cgit 1.2.3-korg From 9ccfc29c671c9d0a83c2a114d4bc5f85f3cd749d Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Sat, 20 May 2006 14:59:58 -0700 Subject: [PATCH] nfsd: sign conversion obscuring errors in nfsd_set_posix_acl() Assigning the result of posix_acl_to_xattr() to an unsigned data type (size/size_t) obscures possible errors. Coverity CID: 1206. Signed-off-by: Florin Malita Acked-by: NeilBrown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/vfs.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 6aa92d0e68764a..1d65f13f458c40 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c @@ -1922,11 +1922,10 @@ nfsd_set_posix_acl(struct svc_fh *fhp, int type, struct posix_acl *acl) value = kmalloc(size, GFP_KERNEL); if (!value) return -ENOMEM; - size = posix_acl_to_xattr(acl, value, size); - if (size < 0) { - error = size; + error = posix_acl_to_xattr(acl, value, size); + if (error < 0) goto getout; - } + size = error; } else size = 0; -- cgit 1.2.3-korg From 48d705522da4fa04bb0169a7ca3c9ab92e28b613 Mon Sep 17 00:00:00 2001 From: "Micon, David" Date: Sat, 20 May 2006 14:59:59 -0700 Subject: [PATCH] HID read busywait fix Make a read of a HID device block until data is available. Without it, the read goes into a busy-wait loop until data is available. Cc: Greg KH Acked-by: Vojtech Pavlik Cc: Dmitry Torokhov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/usb/input/hiddev.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/input/hiddev.c b/drivers/usb/input/hiddev.c index 6dd66669617874..c4670e1d46545f 100644 --- a/drivers/usb/input/hiddev.c +++ b/drivers/usb/input/hiddev.c @@ -317,6 +317,7 @@ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t coun } schedule(); + set_current_state(TASK_INTERRUPTIBLE); } set_current_state(TASK_RUNNING); -- cgit 1.2.3-korg From df88912a2165f56a7402db80126cf8ea075221fe Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 20 May 2006 15:00:01 -0700 Subject: [PATCH] binfmt_flat: don't check for EMFILE Bernd Schmidt points out that binfmt_flat is now leaving the exec file open while the application runs. This offsets all the application's fd numbers. We should have closed the file within exec(), not at exit()-time. But there doesn't seem to be a lot of point in doing all this just to avoid going over RLIMIT_NOFILE by one fd for a few microseconds. So take the EMFILE checking out again. This will cause binfmt_flat to again fail LTP's exec-should-return-EMFILE-when-fdtable-is-full test. That test appears to be wrong anyway - Open Group specs say nothing about exec() returning EMFILE. Cc: Bernd Schmidt Cc: Greg Ungerer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/binfmt_flat.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 69f44dcdb0b4c9..b1c902e319c13d 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c @@ -428,7 +428,6 @@ static int load_flat_file(struct linux_binprm * bprm, loff_t fpos; unsigned long start_code, end_code; int ret; - int exec_fileno; hdr = ((struct flat_hdr *) bprm->buf); /* exec-header */ inode = bprm->file->f_dentry->d_inode; @@ -502,21 +501,12 @@ static int load_flat_file(struct linux_binprm * bprm, goto err; } - /* check file descriptor */ - exec_fileno = get_unused_fd(); - if (exec_fileno < 0) { - ret = -EMFILE; - goto err; - } - get_file(bprm->file); - fd_install(exec_fileno, bprm->file); - /* Flush all traces of the currently running executable */ if (id == 0) { result = flush_old_exec(bprm); if (result) { ret = result; - goto err_close; + goto err; } /* OK, This is the point of no return */ @@ -548,7 +538,7 @@ static int load_flat_file(struct linux_binprm * bprm, textpos = (unsigned long) -ENOMEM; printk("Unable to mmap process text, errno %d\n", (int)-textpos); ret = textpos; - goto err_close; + goto err; } down_write(¤t->mm->mmap_sem); @@ -564,7 +554,7 @@ static int load_flat_file(struct linux_binprm * bprm, (int)-datapos); do_munmap(current->mm, textpos, text_len); ret = realdatastart; - goto err_close; + goto err; } datapos = realdatastart + MAX_SHARED_LIBS * sizeof(unsigned long); @@ -587,7 +577,7 @@ static int load_flat_file(struct linux_binprm * bprm, do_munmap(current->mm, textpos, text_len); do_munmap(current->mm, realdatastart, data_len + extra); ret = result; - goto err_close; + goto err; } reloc = (unsigned long *) (datapos+(ntohl(hdr->reloc_start)-text_len)); @@ -606,7 +596,7 @@ static int load_flat_file(struct linux_binprm * bprm, printk("Unable to allocate RAM for process text/data, errno %d\n", (int)-textpos); ret = textpos; - goto err_close; + goto err; } realdatastart = textpos + ntohl(hdr->data_start); @@ -652,7 +642,7 @@ static int load_flat_file(struct linux_binprm * bprm, do_munmap(current->mm, textpos, text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long)); ret = result; - goto err_close; + goto err; } } @@ -717,7 +707,7 @@ static int load_flat_file(struct linux_binprm * bprm, addr = calc_reloc(*rp, libinfo, id, 0); if (addr == RELOC_FAILED) { ret = -ENOEXEC; - goto err_close; + goto err; } *rp = addr; } @@ -747,7 +737,7 @@ static int load_flat_file(struct linux_binprm * bprm, rp = (unsigned long *) calc_reloc(addr, libinfo, id, 1); if (rp == (unsigned long *)RELOC_FAILED) { ret = -ENOEXEC; - goto err_close; + goto err; } /* Get the pointer's value. */ @@ -762,7 +752,7 @@ static int load_flat_file(struct linux_binprm * bprm, addr = calc_reloc(addr, libinfo, id, 0); if (addr == RELOC_FAILED) { ret = -ENOEXEC; - goto err_close; + goto err; } /* Write back the relocated pointer. */ @@ -783,8 +773,6 @@ static int load_flat_file(struct linux_binprm * bprm, stack_len); return 0; -err_close: - sys_close(exec_fileno); err: return ret; } -- cgit 1.2.3-korg From d4e9dc63dca91cd89086b5a686d7f7635c8319e5 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Sat, 20 May 2006 15:00:02 -0700 Subject: [PATCH] selinux: endian fix Signed-off-by: Alexey Dobriyan Cc: Stephen Smalley Acked-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index d987048d3f3305..21dad415b8960d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -3231,7 +3231,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) goto out; /* Handle mapped IPv4 packets arriving via IPv6 sockets */ - if (family == PF_INET6 && skb->protocol == ntohs(ETH_P_IP)) + if (family == PF_INET6 && skb->protocol == htons(ETH_P_IP)) family = PF_INET; read_lock_bh(&sk->sk_callback_lock); -- cgit 1.2.3-korg From ad8f5797302ed389476debcc51b4630f387618b9 Mon Sep 17 00:00:00 2001 From: KAMEZAWA Hiroyuki Date: Sat, 20 May 2006 15:00:03 -0700 Subject: [PATCH] build fix: CONFIG_MEMORY_HOTPLUG=y on i386 typo in #ifdefs. Fixes http://bugme.osdl.org/show_bug.cgi?id=6538 Signed-off-by: KAMEZAWA Hiroyuki Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/mm/init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/i386/mm/init.c b/arch/i386/mm/init.c index ae6534ad816113..3df1371d4520bb 100644 --- a/arch/i386/mm/init.c +++ b/arch/i386/mm/init.c @@ -651,7 +651,7 @@ void __init mem_init(void) * Specifically, in the case of x86, we will always add * memory to the highmem for now. */ -#ifdef CONFIG_HOTPLUG_MEMORY +#ifdef CONFIG_MEMORY_HOTPLUG #ifndef CONFIG_NEED_MULTIPLE_NODES int add_memory(u64 start, u64 size) { -- cgit 1.2.3-korg From 12783b002db1f02c29353c8f698a85514420b9f4 Mon Sep 17 00:00:00 2001 From: Mike Kravetz Date: Sat, 20 May 2006 15:00:05 -0700 Subject: [PATCH] SPARSEMEM incorrectly calculates section number A bad calculation/loop in __section_nr() could result in incorrect section information being put into sysfs memory entries. This primarily impacts memory add operations as the sysfs information is used while onlining new memory. Fix suggested by Dave Hansen. Note that the bug may not be obvious from the patch. It actually occurs in the function's return statement: return (root_nr * SECTIONS_PER_ROOT) + (ms - root); In the existing code, root_nr has already been multiplied by SECTIONS_PER_ROOT. Signed-off-by: Mike Kravetz Cc: Dave Hansen Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/sparse.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/mm/sparse.c b/mm/sparse.c index c5e89eb9ac8ff1..100040c0dfb6c8 100644 --- a/mm/sparse.c +++ b/mm/sparse.c @@ -87,11 +87,8 @@ int __section_nr(struct mem_section* ms) unsigned long root_nr; struct mem_section* root; - for (root_nr = 0; - root_nr < NR_MEM_SECTIONS; - root_nr += SECTIONS_PER_ROOT) { - root = __nr_to_section(root_nr); - + for (root_nr = 0; root_nr < NR_SECTION_ROOTS; root_nr++) { + root = __nr_to_section(root_nr * SECTIONS_PER_ROOT); if (!root) continue; -- cgit 1.2.3-korg From 66055a4e7334b05354c835123ff621c5f700e56a Mon Sep 17 00:00:00 2001 From: Amy Griffis Date: Sat, 20 May 2006 15:00:06 -0700 Subject: [PATCH] fix race in inotify_release While doing some inotify stress testing, I hit the following race. In inotify_release(), it's possible for a watch to be removed from the lists in between dropping dev->mutex and taking inode->inotify_mutex. The reference we hold prevents the watch from being freed, but not from being removed. Checking the dev's idr mapping will prevent a double list_del of the same watch. Signed-off-by: Amy Griffis Acked-by: John McCutchan Cc: Robert Love Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/inotify.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fs/inotify.c b/fs/inotify.c index 1f50302849c53c..7d57253365274e 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -848,7 +848,11 @@ static int inotify_release(struct inode *ignored, struct file *file) inode = watch->inode; mutex_lock(&inode->inotify_mutex); mutex_lock(&dev->mutex); - remove_watch_no_event(watch, dev); + + /* make sure we didn't race with another list removal */ + if (likely(idr_find(&dev->idr, watch->wd))) + remove_watch_no_event(watch, dev); + mutex_unlock(&dev->mutex); mutex_unlock(&inode->inotify_mutex); put_inotify_watch(watch); -- cgit 1.2.3-korg From d66fd908acc8ba88541ecc570d89b0243f947c5e Mon Sep 17 00:00:00 2001 From: Amy Griffis Date: Sat, 20 May 2006 15:00:07 -0700 Subject: [PATCH] fix NULL dereference in inotify_ignore Don't reassign to watch. If idr_find() returns NULL, then put_inotify_watch() will choke. Signed-off-by: Amy Griffis Cc: John McCutchan Cc: Robert Love Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/inotify.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/fs/inotify.c b/fs/inotify.c index 7d57253365274e..732ec4bd577450 100644 --- a/fs/inotify.c +++ b/fs/inotify.c @@ -894,8 +894,7 @@ static int inotify_ignore(struct inotify_device *dev, s32 wd) mutex_lock(&dev->mutex); /* make sure that we did not race */ - watch = idr_find(&dev->idr, wd); - if (likely(watch)) + if (likely(idr_find(&dev->idr, wd) == watch)) remove_watch(watch, dev); mutex_unlock(&dev->mutex); -- cgit 1.2.3-korg From 593ee20766921fec643194dff829e17f30552220 Mon Sep 17 00:00:00 2001 From: Kristen Accardi Date: Sat, 20 May 2006 15:00:08 -0700 Subject: [PATCH] pci: correctly allocate return buffers for osc calls The OSC set and query functions do not allocate enough space for return values, and set the output buffer length to a false, too large value. This causes the acpi-ca code to assume that the output buffer is larger than it actually is, and overwrite memory when copying acpi return buffers into this caller provided buffer. In some cases this can cause kernel oops if the memory that is overwritten is a pointer. This patch will change these calls to use a dynamically allocated output buffer, thus allowing the acpi-ca code to decide how much space is needed. Signed-off-by: Kristen Carlson Accardi Cc: "Brown, Len" Cc: "Yu, Luming" Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pci/pci-acpi.c | 60 +++++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 6917c6cb091287..c2ecae5ff0c176 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c @@ -33,13 +33,10 @@ acpi_query_osc ( acpi_status status; struct acpi_object_list input; union acpi_object in_params[4]; - struct acpi_buffer output; - union acpi_object out_obj; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *out_obj; u32 osc_dw0; - /* Setting up output buffer */ - output.length = sizeof(out_obj) + 3*sizeof(u32); - output.pointer = &out_obj; /* Setting up input parameters */ input.count = 4; @@ -61,12 +58,15 @@ acpi_query_osc ( "Evaluate _OSC Set fails. Status = 0x%04x\n", status); return status; } - if (out_obj.type != ACPI_TYPE_BUFFER) { + out_obj = output.pointer; + + if (out_obj->type != ACPI_TYPE_BUFFER) { printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n"); - return AE_TYPE; + status = AE_TYPE; + goto query_osc_out; } - osc_dw0 = *((u32 *) out_obj.buffer.pointer); + osc_dw0 = *((u32 *) out_obj->buffer.pointer); if (osc_dw0) { if (osc_dw0 & OSC_REQUEST_ERROR) printk(KERN_DEBUG "_OSC request fails\n"); @@ -76,15 +76,21 @@ acpi_query_osc ( printk(KERN_DEBUG "_OSC invalid revision\n"); if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { /* Update Global Control Set */ - global_ctrlsets = *((u32 *)(out_obj.buffer.pointer+8)); - return AE_OK; + global_ctrlsets = *((u32 *)(out_obj->buffer.pointer+8)); + status = AE_OK; + goto query_osc_out; } - return AE_ERROR; + status = AE_ERROR; + goto query_osc_out; } /* Update Global Control Set */ - global_ctrlsets = *((u32 *)(out_obj.buffer.pointer + 8)); - return AE_OK; + global_ctrlsets = *((u32 *)(out_obj->buffer.pointer + 8)); + status = AE_OK; + +query_osc_out: + kfree(output.pointer); + return status; } @@ -96,14 +102,10 @@ acpi_run_osc ( acpi_status status; struct acpi_object_list input; union acpi_object in_params[4]; - struct acpi_buffer output; - union acpi_object out_obj; + struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL}; + union acpi_object *out_obj; u32 osc_dw0; - /* Setting up output buffer */ - output.length = sizeof(out_obj) + 3*sizeof(u32); - output.pointer = &out_obj; - /* Setting up input parameters */ input.count = 4; input.pointer = in_params; @@ -124,12 +126,14 @@ acpi_run_osc ( "Evaluate _OSC Set fails. Status = 0x%04x\n", status); return status; } - if (out_obj.type != ACPI_TYPE_BUFFER) { + out_obj = output.pointer; + if (out_obj->type != ACPI_TYPE_BUFFER) { printk(KERN_DEBUG "Evaluate _OSC returns wrong type\n"); - return AE_TYPE; + status = AE_TYPE; + goto run_osc_out; } - osc_dw0 = *((u32 *) out_obj.buffer.pointer); + osc_dw0 = *((u32 *) out_obj->buffer.pointer); if (osc_dw0) { if (osc_dw0 & OSC_REQUEST_ERROR) printk(KERN_DEBUG "_OSC request fails\n"); @@ -139,11 +143,17 @@ acpi_run_osc ( printk(KERN_DEBUG "_OSC invalid revision\n"); if (osc_dw0 & OSC_CAPABILITIES_MASK_ERROR) { printk(KERN_DEBUG "_OSC FW not grant req. control\n"); - return AE_SUPPORT; + status = AE_SUPPORT; + goto run_osc_out; } - return AE_ERROR; + status = AE_ERROR; + goto run_osc_out; } - return AE_OK; + status = AE_OK; + +run_osc_out: + kfree(output.pointer); + return status; } /** -- cgit 1.2.3-korg From bdd804f478a0cc74bf7db8e9f9d5fd379d1b31ca Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Sat, 20 May 2006 15:00:09 -0700 Subject: [PATCH] Cpuset: might sleep checking zones allowed fix Fix a couple of infrequently encountered 'sleeping function called from invalid context' in the cpuset hooks in __alloc_pages. Could sleep while interrupts disabled. The routine cpuset_zone_allowed() is called by code in mm/page_alloc.c __alloc_pages() to determine if a zone is allowed in the current tasks cpuset. This routine can sleep, for certain GFP_KERNEL allocations, if the zone is on a memory node not allowed in the current cpuset, but might be allowed in a parent cpuset. But we can't sleep in __alloc_pages() if in interrupt, nor if called for a GFP_ATOMIC request (__GFP_WAIT not set in gfp_flags). The rule was intended to be: Don't call cpuset_zone_allowed() if you can't sleep, unless you pass in the __GFP_HARDWALL flag set in gfp_flag, which disables the code that might scan up ancestor cpusets and sleep. This rule was being violated in a couple of places, due to a bogus change made (by myself, pj) to __alloc_pages() as part of the November 2005 effort to cleanup its logic, and also due to a later fix to constrain which swap daemons were awoken. The bogus change can be seen at: http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-11/4691.html [PATCH 01/05] mm fix __alloc_pages cpuset ALLOC_* flags This was first noticed on a tight memory system, in code that was disabling interrupts and doing allocation requests with __GFP_WAIT not set, which resulted in __might_sleep() writing complaints to the log "Debug: sleeping function called ...", when the code in cpuset_zone_allowed() tried to take the callback_sem cpuset semaphore. We haven't seen a system hang on this 'might_sleep' yet, but we are at decent risk of seeing it fairly soon, especially since the additional cpuset_zone_allowed() check was added, conditioning wakeup_kswapd(), in March 2006. Special thanks to Dave Chinner, for figuring this out, and a tip of the hat to Nick Piggin who warned me of this back in Nov 2005, before I was ready to listen. Signed-off-by: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_alloc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 813b4ec1298a23..bb3416932ab03d 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -951,7 +951,7 @@ restart: goto got_pg; do { - if (cpuset_zone_allowed(*z, gfp_mask)) + if (cpuset_zone_allowed(*z, gfp_mask|__GFP_HARDWALL)) wakeup_kswapd(*z, order); } while (*(++z)); @@ -970,7 +970,8 @@ restart: alloc_flags |= ALLOC_HARDER; if (gfp_mask & __GFP_HIGH) alloc_flags |= ALLOC_HIGH; - alloc_flags |= ALLOC_CPUSET; + if (wait) + alloc_flags |= ALLOC_CPUSET; /* * Go through the zonelist again. Let __GFP_HIGH and allocations -- cgit 1.2.3-korg From 36be57ffe39e03aab9fbe857f70c7a6a15bd9e08 Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Sat, 20 May 2006 15:00:10 -0700 Subject: [PATCH] cpuset: update cpuset_zones_allowed comment Update the kernel/cpuset.c:cpuset_zone_allowed() comment. The rule for when mm/page_alloc.c should call cpuset_zone_allowed() was intended to be: Don't call cpuset_zone_allowed() if you can't sleep, unless you pass in the __GFP_HARDWALL flag set in gfp_flag, which disables the code that might scan up ancestor cpusets and sleep. The explanation of this rule in the comment above cpuset_zone_allowed() was stale, as a result of a restructuring of some __alloc_pages() code in November 2005. Rewrite that comment ... Signed-off-by: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/cpuset.c | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 72248d1b9e3f7a..57fd88237afc94 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2231,19 +2231,25 @@ static const struct cpuset *nearest_exclusive_ancestor(const struct cpuset *cs) * So only GFP_KERNEL allocations, if all nodes in the cpuset are * short of memory, might require taking the callback_mutex mutex. * - * The first loop over the zonelist in mm/page_alloc.c:__alloc_pages() - * calls here with __GFP_HARDWALL always set in gfp_mask, enforcing - * hardwall cpusets - no allocation on a node outside the cpuset is - * allowed (unless in interrupt, of course). - * - * The second loop doesn't even call here for GFP_ATOMIC requests - * (if the __alloc_pages() local variable 'wait' is set). That check - * and the checks below have the combined affect in the second loop of - * the __alloc_pages() routine that: + * The first call here from mm/page_alloc:get_page_from_freelist() + * has __GFP_HARDWALL set in gfp_mask, enforcing hardwall cpusets, so + * no allocation on a node outside the cpuset is allowed (unless in + * interrupt, of course). + * + * The second pass through get_page_from_freelist() doesn't even call + * here for GFP_ATOMIC calls. For those calls, the __alloc_pages() + * variable 'wait' is not set, and the bit ALLOC_CPUSET is not set + * in alloc_flags. That logic and the checks below have the combined + * affect that: * in_interrupt - any node ok (current task context irrelevant) * GFP_ATOMIC - any node ok * GFP_KERNEL - any node in enclosing mem_exclusive cpuset ok * GFP_USER - only nodes in current tasks mems allowed ok. + * + * Rule: + * Don't call cpuset_zone_allowed() if you can't sleep, unless you + * pass in the __GFP_HARDWALL flag set in gfp_flag, which disables + * the code that might scan up ancestor cpusets and sleep. **/ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) -- cgit 1.2.3-korg From 92d1dbd27417c54c23aac6a84c285e256f6118b6 Mon Sep 17 00:00:00 2001 From: Paul Jackson Date: Sat, 20 May 2006 15:00:11 -0700 Subject: [PATCH] cpuset: might_sleep_if check in cpuset_zones_allowed It's too easy to incorrectly call cpuset_zone_allowed() in an atomic context without __GFP_HARDWALL set, and when done, it is not noticed until a tight memory situation forces allocations to be tried outside the current cpuset. Add a 'might_sleep_if()' check, to catch this earlier on, instead of waiting for a similar check in the mutex_lock() code, which is only rarely invoked. Signed-off-by: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/cpuset.c | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 57fd88237afc94..ab81fdd4572bb4 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -2261,6 +2261,7 @@ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) if (in_interrupt()) return 1; node = z->zone_pgdat->node_id; + might_sleep_if(!(gfp_mask & __GFP_HARDWALL)); if (node_isset(node, current->mems_allowed)) return 1; if (gfp_mask & __GFP_HARDWALL) /* If hardwall request, stop here */ -- cgit 1.2.3-korg From a6a61c5494145c904bead0cceadd94080bd3a784 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Sat, 20 May 2006 15:00:12 -0700 Subject: [PATCH] Overrun in isdn_tty.c This fixes coverity bug id #1237. After the while loop, it is possible for i == ISDN_LMSNLEN. If this happens the terminating '\0' is written after the end of the array. Signed-off-by: Eric Sesterhenn Cc: Karsten Keil Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/isdn/i4l/isdn_tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index 3585fb1f334460..2ac90242d26371 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c @@ -2880,7 +2880,7 @@ isdn_tty_cmd_ATand(char **p, modem_info * info) p[0]++; i = 0; while (*p[0] && (strchr("0123456789,-*[]?;", *p[0])) && - (i < ISDN_LMSNLEN)) + (i < ISDN_LMSNLEN - 1)) m->lmsn[i++] = *p[0]++; m->lmsn[i] = '\0'; break; -- cgit 1.2.3-korg From c9ee133b914879e02796bccd840f75f185cf1bb7 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Sat, 20 May 2006 15:00:12 -0700 Subject: [PATCH] Clarify maintainers and include linux-security info Signed-off-by: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 0bd4fec95c2028..89c066be54896f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -40,11 +40,20 @@ trivial patch so apply some common sense. PLEASE document known bugs. If it doesn't work for everything or does something very odd once a month document it. + PLEASE remember that submissions must be made under the terms + of the OSDL certificate of contribution + (http://www.osdl.org/newsroom/press_releases/2004/2004_05_24_dco.html) + and should include a Signed-off-by: line. + 6. Make sure you have the right to send any changes you make. If you do changes at work you may find your employer owns the patch not you. -7. Happy hacking. +7. When sending security related changes or reports to a maintainer + please Cc: security@kernel.org, especially if the maintainer + does not respond. + +8. Happy hacking. ----------------------------------- -- cgit 1.2.3-korg From ae0718f8e3fcfa3e4863f63db90d24bbec6b14a2 Mon Sep 17 00:00:00 2001 From: Theodore Tso Date: Sat, 20 May 2006 15:00:13 -0700 Subject: [PATCH] Update ext2/ext3/jbd MAINTAINERS entries Signed-off-by: "Theodore Ts'o" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 89c066be54896f..bd10b2af2223f0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -978,7 +978,7 @@ S: Maintained EXT3 FILE SYSTEM P: Stephen Tweedie, Andrew Morton M: sct@redhat.com, akpm@osdl.org, adilger@clusterfs.com -L: ext3-users@redhat.com +L: ext2-devel@lists.sourceforge.net S: Maintained F71805F HARDWARE MONITORING DRIVER @@ -1539,6 +1539,12 @@ W: http://jfs.sourceforge.net/ T: git kernel.org:/pub/scm/linux/kernel/git/shaggy/jfs-2.6.git S: Supported +JOURNALLING LAYER FOR BLOCK DEVICS (JBD) +P: Stephen Tweedie, Andrew Morton +M: sct@redhat.com, akpm@osdl.org +L: ext2-devel@lists.sourceforge.net +S: Maintained + KCONFIG P: Roman Zippel M: zippel@linux-m68k.org -- cgit 1.2.3-korg From ba1a051319dc2bec9f43b7cef11c6e5270107fd6 Mon Sep 17 00:00:00 2001 From: dmitry pervushin Date: Sat, 20 May 2006 15:00:14 -0700 Subject: [PATCH] minor SPI doc fix Because several developers asked me about referenced but missing spi_add_master(), I think that this patch should be applied ... it corrects comments so they refer to spi_register_master() instead. Signed-off-by: dmitry pervushin Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/spi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7a3f733051e9ce..1cea4a6799fe66 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -338,18 +338,18 @@ static struct class spi_master_class = { * spi_alloc_master - allocate SPI master controller * @dev: the controller, possibly using the platform_bus * @size: how much driver-private data to preallocate; the pointer to this - * memory is in the class_data field of the returned class_device, + * memory is in the class_data field of the returned class_device, * accessible with spi_master_get_devdata(). * * This call is used only by SPI master controller drivers, which are the * only ones directly touching chip registers. It's how they allocate - * an spi_master structure, prior to calling spi_add_master(). + * an spi_master structure, prior to calling spi_register_master(). * * This must be called from context that can sleep. It returns the SPI * master structure on success, else NULL. * * The caller is responsible for assigning the bus number and initializing - * the master's methods before calling spi_add_master(); and (after errors + * the master's methods before calling spi_register_master(); and (after errors * adding the device) calling spi_master_put() to prevent a memory leak. */ struct spi_master * __init_or_module -- cgit 1.2.3-korg From ccf06998fe179ae2cc9517ed1d75433dc0b5032d Mon Sep 17 00:00:00 2001 From: Kumar Gala Date: Sat, 20 May 2006 15:00:15 -0700 Subject: [PATCH] spi: add spi master driver for Freescale MPC83xx SPI controller This driver supports the SPI controller on the MPC83xx SoC devices from Freescale. Note, this driver supports only the simple shift register SPI controller and not the descriptor based CPM or QUICCEngine SPI controller. Signed-off-by: Kumar Gala Signed-off-by: David Brownell Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/Kconfig | 12 ++ drivers/spi/Makefile | 1 + drivers/spi/spi_mpc83xx.c | 483 ++++++++++++++++++++++++++++++++++++++++++++ include/linux/fsl_devices.h | 11 + 4 files changed, 507 insertions(+) create mode 100644 drivers/spi/spi_mpc83xx.c diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 9ce1d01469b19d..3867c6ef24f34d 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -75,6 +75,18 @@ config SPI_BUTTERFLY inexpensive battery powered microcontroller evaluation board. This same cable can be used to flash new firmware. +config SPI_MPC83xx + tristate "Freescale MPC83xx SPI controller" + depends on SPI_MASTER && PPC_83xx && EXPERIMENTAL + select SPI_BITBANG + help + This enables using the Freescale MPC83xx SPI controller in master + mode. + + Note, this driver uniquely supports the SPI controller on the MPC83xx + family of PowerPC processors. The MPC83xx uses a simple set of shift + registers for data (opposed to the CPM based descriptor model). + config SPI_PXA2XX tristate "PXA2xx SSP SPI master" depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 1bca5f95de251d..5a410caa03c73f 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -14,6 +14,7 @@ obj-$(CONFIG_SPI_MASTER) += spi.o obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o +obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o # ... add above this line ... # SPI protocol drivers (device/link on bus) diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c new file mode 100644 index 00000000000000..5d92a7e5cb4165 --- /dev/null +++ b/drivers/spi/spi_mpc83xx.c @@ -0,0 +1,483 @@ +/* + * MPC83xx SPI controller driver. + * + * Maintainer: Kumar Gala + * + * Copyright (C) 2006 Polycom, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* SPI Controller registers */ +struct mpc83xx_spi_reg { + u8 res1[0x20]; + __be32 mode; + __be32 event; + __be32 mask; + __be32 command; + __be32 transmit; + __be32 receive; +}; + +/* SPI Controller mode register definitions */ +#define SPMODE_CI_INACTIVEHIGH (1 << 29) +#define SPMODE_CP_BEGIN_EDGECLK (1 << 28) +#define SPMODE_DIV16 (1 << 27) +#define SPMODE_REV (1 << 26) +#define SPMODE_MS (1 << 25) +#define SPMODE_ENABLE (1 << 24) +#define SPMODE_LEN(x) ((x) << 20) +#define SPMODE_PM(x) ((x) << 16) + +/* + * Default for SPI Mode: + * SPI MODE 0 (inactive low, phase middle, MSB, 8-bit length, slow clk + */ +#define SPMODE_INIT_VAL (SPMODE_CI_INACTIVEHIGH | SPMODE_DIV16 | SPMODE_REV | \ + SPMODE_MS | SPMODE_LEN(7) | SPMODE_PM(0xf)) + +/* SPIE register values */ +#define SPIE_NE 0x00000200 /* Not empty */ +#define SPIE_NF 0x00000100 /* Not full */ + +/* SPIM register values */ +#define SPIM_NE 0x00000200 /* Not empty */ +#define SPIM_NF 0x00000100 /* Not full */ + +/* SPI Controller driver's private data. */ +struct mpc83xx_spi { + /* bitbang has to be first */ + struct spi_bitbang bitbang; + struct completion done; + + struct mpc83xx_spi_reg __iomem *base; + + /* rx & tx bufs from the spi_transfer */ + const void *tx; + void *rx; + + /* functions to deal with different sized buffers */ + void (*get_rx) (u32 rx_data, struct mpc83xx_spi *); + u32(*get_tx) (struct mpc83xx_spi *); + + unsigned int count; + u32 irq; + + unsigned nsecs; /* (clock cycle time)/2 */ + + u32 sysclk; + void (*activate_cs) (u8 cs, u8 polarity); + void (*deactivate_cs) (u8 cs, u8 polarity); +}; + +static inline void mpc83xx_spi_write_reg(__be32 __iomem * reg, u32 val) +{ + out_be32(reg, val); +} + +static inline u32 mpc83xx_spi_read_reg(__be32 __iomem * reg) +{ + return in_be32(reg); +} + +#define MPC83XX_SPI_RX_BUF(type) \ +void mpc83xx_spi_rx_buf_##type(u32 data, struct mpc83xx_spi *mpc83xx_spi) \ +{ \ + type * rx = mpc83xx_spi->rx; \ + *rx++ = (type)data; \ + mpc83xx_spi->rx = rx; \ +} + +#define MPC83XX_SPI_TX_BUF(type) \ +u32 mpc83xx_spi_tx_buf_##type(struct mpc83xx_spi *mpc83xx_spi) \ +{ \ + u32 data; \ + const type * tx = mpc83xx_spi->tx; \ + data = *tx++; \ + mpc83xx_spi->tx = tx; \ + return data; \ +} + +MPC83XX_SPI_RX_BUF(u8) +MPC83XX_SPI_RX_BUF(u16) +MPC83XX_SPI_RX_BUF(u32) +MPC83XX_SPI_TX_BUF(u8) +MPC83XX_SPI_TX_BUF(u16) +MPC83XX_SPI_TX_BUF(u32) + +static void mpc83xx_spi_chipselect(struct spi_device *spi, int value) +{ + struct mpc83xx_spi *mpc83xx_spi; + u8 pol = spi->mode & SPI_CS_HIGH ? 1 : 0; + + mpc83xx_spi = spi_master_get_devdata(spi->master); + + if (value == BITBANG_CS_INACTIVE) { + if (mpc83xx_spi->deactivate_cs) + mpc83xx_spi->deactivate_cs(spi->chip_select, pol); + } + + if (value == BITBANG_CS_ACTIVE) { + u32 regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); + u32 len = spi->bits_per_word; + if (len == 32) + len = 0; + else + len = len - 1; + + /* mask out bits we are going to set */ + regval &= ~0x38ff0000; + + if (spi->mode & SPI_CPHA) + regval |= SPMODE_CP_BEGIN_EDGECLK; + if (spi->mode & SPI_CPOL) + regval |= SPMODE_CI_INACTIVEHIGH; + + regval |= SPMODE_LEN(len); + + if ((mpc83xx_spi->sysclk / spi->max_speed_hz) >= 64) { + u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 64); + regval |= SPMODE_PM(pm) | SPMODE_DIV16; + } else { + u8 pm = mpc83xx_spi->sysclk / (spi->max_speed_hz * 4); + regval |= SPMODE_PM(pm); + } + + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); + if (mpc83xx_spi->activate_cs) + mpc83xx_spi->activate_cs(spi->chip_select, pol); + } +} + +static +int mpc83xx_spi_setup_transfer(struct spi_device *spi, struct spi_transfer *t) +{ + struct mpc83xx_spi *mpc83xx_spi; + u32 regval; + u8 bits_per_word; + u32 hz; + + mpc83xx_spi = spi_master_get_devdata(spi->master); + + if (t) { + bits_per_word = t->bits_per_word; + hz = t->speed_hz; + } else { + bits_per_word = 0; + hz = 0; + } + + /* spi_transfer level calls that work per-word */ + if (!bits_per_word) + bits_per_word = spi->bits_per_word; + + /* Make sure its a bit width we support [4..16, 32] */ + if ((bits_per_word < 4) + || ((bits_per_word > 16) && (bits_per_word != 32))) + return -EINVAL; + + if (bits_per_word <= 8) { + mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; + mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; + } else if (bits_per_word <= 16) { + mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u16; + mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u16; + } else if (bits_per_word <= 32) { + mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u32; + mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u32; + } else + return -EINVAL; + + /* nsecs = (clock period)/2 */ + if (!hz) + hz = spi->max_speed_hz; + mpc83xx_spi->nsecs = (1000000000 / 2) / hz; + if (mpc83xx_spi->nsecs > MAX_UDELAY_MS * 1000) + return -EINVAL; + + if (bits_per_word == 32) + bits_per_word = 0; + else + bits_per_word = bits_per_word - 1; + + regval = mpc83xx_spi_read_reg(&mpc83xx_spi->base->mode); + + /* Mask out bits_per_wordgth */ + regval &= 0xff0fffff; + regval |= SPMODE_LEN(bits_per_word); + + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); + + return 0; +} + +static int mpc83xx_spi_setup(struct spi_device *spi) +{ + struct spi_bitbang *bitbang; + struct mpc83xx_spi *mpc83xx_spi; + int retval; + + if (!spi->max_speed_hz) + return -EINVAL; + + bitbang = spi_master_get_devdata(spi->master); + mpc83xx_spi = spi_master_get_devdata(spi->master); + + if (!spi->bits_per_word) + spi->bits_per_word = 8; + + retval = mpc83xx_spi_setup_transfer(spi, NULL); + if (retval < 0) + return retval; + + dev_dbg(&spi->dev, "%s, mode %d, %u bits/w, %u nsec\n", + __FUNCTION__, spi->mode & (SPI_CPOL | SPI_CPHA), + spi->bits_per_word, 2 * mpc83xx_spi->nsecs); + + /* NOTE we _need_ to call chipselect() early, ideally with adapter + * setup, unless the hardware defaults cooperate to avoid confusion + * between normal (active low) and inverted chipselects. + */ + + /* deselect chip (low or high) */ + spin_lock(&bitbang->lock); + if (!bitbang->busy) { + bitbang->chipselect(spi, BITBANG_CS_INACTIVE); + ndelay(mpc83xx_spi->nsecs); + } + spin_unlock(&bitbang->lock); + + return 0; +} + +static int mpc83xx_spi_bufs(struct spi_device *spi, struct spi_transfer *t) +{ + struct mpc83xx_spi *mpc83xx_spi; + u32 word; + + mpc83xx_spi = spi_master_get_devdata(spi->master); + + mpc83xx_spi->tx = t->tx_buf; + mpc83xx_spi->rx = t->rx_buf; + mpc83xx_spi->count = t->len; + INIT_COMPLETION(mpc83xx_spi->done); + + /* enable rx ints */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, SPIM_NE); + + /* transmit word */ + word = mpc83xx_spi->get_tx(mpc83xx_spi); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit, word); + + wait_for_completion(&mpc83xx_spi->done); + + /* disable rx ints */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0); + + return t->len - mpc83xx_spi->count; +} + +irqreturn_t mpc83xx_spi_irq(s32 irq, void *context_data, + struct pt_regs * ptregs) +{ + struct mpc83xx_spi *mpc83xx_spi = context_data; + u32 event; + irqreturn_t ret = IRQ_NONE; + + /* Get interrupt events(tx/rx) */ + event = mpc83xx_spi_read_reg(&mpc83xx_spi->base->event); + + /* We need handle RX first */ + if (event & SPIE_NE) { + u32 rx_data = mpc83xx_spi_read_reg(&mpc83xx_spi->base->receive); + + if (mpc83xx_spi->rx) + mpc83xx_spi->get_rx(rx_data, mpc83xx_spi); + + ret = IRQ_HANDLED; + } + + if ((event & SPIE_NF) == 0) + /* spin until TX is done */ + while (((event = + mpc83xx_spi_read_reg(&mpc83xx_spi->base->event)) & + SPIE_NF) == 0) + cpu_relax(); + + mpc83xx_spi->count -= 1; + if (mpc83xx_spi->count) { + if (mpc83xx_spi->tx) { + u32 word = mpc83xx_spi->get_tx(mpc83xx_spi); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->transmit, + word); + } + } else { + complete(&mpc83xx_spi->done); + } + + /* Clear the events */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->event, event); + + return ret; +} + +static int __init mpc83xx_spi_probe(struct platform_device *dev) +{ + struct spi_master *master; + struct mpc83xx_spi *mpc83xx_spi; + struct fsl_spi_platform_data *pdata; + struct resource *r; + u32 regval; + int ret = 0; + + /* Get resources(memory, IRQ) associated with the device */ + master = spi_alloc_master(&dev->dev, sizeof(struct mpc83xx_spi)); + + if (master == NULL) { + ret = -ENOMEM; + goto err; + } + + platform_set_drvdata(dev, master); + pdata = dev->dev.platform_data; + + if (pdata == NULL) { + ret = -ENODEV; + goto free_master; + } + + r = platform_get_resource(dev, IORESOURCE_MEM, 0); + if (r == NULL) { + ret = -ENODEV; + goto free_master; + } + + mpc83xx_spi = spi_master_get_devdata(master); + mpc83xx_spi->bitbang.master = spi_master_get(master); + mpc83xx_spi->bitbang.chipselect = mpc83xx_spi_chipselect; + mpc83xx_spi->bitbang.setup_transfer = mpc83xx_spi_setup_transfer; + mpc83xx_spi->bitbang.txrx_bufs = mpc83xx_spi_bufs; + mpc83xx_spi->sysclk = pdata->sysclk; + mpc83xx_spi->activate_cs = pdata->activate_cs; + mpc83xx_spi->deactivate_cs = pdata->deactivate_cs; + mpc83xx_spi->get_rx = mpc83xx_spi_rx_buf_u8; + mpc83xx_spi->get_tx = mpc83xx_spi_tx_buf_u8; + + mpc83xx_spi->bitbang.master->setup = mpc83xx_spi_setup; + init_completion(&mpc83xx_spi->done); + + mpc83xx_spi->base = ioremap(r->start, r->end - r->start + 1); + if (mpc83xx_spi->base == NULL) { + ret = -ENOMEM; + goto put_master; + } + + mpc83xx_spi->irq = platform_get_irq(dev, 0); + + if (mpc83xx_spi->irq < 0) { + ret = -ENXIO; + goto unmap_io; + } + + /* Register for SPI Interrupt */ + ret = request_irq(mpc83xx_spi->irq, mpc83xx_spi_irq, + 0, "mpc83xx_spi", mpc83xx_spi); + + if (ret != 0) + goto unmap_io; + + master->bus_num = pdata->bus_num; + master->num_chipselect = pdata->max_chipselect; + + /* SPI controller initializations */ + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, 0); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mask, 0); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->command, 0); + mpc83xx_spi_write_reg(&mpc83xx_spi->base->event, 0xffffffff); + + /* Enable SPI interface */ + regval = pdata->initial_spmode | SPMODE_INIT_VAL | SPMODE_ENABLE; + mpc83xx_spi_write_reg(&mpc83xx_spi->base->mode, regval); + + ret = spi_bitbang_start(&mpc83xx_spi->bitbang); + + if (ret != 0) + goto free_irq; + + printk(KERN_INFO + "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n", + dev->dev.bus_id, mpc83xx_spi->base, mpc83xx_spi->irq); + + return ret; + +free_irq: + free_irq(mpc83xx_spi->irq, mpc83xx_spi); +unmap_io: + iounmap(mpc83xx_spi->base); +put_master: + spi_master_put(master); +free_master: + kfree(master); +err: + return ret; +} + +static int __devexit mpc83xx_spi_remove(struct platform_device *dev) +{ + struct mpc83xx_spi *mpc83xx_spi; + struct spi_master *master; + + master = platform_get_drvdata(dev); + mpc83xx_spi = spi_master_get_devdata(master); + + spi_bitbang_stop(&mpc83xx_spi->bitbang); + free_irq(mpc83xx_spi->irq, mpc83xx_spi); + iounmap(mpc83xx_spi->base); + spi_master_put(mpc83xx_spi->bitbang.master); + + return 0; +} + +static struct platform_driver mpc83xx_spi_driver = { + .probe = mpc83xx_spi_probe, + .remove = __devexit_p(mpc83xx_spi_remove), + .driver = { + .name = "mpc83xx_spi", + }, +}; + +static int __init mpc83xx_spi_init(void) +{ + return platform_driver_register(&mpc83xx_spi_driver); +} + +static void __exit mpc83xx_spi_exit(void) +{ + platform_driver_unregister(&mpc83xx_spi_driver); +} + +module_init(mpc83xx_spi_init); +module_exit(mpc83xx_spi_exit); + +MODULE_AUTHOR("Kumar Gala"); +MODULE_DESCRIPTION("Simple MPC83xx SPI Driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/fsl_devices.h b/include/linux/fsl_devices.h index a3a0e078f79d61..16fbe59edeb185 100644 --- a/include/linux/fsl_devices.h +++ b/include/linux/fsl_devices.h @@ -110,5 +110,16 @@ struct fsl_usb2_platform_data { #define FSL_USB2_PORT0_ENABLED 0x00000001 #define FSL_USB2_PORT1_ENABLED 0x00000002 +struct fsl_spi_platform_data { + u32 initial_spmode; /* initial SPMODE value */ + u16 bus_num; + + /* board specific information */ + u16 max_chipselect; + void (*activate_cs)(u8 cs, u8 polarity); + void (*deactivate_cs)(u8 cs, u8 polarity); + u32 sysclk; +}; + #endif /* _FSL_DEVICE_H_ */ #endif /* __KERNEL__ */ -- cgit 1.2.3-korg From 1b81d6637d27a0e6a0506ecef65493b50d859cfc Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sat, 20 May 2006 15:00:16 -0700 Subject: [PATCH] drivers/base/firmware_class.c: cleanups - remove the following global function that is both unused and unimplemented: - register_firmware() - make the following needlessly global function static: - firmware_class_uevent() Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/firmware_class/README | 17 ---------- .../firmware_class/firmware_sample_driver.c | 11 ------ drivers/base/firmware_class.c | 39 +++++----------------- include/linux/firmware.h | 1 - 4 files changed, 8 insertions(+), 60 deletions(-) diff --git a/Documentation/firmware_class/README b/Documentation/firmware_class/README index 43e836c07ae89e..e9cc8bb26f7d09 100644 --- a/Documentation/firmware_class/README +++ b/Documentation/firmware_class/README @@ -105,20 +105,3 @@ on the setup, so I think that the choice on what firmware to make persistent should be left to userspace. - - Why register_firmware()+__init can be useful: - - For boot devices needing firmware. - - To make the transition easier: - The firmware can be declared __init and register_firmware() - called on module_init. Then the firmware is warranted to be - there even if "firmware hotplug userspace" is not there yet or - it doesn't yet provide the needed firmware. - Once the firmware is widely available in userspace, it can be - removed from the kernel. Or made optional (CONFIG_.*_FIRMWARE). - - In either case, if firmware hotplug support is there, it can move the - firmware out of kernel memory into the real filesystem for later - usage. - - Note: If persistence is implemented on top of initramfs, - register_firmware() may not be appropriate. - diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c index ad3edaba4533cf..87feccdb5c9f8f 100644 --- a/Documentation/firmware_class/firmware_sample_driver.c +++ b/Documentation/firmware_class/firmware_sample_driver.c @@ -5,8 +5,6 @@ * * Sample code on how to use request_firmware() from drivers. * - * Note that register_firmware() is currently useless. - * */ #include @@ -17,11 +15,6 @@ #include "linux/firmware.h" -#define WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE -#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE -char __init inkernel_firmware[] = "let's say that this is firmware\n"; -#endif - static struct device ghost_device = { .bus_id = "ghost0", }; @@ -104,10 +97,6 @@ static void sample_probe_async(void) static int sample_init(void) { -#ifdef WE_CAN_NEED_FIRMWARE_BEFORE_USERSPACE_IS_AVAILABLE - register_firmware("sample_driver_fw", inkernel_firmware, - sizeof(inkernel_firmware)); -#endif device_initialize(&ghost_device); /* since there is no real hardware insertion I just call the * sample probe functions here */ diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 47231820523616..0c99ae6a340728 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -86,18 +86,9 @@ firmware_timeout_store(struct class *class, const char *buf, size_t count) static CLASS_ATTR(timeout, 0644, firmware_timeout_show, firmware_timeout_store); static void fw_class_dev_release(struct class_device *class_dev); -int firmware_class_uevent(struct class_device *dev, char **envp, - int num_envp, char *buffer, int buffer_size); -static struct class firmware_class = { - .name = "firmware", - .uevent = firmware_class_uevent, - .release = fw_class_dev_release, -}; - -int -firmware_class_uevent(struct class_device *class_dev, char **envp, - int num_envp, char *buffer, int buffer_size) +static int firmware_class_uevent(struct class_device *class_dev, char **envp, + int num_envp, char *buffer, int buffer_size) { struct firmware_priv *fw_priv = class_get_devdata(class_dev); int i = 0, len = 0; @@ -116,6 +107,12 @@ firmware_class_uevent(struct class_device *class_dev, char **envp, return 0; } +static struct class firmware_class = { + .name = "firmware", + .uevent = firmware_class_uevent, + .release = fw_class_dev_release, +}; + static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf) { @@ -493,25 +490,6 @@ release_firmware(const struct firmware *fw) } } -/** - * register_firmware: - provide a firmware image for later usage - * @name: name of firmware image file - * @data: buffer pointer for the firmware image - * @size: size of the data buffer area - * - * Make sure that @data will be available by requesting firmware @name. - * - * Note: This will not be possible until some kind of persistence - * is available. - **/ -void -register_firmware(const char *name, const u8 *data, size_t size) -{ - /* This is meaningless without firmware caching, so until we - * decide if firmware caching is reasonable just leave it as a - * noop */ -} - /* Async support */ struct firmware_work { struct work_struct work; @@ -630,4 +608,3 @@ module_exit(firmware_class_exit); EXPORT_SYMBOL(release_firmware); EXPORT_SYMBOL(request_firmware); EXPORT_SYMBOL(request_firmware_nowait); -EXPORT_SYMBOL(register_firmware); diff --git a/include/linux/firmware.h b/include/linux/firmware.h index 2d716080be4af7..33d8f2087b6ea9 100644 --- a/include/linux/firmware.h +++ b/include/linux/firmware.h @@ -19,5 +19,4 @@ int request_firmware_nowait( void (*cont)(const struct firmware *fw, void *context)); void release_firmware(const struct firmware *fw); -void register_firmware(const char *name, const u8 *data, size_t size); #endif -- cgit 1.2.3-korg From 1fc7547d4bfe5c8c8c79e196b955b6fbaa21bfd2 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sat, 20 May 2006 15:00:17 -0700 Subject: [PATCH] S3C24XX: GPIO based SPI driver SPI driver for SPI by GPIO on the Samsung S3C24XX series of SoC processors. Signed-off-by: Ben Dooks Cc: Greg KH Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/Kconfig | 8 ++ drivers/spi/Makefile | 1 + drivers/spi/spi_butterfly.c | 1 + drivers/spi/spi_s3c24xx_gpio.c | 188 ++++++++++++++++++++++++++++++++ include/asm-arm/arch-s3c2410/spi-gpio.h | 31 ++++++ 5 files changed, 229 insertions(+) create mode 100644 drivers/spi/spi_s3c24xx_gpio.c create mode 100644 include/asm-arm/arch-s3c2410/spi-gpio.h diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 3867c6ef24f34d..c60dacfaadd2db 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -95,6 +95,14 @@ config SPI_PXA2XX The driver can be configured to use any SSP port and additional documentation can be found a Documentation/spi/pxa2xx. +config SPI_S3C24XX_GPIO + tristate "Samsung S3C24XX series SPI by GPIO" + depends on SPI_MASTER && ARCH_S3C2410 && SPI_BITBANG && EXPERIMENTAL + help + SPI driver for Samsung S3C24XX series ARM SoCs using + GPIO lines to provide the SPI bus. This can be used where + the inbuilt hardware cannot provide the transfer mode, or + where the board is using non hardware connected pins. # # Add new SPI master controllers in alphabetical order above this line # diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 5a410caa03c73f..4dc82c93bfe69e 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o +obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o # ... add above this line ... # SPI protocol drivers (device/link on bus) diff --git a/drivers/spi/spi_butterfly.c b/drivers/spi/spi_butterfly.c index ff9e5faa4dc9f3..a006a1ee27acb6 100644 --- a/drivers/spi/spi_butterfly.c +++ b/drivers/spi/spi_butterfly.c @@ -321,6 +321,7 @@ static void butterfly_attach(struct parport *p) * (firmware resets at45, acts as spi slave) or neither (we ignore * both, AVR uses AT45). Here we expect firmware for the first option. */ + pp->info[0].max_speed_hz = 15 * 1000 * 1000; strcpy(pp->info[0].modalias, "mtd_dataflash"); pp->info[0].platform_data = &flash; diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c new file mode 100644 index 00000000000000..aacdceb8f44b69 --- /dev/null +++ b/drivers/spi/spi_s3c24xx_gpio.c @@ -0,0 +1,188 @@ +/* linux/drivers/spi/spi_s3c24xx_gpio.c + * + * Copyright (c) 2006 Ben Dooks + * Copyright (c) 2006 Simtec Electronics + * + * S3C24XX GPIO based SPI driver + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +struct s3c2410_spigpio { + struct spi_bitbang bitbang; + + struct s3c2410_spigpio_info *info; + struct platform_device *dev; +}; + +static inline struct s3c2410_spigpio *spidev_to_sg(struct spi_device *spi) +{ + return spi->controller_data; +} + +static inline void setsck(struct spi_device *dev, int on) +{ + struct s3c2410_spigpio *sg = spidev_to_sg(dev); + s3c2410_gpio_setpin(sg->info->pin_clk, on ? 1 : 0); +} + +static inline void setmosi(struct spi_device *dev, int on) +{ + struct s3c2410_spigpio *sg = spidev_to_sg(dev); + s3c2410_gpio_setpin(sg->info->pin_mosi, on ? 1 : 0); +} + +static inline u32 getmiso(struct spi_device *dev) +{ + struct s3c2410_spigpio *sg = spidev_to_sg(dev); + return s3c2410_gpio_getpin(sg->info->pin_miso) ? 1 : 0; +} + +#define spidelay(x) ndelay(x) + +#define EXPAND_BITBANG_TXRX +#include + + +static u32 s3c2410_spigpio_txrx_mode0(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); +} + +static u32 s3c2410_spigpio_txrx_mode1(struct spi_device *spi, + unsigned nsecs, u32 word, u8 bits) +{ + return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits); +} + +static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value) +{ + struct s3c2410_spigpio *sg = spidev_to_sg(dev); + + if (sg->info && sg->info->chip_select) + (sg->info->chip_select)(sg->info, value); +} + +static int s3c2410_spigpio_probe(struct platform_device *dev) +{ + struct spi_master *master; + struct s3c2410_spigpio *sp; + int ret; + int i; + + master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio)); + if (master == NULL) { + dev_err(&dev->dev, "failed to allocate spi master\n"); + ret = -ENOMEM; + goto err; + } + + sp = spi_master_get_devdata(master); + + platform_set_drvdata(dev, sp); + + /* copy in the plkatform data */ + sp->info = dev->dev.platform_data; + + /* setup spi bitbang adaptor */ + sp->bitbang.master = spi_master_get(master); + sp->bitbang.chipselect = s3c2410_spigpio_chipselect; + + sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0; + sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1; + + /* set state of spi pins */ + s3c2410_gpio_setpin(sp->info->pin_clk, 0); + s3c2410_gpio_setpin(sp->info->pin_mosi, 0); + + s3c2410_gpio_cfgpin(sp->info->pin_clk, S3C2410_GPIO_OUTPUT); + s3c2410_gpio_cfgpin(sp->info->pin_mosi, S3C2410_GPIO_OUTPUT); + s3c2410_gpio_cfgpin(sp->info->pin_miso, S3C2410_GPIO_INPUT); + + ret = spi_bitbang_start(&sp->bitbang); + if (ret) + goto err_no_bitbang; + + /* register the chips to go with the board */ + + for (i = 0; i < sp->info->board_size; i++) { + dev_info(&dev->dev, "registering %p: %s\n", + &sp->info->board_info[i], + sp->info->board_info[i].modalias); + + sp->info->board_info[i].controller_data = sp; + spi_new_device(master, sp->info->board_info + i); + } + + return 0; + + err_no_bitbang: + spi_master_put(sp->bitbang.master); + err: + return ret; + +} + +static int s3c2410_spigpio_remove(struct platform_device *dev) +{ + struct s3c2410_spigpio *sp = platform_get_drvdata(dev); + + spi_bitbang_stop(&sp->bitbang); + spi_master_put(sp->bitbang.master); + + return 0; +} + +/* all gpio should be held over suspend/resume, so we should + * not need to deal with this +*/ + +#define s3c2410_spigpio_suspend NULL +#define s3c2410_spigpio_resume NULL + + +static struct platform_driver s3c2410_spigpio_drv = { + .probe = s3c2410_spigpio_probe, + .remove = s3c2410_spigpio_remove, + .suspend = s3c2410_spigpio_suspend, + .resume = s3c2410_spigpio_resume, + .driver = { + .name = "s3c24xx-spi-gpio", + .owner = THIS_MODULE, + }, +}; + +static int __init s3c2410_spigpio_init(void) +{ + return platform_driver_register(&s3c2410_spigpio_drv); +} + +static void __exit s3c2410_spigpio_exit(void) +{ + platform_driver_unregister(&s3c2410_spigpio_drv); +} + +module_init(s3c2410_spigpio_init); +module_exit(s3c2410_spigpio_exit); + +MODULE_DESCRIPTION("S3C24XX SPI Driver"); +MODULE_AUTHOR("Ben Dooks, "); +MODULE_LICENSE("GPL"); diff --git a/include/asm-arm/arch-s3c2410/spi-gpio.h b/include/asm-arm/arch-s3c2410/spi-gpio.h new file mode 100644 index 00000000000000..258c00bca2706f --- /dev/null +++ b/include/asm-arm/arch-s3c2410/spi-gpio.h @@ -0,0 +1,31 @@ +/* linux/include/asm-arm/arch-s3c2410/spi.h + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * S3C2410 - SPI Controller platfrom_device info + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_SPIGPIO_H +#define __ASM_ARCH_SPIGPIO_H __FILE__ + +struct s3c2410_spigpio_info; +struct spi_board_info; + +struct s3c2410_spigpio_info { + unsigned long pin_clk; + unsigned long pin_mosi; + unsigned long pin_miso; + + unsigned long board_size; + struct spi_board_info *board_info; + + void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs); +}; + + +#endif /* __ASM_ARCH_SPIGPIO_H */ -- cgit 1.2.3-korg From 7fba53402eb0fb4209c74469814c583b6455e096 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sat, 20 May 2006 15:00:18 -0700 Subject: [PATCH] S3C24XX: hardware SPI driver Hardware based SPI driver for Samsung S3C24XX SoC systems Signed-off-by: Ben Dooks Cc: David Brownell Cc: Greg KH Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/Kconfig | 6 + drivers/spi/Makefile | 1 + drivers/spi/spi_s3c24xx.c | 453 +++++++++++++++++++++++++++++++++++++ include/asm-arm/arch-s3c2410/spi.h | 29 +++ 4 files changed, 489 insertions(+) create mode 100644 drivers/spi/spi_s3c24xx.c create mode 100644 include/asm-arm/arch-s3c2410/spi.h diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index c60dacfaadd2db..23334c8bc4c75e 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -108,6 +108,12 @@ config SPI_S3C24XX_GPIO # +config SPI_S3C24XX + tristate "Samsung S3C24XX series SPI" + depends on SPI_MASTER && ARCH_S3C2410 && EXPERIMENTAL + help + SPI driver for Samsung S3C24XX series ARM SoCs + # # There are lots of SPI device types, with sensors and memory # being probably the most widely used ones. diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 4dc82c93bfe69e..8f4cb67997b32a 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -16,6 +16,7 @@ obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o obj-$(CONFIG_SPI_MPC83xx) += spi_mpc83xx.o obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o +obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o # ... add above this line ... # SPI protocol drivers (device/link on bus) diff --git a/drivers/spi/spi_s3c24xx.c b/drivers/spi/spi_s3c24xx.c new file mode 100644 index 00000000000000..9de4b5a04d70f2 --- /dev/null +++ b/drivers/spi/spi_s3c24xx.c @@ -0,0 +1,453 @@ +/* linux/drivers/spi/spi_s3c24xx.c + * + * Copyright (c) 2006 Ben Dooks + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * +*/ + + +//#define DEBUG + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +struct s3c24xx_spi { + /* bitbang has to be first */ + struct spi_bitbang bitbang; + struct completion done; + + void __iomem *regs; + int irq; + int len; + int count; + + /* data buffers */ + const unsigned char *tx; + unsigned char *rx; + + struct clk *clk; + struct resource *ioarea; + struct spi_master *master; + struct spi_device *curdev; + struct device *dev; + struct s3c2410_spi_info *pdata; +}; + +#define SPCON_DEFAULT (S3C2410_SPCON_MSTR | S3C2410_SPCON_SMOD_INT) +#define SPPIN_DEFAULT (S3C2410_SPPIN_KEEP) + +static inline struct s3c24xx_spi *to_hw(struct spi_device *sdev) +{ + return spi_master_get_devdata(sdev->master); +} + +static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) +{ + struct s3c24xx_spi *hw = to_hw(spi); + unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0; + unsigned int spcon; + + switch (value) { + case BITBANG_CS_INACTIVE: + if (hw->pdata->set_cs) + hw->pdata->set_cs(hw->pdata, value, cspol); + else + s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol ^ 1); + break; + + case BITBANG_CS_ACTIVE: + spcon = readb(hw->regs + S3C2410_SPCON); + + if (spi->mode & SPI_CPHA) + spcon |= S3C2410_SPCON_CPHA_FMTB; + else + spcon &= ~S3C2410_SPCON_CPHA_FMTB; + + if (spi->mode & SPI_CPOL) + spcon |= S3C2410_SPCON_CPOL_HIGH; + else + spcon &= ~S3C2410_SPCON_CPOL_HIGH; + + spcon |= S3C2410_SPCON_ENSCK; + + /* write new configration */ + + writeb(spcon, hw->regs + S3C2410_SPCON); + + if (hw->pdata->set_cs) + hw->pdata->set_cs(hw->pdata, value, cspol); + else + s3c2410_gpio_setpin(hw->pdata->pin_cs, cspol); + + break; + + } +} + +static int s3c24xx_spi_setupxfer(struct spi_device *spi, + struct spi_transfer *t) +{ + struct s3c24xx_spi *hw = to_hw(spi); + unsigned int bpw; + unsigned int hz; + unsigned int div; + + bpw = t ? t->bits_per_word : spi->bits_per_word; + hz = t ? t->speed_hz : spi->max_speed_hz; + + if (bpw != 8) { + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw); + return -EINVAL; + } + + div = clk_get_rate(hw->clk) / hz; + + /* is clk = pclk / (2 * (pre+1)), or is it + * clk = (pclk * 2) / ( pre + 1) */ + + div = (div / 2) - 1; + + if (div < 0) + div = 1; + + if (div > 255) + div = 255; + + dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", div, hz); + writeb(div, hw->regs + S3C2410_SPPRE); + + spin_lock(&hw->bitbang.lock); + if (!hw->bitbang.busy) { + hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); + /* need to ndelay for 0.5 clocktick ? */ + } + spin_unlock(&hw->bitbang.lock); + + return 0; +} + +static int s3c24xx_spi_setup(struct spi_device *spi) +{ + int ret; + + if (!spi->bits_per_word) + spi->bits_per_word = 8; + + if ((spi->mode & SPI_LSB_FIRST) != 0) + return -EINVAL; + + ret = s3c24xx_spi_setupxfer(spi, NULL); + if (ret < 0) { + dev_err(&spi->dev, "setupxfer returned %d\n", ret); + return ret; + } + + dev_dbg(&spi->dev, "%s: mode %d, %u bpw, %d hz\n", + __FUNCTION__, spi->mode, spi->bits_per_word, + spi->max_speed_hz); + + return 0; +} + +static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count) +{ + return hw->tx ? hw->tx[count] : 0xff; +} + +static int s3c24xx_spi_txrx(struct spi_device *spi, struct spi_transfer *t) +{ + struct s3c24xx_spi *hw = to_hw(spi); + + dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", + t->tx_buf, t->rx_buf, t->len); + + hw->tx = t->tx_buf; + hw->rx = t->rx_buf; + hw->len = t->len; + hw->count = 0; + + /* send the first byte */ + writeb(hw_txbyte(hw, 0), hw->regs + S3C2410_SPTDAT); + wait_for_completion(&hw->done); + + return hw->count; +} + +static irqreturn_t s3c24xx_spi_irq(int irq, void *dev, struct pt_regs *regs) +{ + struct s3c24xx_spi *hw = dev; + unsigned int spsta = readb(hw->regs + S3C2410_SPSTA); + unsigned int count = hw->count; + + if (spsta & S3C2410_SPSTA_DCOL) { + dev_dbg(hw->dev, "data-collision\n"); + complete(&hw->done); + goto irq_done; + } + + if (!(spsta & S3C2410_SPSTA_READY)) { + dev_dbg(hw->dev, "spi not ready for tx?\n"); + complete(&hw->done); + goto irq_done; + } + + hw->count++; + + if (hw->rx) + hw->rx[count] = readb(hw->regs + S3C2410_SPRDAT); + + count++; + + if (count < hw->len) + writeb(hw_txbyte(hw, count), hw->regs + S3C2410_SPTDAT); + else + complete(&hw->done); + + irq_done: + return IRQ_HANDLED; +} + +static int s3c24xx_spi_probe(struct platform_device *pdev) +{ + struct s3c24xx_spi *hw; + struct spi_master *master; + struct spi_board_info *bi; + struct resource *res; + int err = 0; + int i; + + master = spi_alloc_master(&pdev->dev, sizeof(struct s3c24xx_spi)); + if (master == NULL) { + dev_err(&pdev->dev, "No memory for spi_master\n"); + err = -ENOMEM; + goto err_nomem; + } + + hw = spi_master_get_devdata(master); + memset(hw, 0, sizeof(struct s3c24xx_spi)); + + hw->master = spi_master_get(master); + hw->pdata = pdev->dev.platform_data; + hw->dev = &pdev->dev; + + if (hw->pdata == NULL) { + dev_err(&pdev->dev, "No platform data supplied\n"); + err = -ENOENT; + goto err_no_pdata; + } + + platform_set_drvdata(pdev, hw); + init_completion(&hw->done); + + /* setup the state for the bitbang driver */ + + hw->bitbang.master = hw->master; + hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer; + hw->bitbang.chipselect = s3c24xx_spi_chipsel; + hw->bitbang.txrx_bufs = s3c24xx_spi_txrx; + hw->bitbang.master->setup = s3c24xx_spi_setup; + + dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang); + + /* find and map our resources */ + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); + err = -ENOENT; + goto err_no_iores; + } + + hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1, + pdev->name); + + if (hw->ioarea == NULL) { + dev_err(&pdev->dev, "Cannot reserve region\n"); + err = -ENXIO; + goto err_no_iores; + } + + hw->regs = ioremap(res->start, (res->end - res->start)+1); + if (hw->regs == NULL) { + dev_err(&pdev->dev, "Cannot map IO\n"); + err = -ENXIO; + goto err_no_iomap; + } + + hw->irq = platform_get_irq(pdev, 0); + if (hw->irq < 0) { + dev_err(&pdev->dev, "No IRQ specified\n"); + err = -ENOENT; + goto err_no_irq; + } + + err = request_irq(hw->irq, s3c24xx_spi_irq, 0, pdev->name, hw); + if (err) { + dev_err(&pdev->dev, "Cannot claim IRQ\n"); + goto err_no_irq; + } + + hw->clk = clk_get(&pdev->dev, "spi"); + if (IS_ERR(hw->clk)) { + dev_err(&pdev->dev, "No clock for device\n"); + err = PTR_ERR(hw->clk); + goto err_no_clk; + } + + /* for the moment, permanently enable the clock */ + + clk_enable(hw->clk); + + /* program defaults into the registers */ + + writeb(0xff, hw->regs + S3C2410_SPPRE); + writeb(SPPIN_DEFAULT, hw->regs + S3C2410_SPPIN); + writeb(SPCON_DEFAULT, hw->regs + S3C2410_SPCON); + + /* setup any gpio we can */ + + if (!hw->pdata->set_cs) { + s3c2410_gpio_setpin(hw->pdata->pin_cs, 1); + s3c2410_gpio_cfgpin(hw->pdata->pin_cs, S3C2410_GPIO_OUTPUT); + } + + /* register our spi controller */ + + err = spi_bitbang_start(&hw->bitbang); + if (err) { + dev_err(&pdev->dev, "Failed to register SPI master\n"); + goto err_register; + } + + dev_dbg(hw->dev, "shutdown=%d\n", hw->bitbang.shutdown); + + /* register all the devices associated */ + + bi = &hw->pdata->board_info[0]; + for (i = 0; i < hw->pdata->board_size; i++, bi++) { + dev_info(hw->dev, "registering %s\n", bi->modalias); + + bi->controller_data = hw; + spi_new_device(master, bi); + } + + return 0; + + err_register: + clk_disable(hw->clk); + clk_put(hw->clk); + + err_no_clk: + free_irq(hw->irq, hw); + + err_no_irq: + iounmap(hw->regs); + + err_no_iomap: + release_resource(hw->ioarea); + kfree(hw->ioarea); + + err_no_iores: + err_no_pdata: + spi_master_put(hw->master);; + + err_nomem: + return err; +} + +static int s3c24xx_spi_remove(struct platform_device *dev) +{ + struct s3c24xx_spi *hw = platform_get_drvdata(dev); + + platform_set_drvdata(dev, NULL); + + spi_unregister_master(hw->master); + + clk_disable(hw->clk); + clk_put(hw->clk); + + free_irq(hw->irq, hw); + iounmap(hw->regs); + + release_resource(hw->ioarea); + kfree(hw->ioarea); + + spi_master_put(hw->master); + return 0; +} + + +#ifdef CONFIG_PM + +static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg) +{ + struct s3c24xx_spi *hw = platform_get_drvdata(dev); + + clk_disable(hw->clk); + return 0; +} + +static int s3c24xx_spi_resume(struct platform_device *pdev) +{ + struct s3c24xx_spi *hw = platform_get_drvdata(dev); + + clk_enable(hw->clk); + return 0; +} + +#else +#define s3c24xx_spi_suspend NULL +#define s3c24xx_spi_resume NULL +#endif + +static struct platform_driver s3c24xx_spidrv = { + .probe = s3c24xx_spi_probe, + .remove = s3c24xx_spi_remove, + .suspend = s3c24xx_spi_suspend, + .resume = s3c24xx_spi_resume, + .driver = { + .name = "s3c2410-spi", + .owner = THIS_MODULE, + }, +}; + +static int __init s3c24xx_spi_init(void) +{ + return platform_driver_register(&s3c24xx_spidrv); +} + +static void __exit s3c24xx_spi_exit(void) +{ + platform_driver_unregister(&s3c24xx_spidrv); +} + +module_init(s3c24xx_spi_init); +module_exit(s3c24xx_spi_exit); + +MODULE_DESCRIPTION("S3C24XX SPI Driver"); +MODULE_AUTHOR("Ben Dooks, "); +MODULE_LICENSE("GPL"); diff --git a/include/asm-arm/arch-s3c2410/spi.h b/include/asm-arm/arch-s3c2410/spi.h new file mode 100644 index 00000000000000..4029a1a1ab406f --- /dev/null +++ b/include/asm-arm/arch-s3c2410/spi.h @@ -0,0 +1,29 @@ +/* linux/include/asm-arm/arch-s3c2410/spi.h + * + * Copyright (c) 2006 Simtec Electronics + * Ben Dooks + * + * S3C2410 - SPI Controller platform_device info + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. +*/ + +#ifndef __ASM_ARCH_SPI_H +#define __ASM_ARCH_SPI_H __FILE__ + +struct s3c2410_spi_info; +struct spi_board_info; + +struct s3c2410_spi_info { + unsigned long pin_cs; /* simple gpio cs */ + + unsigned long board_size; + struct spi_board_info *board_info; + + void (*set_cs)(struct s3c2410_spi_info *spi, int cs, int pol); +}; + + +#endif /* __ASM_ARCH_SPI_H */ -- cgit 1.2.3-korg From 5daa3ba0c6a41a8bb4ba17ad8d5514172e103504 Mon Sep 17 00:00:00 2001 From: Stephen Street Date: Sat, 20 May 2006 15:00:19 -0700 Subject: [PATCH] pxa2xx-spi update Fix some outstanding issues with the pxa2xx_spi driver when running on a PXA270: - Wrong timeout calculation in the setup function due to different peripheral clock rates in the PXAxxx family. - Bad handling of SSSR_TFS interrupts in interrupt_transfer function. - Added locking to interface between the pump_messages workqueue and the pump_transfers tasklet. Much thanks to Juergen Beisert for the extensive testing on the PXA270. Signed-off-by: Stephen Street Signed-off-by: David Brownell Cc: Russell King Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/spi/pxa2xx_spi.c | 93 +++++++++++++++++++++-------------- include/asm-arm/arch-pxa/pxa2xx_spi.h | 3 ++ 2 files changed, 59 insertions(+), 37 deletions(-) diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 596bf820b70c65..29aec77f98be53 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -363,25 +363,30 @@ static void unmap_dma_buffers(struct driver_data *drv_data) } /* caller already set message->status; dma and pio irqs are blocked */ -static void giveback(struct spi_message *message, struct driver_data *drv_data) +static void giveback(struct driver_data *drv_data) { struct spi_transfer* last_transfer; + unsigned long flags; + struct spi_message *msg; - last_transfer = list_entry(message->transfers.prev, + spin_lock_irqsave(&drv_data->lock, flags); + msg = drv_data->cur_msg; + drv_data->cur_msg = NULL; + drv_data->cur_transfer = NULL; + drv_data->cur_chip = NULL; + queue_work(drv_data->workqueue, &drv_data->pump_messages); + spin_unlock_irqrestore(&drv_data->lock, flags); + + last_transfer = list_entry(msg->transfers.prev, struct spi_transfer, transfer_list); if (!last_transfer->cs_change) drv_data->cs_control(PXA2XX_CS_DEASSERT); - message->state = NULL; - if (message->complete) - message->complete(message->context); - - drv_data->cur_msg = NULL; - drv_data->cur_transfer = NULL; - drv_data->cur_chip = NULL; - queue_work(drv_data->workqueue, &drv_data->pump_messages); + msg->state = NULL; + if (msg->complete) + msg->complete(msg->context); } static int wait_ssp_rx_stall(void *ioaddr) @@ -415,10 +420,11 @@ static void dma_handler(int channel, void *data, struct pt_regs *regs) if (irq_status & DCSR_BUSERR) { /* Disable interrupts, clear status and reset DMA */ + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; @@ -454,8 +460,8 @@ static void dma_handler(int channel, void *data, struct pt_regs *regs) "dma_handler: ssp rx stall failed\n"); /* Clear and disable interrupts on SSP and DMA channels*/ - write_SSSR(drv_data->clear_sr, reg); write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); + write_SSSR(drv_data->clear_sr, reg); DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; if (wait_dma_channel_stop(drv_data->rx_channel) == 0) @@ -497,10 +503,11 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) irq_status = read_SSSR(reg) & drv_data->mask_sr; if (irq_status & SSSR_ROR) { /* Clear and disable interrupts on SSP and DMA channels*/ + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; unmap_dma_buffers(drv_data); @@ -526,10 +533,10 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) if (irq_status & SSSR_TINT || drv_data->rx == drv_data->rx_end) { /* Clear and disable interrupts on SSP and DMA channels*/ + write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->dma_cr1, reg); DCSR(drv_data->tx_channel) = RESET_DMA_CHANNEL; DCSR(drv_data->rx_channel) = RESET_DMA_CHANNEL; @@ -572,26 +579,30 @@ static irqreturn_t dma_transfer(struct driver_data *drv_data) static irqreturn_t interrupt_transfer(struct driver_data *drv_data) { - u32 irq_status; struct spi_message *msg = drv_data->cur_msg; void *reg = drv_data->ioaddr; - irqreturn_t handled = IRQ_NONE; unsigned long limit = loops_per_jiffy << 1; + u32 irq_status; + u32 irq_mask = (read_SSCR1(reg) & SSCR1_TIE) ? + drv_data->mask_sr : drv_data->mask_sr & ~SSSR_TFS; - while ((irq_status = (read_SSSR(reg) & drv_data->mask_sr))) { + while ((irq_status = read_SSSR(reg) & irq_mask)) { if (irq_status & SSSR_ROR) { /* Clear and disable interrupts */ + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); if (flush(drv_data) == 0) dev_err(&drv_data->pdev->dev, "interrupt_transfer: flush fail\n"); + /* Stop the SSP */ + dev_warn(&drv_data->pdev->dev, "interrupt_transfer: fifo overun\n"); @@ -613,6 +624,7 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) if (drv_data->tx == drv_data->tx_end) { /* Disable tx interrupt */ write_SSCR1(read_SSCR1(reg) & ~SSCR1_TIE, reg); + irq_mask = drv_data->mask_sr & ~SSSR_TFS; /* PXA25x_SSP has no timeout, read trailing bytes */ if (drv_data->ssp_type == PXA25x_SSP) { @@ -630,10 +642,10 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) || (drv_data->rx == drv_data->rx_end)) { /* Clear timeout */ + write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); if (drv_data->ssp_type != PXA25x_SSP) write_SSTO(0, reg); write_SSSR(drv_data->clear_sr, reg); - write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); /* Update total byte transfered */ msg->actual_length += drv_data->len; @@ -648,24 +660,29 @@ static irqreturn_t interrupt_transfer(struct driver_data *drv_data) /* Schedule transfer tasklet */ tasklet_schedule(&drv_data->pump_transfers); - - return IRQ_HANDLED; } - - /* We did something */ - handled = IRQ_HANDLED; } - return handled; + /* We did something */ + return IRQ_HANDLED; } static irqreturn_t ssp_int(int irq, void *dev_id, struct pt_regs *regs) { struct driver_data *drv_data = (struct driver_data *)dev_id; + void *reg = drv_data->ioaddr; if (!drv_data->cur_msg) { + + write_SSCR0(read_SSCR0(reg) & ~SSCR0_SSE, reg); + write_SSCR1(read_SSCR1(reg) & ~drv_data->int_cr1, reg); + if (drv_data->ssp_type != PXA25x_SSP) + write_SSTO(0, reg); + write_SSSR(drv_data->clear_sr, reg); + dev_err(&drv_data->pdev->dev, "bad message state " - "in interrupt handler\n"); + "in interrupt handler"); + /* Never fail */ return IRQ_HANDLED; } @@ -694,14 +711,14 @@ static void pump_transfers(unsigned long data) /* Handle for abort */ if (message->state == ERROR_STATE) { message->status = -EIO; - giveback(message, drv_data); + giveback(drv_data); return; } /* Handle end of message */ if (message->state == DONE_STATE) { message->status = 0; - giveback(message, drv_data); + giveback(drv_data); return; } @@ -718,7 +735,7 @@ static void pump_transfers(unsigned long data) if (flush(drv_data) == 0) { dev_err(&drv_data->pdev->dev, "pump_transfers: flush failed\n"); message->status = -EIO; - giveback(message, drv_data); + giveback(drv_data); return; } drv_data->n_bytes = chip->n_bytes; @@ -782,7 +799,7 @@ static void pump_transfers(unsigned long data) cr0 = clk_div | SSCR0_Motorola - | SSCR0_DataSize(bits & 0x0f) + | SSCR0_DataSize(bits > 16 ? bits - 16 : bits) | SSCR0_SSE | (bits > 16 ? SSCR0_EDSS : 0); @@ -890,8 +907,6 @@ static void pump_messages(void *data) drv_data->cur_msg = list_entry(drv_data->queue.next, struct spi_message, queue); list_del_init(&drv_data->cur_msg->queue); - drv_data->busy = 1; - spin_unlock_irqrestore(&drv_data->lock, flags); /* Initial message state*/ drv_data->cur_msg->state = START_STATE; @@ -905,6 +920,9 @@ static void pump_messages(void *data) /* Mark as busy and launch transfers */ tasklet_schedule(&drv_data->pump_transfers); + + drv_data->busy = 1; + spin_unlock_irqrestore(&drv_data->lock, flags); } static int transfer(struct spi_device *spi, struct spi_message *msg) @@ -958,7 +976,7 @@ static int setup(struct spi_device *spi) chip->cs_control = null_cs_control; chip->enable_dma = 0; - chip->timeout = 5; + chip->timeout = SSP_TIMEOUT(1000); chip->threshold = SSCR1_RxTresh(1) | SSCR1_TxTresh(1); chip->dma_burst_size = drv_data->master_info->enable_dma ? DCMD_BURST8 : 0; @@ -971,7 +989,7 @@ static int setup(struct spi_device *spi) if (chip_info->cs_control) chip->cs_control = chip_info->cs_control; - chip->timeout = (chip_info->timeout_microsecs * 10000) / 2712; + chip->timeout = SSP_TIMEOUT(chip_info->timeout_microsecs); chip->threshold = SSCR1_RxTresh(chip_info->rx_threshold) | SSCR1_TxTresh(chip_info->tx_threshold); @@ -1013,7 +1031,8 @@ static int setup(struct spi_device *spi) chip->cr0 = clk_div | SSCR0_Motorola - | SSCR0_DataSize(spi->bits_per_word & 0x0f) + | SSCR0_DataSize(spi->bits_per_word > 16 ? + spi->bits_per_word - 16 : spi->bits_per_word) | SSCR0_SSE | (spi->bits_per_word > 16 ? SSCR0_EDSS : 0); chip->cr1 |= (((spi->mode & SPI_CPHA) != 0) << 4) @@ -1196,7 +1215,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) goto out_error_master_alloc; } - drv_data->ioaddr = (void *)io_p2v(memory_resource->start); + drv_data->ioaddr = (void *)io_p2v((unsigned long)(memory_resource->start)); drv_data->ssdr_physical = memory_resource->start + 0x00000010; if (platform_info->ssp_type == PXA25x_SSP) { drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE; @@ -1218,7 +1237,7 @@ static int pxa2xx_spi_probe(struct platform_device *pdev) goto out_error_master_alloc; } - status = request_irq(irq, ssp_int, SA_INTERRUPT, dev->bus_id, drv_data); + status = request_irq(irq, ssp_int, 0, dev->bus_id, drv_data); if (status < 0) { dev_err(&pdev->dev, "can not get IRQ\n"); goto out_error_master_alloc; diff --git a/include/asm-arm/arch-pxa/pxa2xx_spi.h b/include/asm-arm/arch-pxa/pxa2xx_spi.h index 1e70908b816f59..915590c391c8c8 100644 --- a/include/asm-arm/arch-pxa/pxa2xx_spi.h +++ b/include/asm-arm/arch-pxa/pxa2xx_spi.h @@ -27,13 +27,16 @@ #define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/2/(x+1))<<8)&0x0000ff00) #define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) +#define SSP_TIMEOUT_SCALE (2712) #elif defined(CONFIG_PXA27x) #define CLOCK_SPEED_HZ 13000000 #define SSP1_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP2_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) #define SSP3_SerClkDiv(x) (((CLOCK_SPEED_HZ/(x+1))<<8)&0x000fff00) +#define SSP_TIMEOUT_SCALE (769) #endif +#define SSP_TIMEOUT(x) ((x*10000)/SSP_TIMEOUT_SCALE) #define SSP1_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(1))))) #define SSP2_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(2))))) #define SSP3_VIRT ((void *)(io_p2v(__PREG(SSCR0_P(3))))) -- cgit 1.2.3-korg From be0d03f1c3d3612fe2b6aa451ae87a89382c9231 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Sat, 20 May 2006 15:00:21 -0700 Subject: [PATCH] i386 kdump boot cpu physical apicid fix o Kdump second kernel boot fails after a system crash if second kernel is UP and acpi=off and if crash occurred on a non-boot cpu. o Issue here is that MP tables report boot cpu lapic id as 0 but second kernel is booting on a different processor and MP table data is stale in this context. Hence apic_id_registered() check fails in setup_local_APIC() when called from APIC_init_uniprocessor(). o Problem is not seen if ACPI is enabled as in that case boot_cpu_physical_apicid is read from the LAPIC. o Problem is not seen with SMP kernels as well because in this case also boot_cpu_physical_apicid is read from LAPIC. (smp_boot_cpus()). o The problem is fixed by reading boot_cpu_physical_apicid from LAPIC if it is a UP kernel and CRASH_DUMP is enabled. Signed-off-by: Vivek Goyal Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/kernel/apic.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/i386/kernel/apic.c b/arch/i386/kernel/apic.c index 013b85df18c658..3d4b2f3d116a79 100644 --- a/arch/i386/kernel/apic.c +++ b/arch/i386/kernel/apic.c @@ -1341,6 +1341,14 @@ int __init APIC_init_uniprocessor (void) connect_bsp_APIC(); + /* + * Hack: In case of kdump, after a crash, kernel might be booting + * on a cpu with non-zero lapic id. But boot_cpu_physical_apicid + * might be zero if read from MP tables. Get it from LAPIC. + */ +#ifdef CONFIG_CRASH_DUMP + boot_cpu_physical_apicid = GET_APIC_ID(apic_read(APIC_ID)); +#endif phys_cpu_present_map = physid_mask_of_physid(boot_cpu_physical_apicid); setup_local_APIC(); -- cgit 1.2.3-korg From dc49e3445aa703eb7fd33c7ddb7e4a7bbcf06d30 Mon Sep 17 00:00:00 2001 From: Satoshi Oshima Date: Sat, 20 May 2006 15:00:21 -0700 Subject: [PATCH] kprobes: bad manipulation of 2 byte opcode on x86_64 Problem: If we put a probe onto a callq instruction and the probe is executed, kernel panic of Bad RIP value occurs. Root cause: If resume_execution() found 0xff at first byte of p->ainsn.insn, it must check the _second_ byte. But current resume_execution check _first_ byte again. I changed it checks second byte of p->ainsn.insn. Kprobes on i386 don't have this problem, because the implementation is a little bit different from x86_64. Cc: Andi Kleen Signed-off-by: Satoshi Oshima Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/kprobes.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index 1eaa5dae6174ff..fa1d19ca700ae8 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c @@ -514,13 +514,13 @@ static void __kprobes resume_execution(struct kprobe *p, *tos = orig_rip + (*tos - copy_rip); break; case 0xff: - if ((*insn & 0x30) == 0x10) { + if ((insn[1] & 0x30) == 0x10) { /* call absolute, indirect */ /* Fix return addr; rip is correct. */ next_rip = regs->rip; *tos = orig_rip + (*tos - copy_rip); - } else if (((*insn & 0x31) == 0x20) || /* jmp near, absolute indirect */ - ((*insn & 0x31) == 0x21)) { /* jmp far, absolute indirect */ + } else if (((insn[1] & 0x31) == 0x20) || /* jmp near, absolute indirect */ + ((insn[1] & 0x31) == 0x21)) { /* jmp far, absolute indirect */ /* rip is correct. */ next_rip = regs->rip; } -- cgit 1.2.3-korg From 8b1ea24c6cc529f6860c458b1c0872f22e74c950 Mon Sep 17 00:00:00 2001 From: Rene Herman Date: Sat, 20 May 2006 15:00:22 -0700 Subject: [PATCH] missing newline in scsi/st.c st: Version 20050830, fixed bufsize 32768, s/g segs 256 st 0:0:6:0: Attached scsi tape st0<4>st0: try direct i/o: yes (alignment 512 B) Cc: James Bottomley Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/scsi/st.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index d40e7c871c3632..56cb4900611659 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4054,7 +4054,7 @@ static int st_probe(struct device *dev) } sdev_printk(KERN_WARNING, SDp, - "Attached scsi tape %s", tape_name(tpnt)); + "Attached scsi tape %s\n", tape_name(tpnt)); printk(KERN_WARNING "%s: try direct i/o: %s (alignment %d B)\n", tape_name(tpnt), tpnt->try_dio ? "yes" : "no", queue_dma_alignment(SDp->request_queue) + 1); -- cgit 1.2.3-korg From 0662b71322e211dba9a4bc0e6fbca7861a2b5a7d Mon Sep 17 00:00:00 2001 From: Zachary Amsden Date: Sat, 20 May 2006 15:00:24 -0700 Subject: [PATCH] Fix a NO_IDLE_HZ timer bug Under certain timing conditions, a race during boot occurs where timer ticks are being processed on remote CPUs. The remote timer ticks can increment jiffies, and if this happens during a window when a timeout is very close to expiring but a local tick has not yet been delivered, you can end up with 1) No softirq pending 2) A local timer wheel which is not synced to jiffies 3) No high resolution timer active 4) A local timer which is supposed to fire before the current jiffies value. In this circumstance, the comparison in next_timer_interrupt overflows, because the base of the comparison for high resolution timers is jiffies, but for the softirq timer wheel, it is relative the the current base of the wheel (jiffies_base). Signed-off-by: Zachary Amsden Cc: Martin Schwidefsky Cc: Oleg Nesterov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/timer.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/kernel/timer.c b/kernel/timer.c index 67eaf0f54096f8..9e49deed468cd8 100644 --- a/kernel/timer.c +++ b/kernel/timer.c @@ -541,6 +541,22 @@ found: } spin_unlock(&base->lock); + /* + * It can happen that other CPUs service timer IRQs and increment + * jiffies, but we have not yet got a local timer tick to process + * the timer wheels. In that case, the expiry time can be before + * jiffies, but since the high-resolution timer here is relative to + * jiffies, the default expression when high-resolution timers are + * not active, + * + * time_before(MAX_JIFFY_OFFSET + jiffies, expires) + * + * would falsely evaluate to true. If that is the case, just + * return jiffies so that we can immediately fire the local timer + */ + if (time_before(expires, jiffies)) + return jiffies; + if (time_before(hr_expires, expires)) return hr_expires; -- cgit 1.2.3-korg From 92f63cd000059366af18712367216d96180e0ec0 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Sat, 20 May 2006 15:00:25 -0700 Subject: [PATCH] s390: next_timer_interrupt overflow in stop_hz_timer The 32 bit unsigned substraction (next - jiffies) in stop_hz_timer can overflow if jiffies gets advanced between next_timer_interrupt and the read under the xtime lock. The cast to a u64 then results in a large value which causes the cpu to wait too long. Fix this by casting next and jiffies independently to u64 before subtracting them. (Spotted by Zachary Amsden ) Signed-off-by: Martin Schwidefsky Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/s390/kernel/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 029f09901b851f..ce19ad4e92ec26 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 - jiffies) + jiffies_64; + timer = (__u64 next) - (__u64 jiffies) + jiffies_64; } while (read_seqretry_irqrestore(&xtime_lock, seq, flags)); todval = -1ULL; /* Be careful about overflows. */ -- cgit 1.2.3-korg From 2c1a51f39d9551a514d7a089d01c23c0c3a54ab8 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 20 May 2006 15:00:26 -0700 Subject: [PATCH] kbuild: check SHT_REL sections I found that modpost can not detect section mismatch on mips and i386. On mips64, the modpost (with r_info layout fix) can detect it. The current modpst only checks SHT_RELA section but I suppose SHT_REL section should be checked also. This patch does not contain r_info layout fix. I'll post an updated r_info layout fix on next mail. Check SHT_REL sections as like as SHT_RELA sections to detect section mismatch. Signed-off-by: Atsushi Nemoto Cc: Sam Ravnborg Cc: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/mod/modpost.c | 65 ++++++++++++++++++++++++++++++++++++--------------- scripts/mod/modpost.h | 2 ++ 2 files changed, 48 insertions(+), 19 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 6d04504b2fc111..1aa52a86c2cfa1 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -697,29 +697,56 @@ static void check_sec_ref(struct module *mod, const char *modname, /* Walk through all sections */ for (i = 0; i < hdr->e_shnum; i++) { - Elf_Rela *rela; - Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; - Elf_Rela *stop = (void*)start + sechdrs[i].sh_size; - const char *name = secstrings + sechdrs[i].sh_name + - strlen(".rela"); + const char *name = secstrings + sechdrs[i].sh_name; + const char *secname; + Elf_Rela r; /* We want to process only relocation sections and not .init */ - if (section_ref_ok(name) || (sechdrs[i].sh_type != SHT_RELA)) - continue; + if (sechdrs[i].sh_type == SHT_RELA) { + Elf_Rela *rela; + Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; + Elf_Rela *stop = (void*)start + sechdrs[i].sh_size; + name += strlen(".rela"); + if (section_ref_ok(name)) + continue; - for (rela = start; rela < stop; rela++) { - Elf_Rela r; - const char *secname; - r.r_offset = TO_NATIVE(rela->r_offset); - r.r_info = TO_NATIVE(rela->r_info); - r.r_addend = TO_NATIVE(rela->r_addend); - sym = elf->symtab_start + ELF_R_SYM(r.r_info); - /* Skip special sections */ - if (sym->st_shndx >= SHN_LORESERVE) + for (rela = start; rela < stop; rela++) { + r.r_offset = TO_NATIVE(rela->r_offset); + r.r_info = TO_NATIVE(rela->r_info); + r.r_addend = TO_NATIVE(rela->r_addend); + sym = elf->symtab_start + ELF_R_SYM(r.r_info); + /* Skip special sections */ + if (sym->st_shndx >= SHN_LORESERVE) + continue; + + secname = secstrings + + sechdrs[sym->st_shndx].sh_name; + if (section(secname)) + warn_sec_mismatch(modname, name, + elf, sym, r); + } + } else if (sechdrs[i].sh_type == SHT_REL) { + Elf_Rel *rel; + Elf_Rel *start = (void *)hdr + sechdrs[i].sh_offset; + Elf_Rel *stop = (void*)start + sechdrs[i].sh_size; + name += strlen(".rel"); + if (section_ref_ok(name)) continue; - secname = secstrings + sechdrs[sym->st_shndx].sh_name; - if (section(secname)) - warn_sec_mismatch(modname, name, elf, sym, r); + for (rel = start; rel < stop; rel++) { + r.r_offset = TO_NATIVE(rel->r_offset); + r.r_info = TO_NATIVE(rel->r_info); + r.r_addend = 0; + sym = elf->symtab_start + ELF_R_SYM(r.r_info); + /* Skip special sections */ + if (sym->st_shndx >= SHN_LORESERVE) + continue; + + secname = secstrings + + sechdrs[sym->st_shndx].sh_name; + if (section(secname)) + warn_sec_mismatch(modname, name, + elf, sym, r); + } } } } diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index b14255c72a375e..086fa466504c7f 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -21,6 +21,7 @@ #define ELF_ST_BIND ELF32_ST_BIND #define ELF_ST_TYPE ELF32_ST_TYPE +#define Elf_Rel Elf32_Rel #define Elf_Rela Elf32_Rela #define ELF_R_SYM ELF32_R_SYM #define ELF_R_TYPE ELF32_R_TYPE @@ -34,6 +35,7 @@ #define ELF_ST_BIND ELF64_ST_BIND #define ELF_ST_TYPE ELF64_ST_TYPE +#define Elf_Rel Elf64_Rel #define Elf_Rela Elf64_Rela #define ELF_R_SYM ELF64_R_SYM #define ELF_R_TYPE ELF64_R_TYPE -- cgit 1.2.3-korg From eae07ac607f317ee6781983d3f9d8f77ef144b45 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Sat, 20 May 2006 15:00:28 -0700 Subject: [PATCH] kbuild: fix modpost segfault for 64bit mipsel kernel Here is an updated r_info layout fix. Please apply "check SHT_REL sections" patch before this. 64bit mips has different r_info layout. This patch fixes modpost segfault for 64bit little endian mips kernel. Signed-off-by: Atsushi Nemoto Cc: Sam Ravnborg Cc: Ralf Baechle Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/mod/modpost.c | 31 +++++++++++++++++++++++++++---- scripts/mod/modpost.h | 21 +++++++++++++++++++-- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 1aa52a86c2cfa1..d0f86ed43f7a17 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c @@ -700,6 +700,7 @@ static void check_sec_ref(struct module *mod, const char *modname, const char *name = secstrings + sechdrs[i].sh_name; const char *secname; Elf_Rela r; + unsigned int r_sym; /* We want to process only relocation sections and not .init */ if (sechdrs[i].sh_type == SHT_RELA) { Elf_Rela *rela; @@ -711,9 +712,20 @@ static void check_sec_ref(struct module *mod, const char *modname, for (rela = start; rela < stop; rela++) { r.r_offset = TO_NATIVE(rela->r_offset); - r.r_info = TO_NATIVE(rela->r_info); +#if KERNEL_ELFCLASS == ELFCLASS64 + if (hdr->e_machine == EM_MIPS) { + r_sym = ELF64_MIPS_R_SYM(rela->r_info); + r_sym = TO_NATIVE(r_sym); + } else { + r.r_info = TO_NATIVE(rela->r_info); + r_sym = ELF_R_SYM(r.r_info); + } +#else + r.r_info = TO_NATIVE(rela->r_info); + r_sym = ELF_R_SYM(r.r_info); +#endif r.r_addend = TO_NATIVE(rela->r_addend); - sym = elf->symtab_start + ELF_R_SYM(r.r_info); + sym = elf->symtab_start + r_sym; /* Skip special sections */ if (sym->st_shndx >= SHN_LORESERVE) continue; @@ -734,9 +746,20 @@ static void check_sec_ref(struct module *mod, const char *modname, for (rel = start; rel < stop; rel++) { r.r_offset = TO_NATIVE(rel->r_offset); - r.r_info = TO_NATIVE(rel->r_info); +#if KERNEL_ELFCLASS == ELFCLASS64 + if (hdr->e_machine == EM_MIPS) { + r_sym = ELF64_MIPS_R_SYM(rel->r_info); + r_sym = TO_NATIVE(r_sym); + } else { + r.r_info = TO_NATIVE(rel->r_info); + r_sym = ELF_R_SYM(r.r_info); + } +#else + r.r_info = TO_NATIVE(rel->r_info); + r_sym = ELF_R_SYM(r.r_info); +#endif r.r_addend = 0; - sym = elf->symtab_start + ELF_R_SYM(r.r_info); + sym = elf->symtab_start + r_sym; /* Skip special sections */ if (sym->st_shndx >= SHN_LORESERVE) continue; diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 086fa466504c7f..861d866fcd8394 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h @@ -41,6 +41,25 @@ #define ELF_R_TYPE ELF64_R_TYPE #endif +/* The 64-bit MIPS ELF ABI uses an unusual reloc format. */ +typedef struct +{ + Elf32_Word r_sym; /* Symbol index */ + unsigned char r_ssym; /* Special symbol for 2nd relocation */ + unsigned char r_type3; /* 3rd relocation type */ + unsigned char r_type2; /* 2nd relocation type */ + unsigned char r_type1; /* 1st relocation type */ +} _Elf64_Mips_R_Info; + +typedef union +{ + Elf64_Xword r_info_number; + _Elf64_Mips_R_Info r_info_fields; +} _Elf64_Mips_R_Info_union; + +#define ELF64_MIPS_R_SYM(i) \ + ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) + #if KERNEL_ELFDATA != HOST_ELFDATA static inline void __endian(const void *src, void *dest, unsigned int size) @@ -50,8 +69,6 @@ static inline void __endian(const void *src, void *dest, unsigned int size) ((unsigned char*)dest)[i] = ((unsigned char*)src)[size - i-1]; } - - #define TO_NATIVE(x) \ ({ \ typeof(x) __x; \ -- cgit 1.2.3-korg From b3969e5831adac133b286600e74214e1ae42ec05 Mon Sep 17 00:00:00 2001 From: Alessandro Zummo Date: Sat, 20 May 2006 15:00:29 -0700 Subject: [PATCH] rtc subsystem: use ENOIOCTLCMD and ENOTTY where appropriate Appropriately use -ENOIOCTLCMD and -ENOTTY when the ioctl is not implemented by a driver. (akpm: we're not allowed to return -ENOIOCTLCMD to userspace. This patch does the right thing). Signed-off-by: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-dev.c | 6 +++--- drivers/rtc/rtc-sa1100.c | 2 +- drivers/rtc/rtc-test.c | 2 +- drivers/rtc/rtc-vr41xx.c | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 6c9ad92747fddd..2011567005f99a 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -141,13 +141,13 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, /* try the driver's ioctl interface */ if (ops->ioctl) { err = ops->ioctl(class_dev->dev, cmd, arg); - if (err != -EINVAL) + if (err != -ENOIOCTLCMD) return err; } /* if the driver does not provide the ioctl interface * or if that particular ioctl was not implemented - * (-EINVAL), we will try to emulate here. + * (-ENOIOCTLCMD), we will try to emulate here. */ switch (cmd) { @@ -233,7 +233,7 @@ static int rtc_dev_ioctl(struct inode *inode, struct file *file, break; default: - err = -EINVAL; + err = -ENOTTY; break; } diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c index 2bc8aad4721918..a997529f8926e2 100644 --- a/drivers/rtc/rtc-sa1100.c +++ b/drivers/rtc/rtc-sa1100.c @@ -247,7 +247,7 @@ static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd, rtc_freq = arg; return 0; } - return -EINVAL; + return -ENOIOCTLCMD; } static int sa1100_rtc_read_time(struct device *dev, struct rtc_time *tm) diff --git a/drivers/rtc/rtc-test.c b/drivers/rtc/rtc-test.c index e1f7e8e86daffe..e1fa5fe7901f90 100644 --- a/drivers/rtc/rtc-test.c +++ b/drivers/rtc/rtc-test.c @@ -71,7 +71,7 @@ static int test_rtc_ioctl(struct device *dev, unsigned int cmd, return 0; default: - return -EINVAL; + return -ENOIOCTLCMD; } } diff --git a/drivers/rtc/rtc-vr41xx.c b/drivers/rtc/rtc-vr41xx.c index 4d49fd501198fe..277596c302e304 100644 --- a/drivers/rtc/rtc-vr41xx.c +++ b/drivers/rtc/rtc-vr41xx.c @@ -270,7 +270,7 @@ static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long epoch = arg; break; default: - return -EINVAL; + return -ENOIOCTLCMD; } return 0; -- cgit 1.2.3-korg From ae57a856429dd932c547530df1b234eb7e642297 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 20 May 2006 15:00:30 -0700 Subject: [PATCH] kobject: quiet errors in kobject_add People don't like released kernels yelling at them, no matter how real the error might be. So only report it if CONFIG_KOBJECT_DEBUG is enabled. Sent on request of Andrew Morton. (akpm: should bring this back post-2.6.17) Signed-off-by: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/kobject.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/kobject.c b/lib/kobject.c index b46350c278370b..687ab418d292b1 100644 --- a/lib/kobject.c +++ b/lib/kobject.c @@ -198,14 +198,14 @@ int kobject_add(struct kobject * kobj) /* be noisy on error issues */ if (error == -EEXIST) - printk("kobject_add failed for %s with -EEXIST, " + pr_debug("kobject_add failed for %s with -EEXIST, " "don't try to register things with the " "same name in the same directory.\n", kobject_name(kobj)); else - printk("kobject_add failed for %s (%d)\n", + pr_debug("kobject_add failed for %s (%d)\n", kobject_name(kobj), error); - dump_stack(); + /* dump_stack(); */ } return error; -- cgit 1.2.3-korg From e984bb43f7450312ba66fe0e67a99efa6be3b246 Mon Sep 17 00:00:00 2001 From: Bob Picco Date: Sat, 20 May 2006 15:00:31 -0700 Subject: [PATCH] Align the node_mem_map endpoints to a MAX_ORDER boundary Andy added code to buddy allocator which does not require the zone's endpoints to be aligned to MAX_ORDER. An issue is that the buddy allocator requires the node_mem_map's endpoints to be MAX_ORDER aligned. Otherwise __page_find_buddy could compute a buddy not in node_mem_map for partial MAX_ORDER regions at zone's endpoints. page_is_buddy will detect that these pages at endpoints are not PG_buddy (they were zeroed out by bootmem allocator and not part of zone). Of course the negative here is we could waste a little memory but the positive is eliminating all the old checks for zone boundary conditions. SPARSEMEM won't encounter this issue because of MAX_ORDER size constraint when SPARSEMEM is configured. ia64 VIRTUAL_MEM_MAP doesn't need the logic either because the holes and endpoints are handled differently. This leaves checking alloc_remap and other arches which privately allocate for node_mem_map. Signed-off-by: Bob Picco Acked-by: Mel Gorman Cc: Dave Hansen Cc: Andy Whitcroft Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/mmzone.h | 1 + mm/page_alloc.c | 14 +++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index b5c21122c2996b..36740354d4db47 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -22,6 +22,7 @@ #else #define MAX_ORDER CONFIG_FORCE_MAX_ZONEORDER #endif +#define MAX_ORDER_NR_PAGES (1 << (MAX_ORDER - 1)) struct free_area { struct list_head free_list; diff --git a/mm/page_alloc.c b/mm/page_alloc.c index bb3416932ab03d..253a450c400df0 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -2125,14 +2125,22 @@ static void __init alloc_node_mem_map(struct pglist_data *pgdat) #ifdef CONFIG_FLAT_NODE_MEM_MAP /* ia64 gets its own node_mem_map, before this, without bootmem */ if (!pgdat->node_mem_map) { - unsigned long size; + unsigned long size, start, end; struct page *map; - size = (pgdat->node_spanned_pages + 1) * sizeof(struct page); + /* + * The zone's endpoints aren't required to be MAX_ORDER + * aligned but the node_mem_map endpoints must be in order + * for the buddy allocator to function correctly. + */ + start = pgdat->node_start_pfn & ~(MAX_ORDER_NR_PAGES - 1); + end = pgdat->node_start_pfn + pgdat->node_spanned_pages; + end = ALIGN(end, MAX_ORDER_NR_PAGES); + size = (end - start) * sizeof(struct page); map = alloc_remap(pgdat->node_id, size); if (!map) map = alloc_bootmem_node(pgdat, size); - pgdat->node_mem_map = map; + pgdat->node_mem_map = map + (pgdat->node_start_pfn - start); } #ifdef CONFIG_FLATMEM /* -- cgit 1.2.3-korg From 9781b8b055bd0a02a043ed80fb8d59d703a49daf Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 20 May 2006 15:00:32 -0700 Subject: [PATCH] pd6729 section fix WARNING: drivers/pcmcia/pd6729.o - Section mismatch: reference to .init.text: from .text between 'pd6729_pci_probe' (at offset 0x9a8) and 'pd6729_pci_remove' Cc: Dominik Brodowski Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/pcmcia/pd6729.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c index 16d1ea7b0a18ae..247ab837f84173 100644 --- a/drivers/pcmcia/pd6729.c +++ b/drivers/pcmcia/pd6729.c @@ -589,7 +589,7 @@ static int pd6729_check_irq(int irq, int flags) return 0; } -static u_int __init pd6729_isa_scan(void) +static u_int __devinit pd6729_isa_scan(void) { u_int mask0, mask = 0; int i; -- cgit 1.2.3-korg From 9e8a3d229b23c34adb9c20cc2875fc67dce12585 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 20 May 2006 15:00:33 -0700 Subject: [PATCH] i810 section fix WARNING: drivers/video/i810/i810fb.o - Section mismatch: reference to .init.data: from .text between 'i810_fix_offsets' (at offset 0x1b88) and 'i810_alloc_agp_mem' WARNING: drivers/video/i810/i810fb.o - Section mismatch: reference to .init.data: from .text between 'i810_fix_offsets' (at offset 0x1b8f) and 'i810_alloc_agp_mem' WARNING: drivers/video/i810/i810fb.o - Section mismatch: reference to .init.data: from .text between 'i810_fix_offsets' (at offset 0x1ba3) and 'i810_alloc_agp_mem' WARNING: drivers/video/i810/i810fb.o - Section mismatch: reference to .init.data: from .text between 'i810_fix_offsets' (at offset 0x1bb5) and 'i810_alloc_agp_mem' WARNING: drivers/video/i810/i810fb.o - Section mismatch: reference to .init.data: from .text between 'i810_fix_offsets' (at offset 0x1bc6) and 'i810_alloc_agp_mem' WARNING: drivers/video/i810/i810fb.o - Section mismatch: reference to .init.data: from .text between 'i810_init_defaults' (at offset 0x1dd8) and 'i810_init_device' WARNING: drivers/video/i810/i810fb.o - Section mismatch: reference to .init.data: from .text between 'i810_init_defaults' (at offset 0x1dfb) and 'i810_init_device' Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/i810/i810_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index 788297e9d59e16..44aa2ffff973e5 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -76,8 +76,8 @@ * * Experiment with v_offset to find out which works best for you. */ -static u32 v_offset_default __initdata; /* For 32 MiB Aper size, 8 should be the default */ -static u32 voffset __initdata = 0; +static u32 v_offset_default __devinitdata; /* For 32 MiB Aper size, 8 should be the default */ +static u32 voffset __devinitdata; static int i810fb_cursor(struct fb_info *info, struct fb_cursor *cursor); static int __devinit i810fb_init_pci (struct pci_dev *dev, -- cgit 1.2.3-korg From fad43488b8c9b3914fcdc48ee3b8d30aeb49fa30 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 20 May 2006 15:00:34 -0700 Subject: [PATCH] mpu401 section fix WARNING: sound/drivers/mpu401/snd-mpu401.o - Section mismatch: reference to .init.text: from .text between 'snd_mpu401_pnp_probe' (at offset 0x1f7) and 'snd_mpu401_pnp_remove' Cc: Jaroslav Kysela Cc: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- sound/drivers/mpu401/mpu401.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c index da7ef26995c3d9..77b06009735df8 100644 --- a/sound/drivers/mpu401/mpu401.c +++ b/sound/drivers/mpu401/mpu401.c @@ -151,7 +151,7 @@ static struct pnp_device_id snd_mpu401_pnpids[] = { MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids); -static int __init snd_mpu401_pnp(int dev, struct pnp_dev *device, +static int __devinit snd_mpu401_pnp(int dev, struct pnp_dev *device, const struct pnp_device_id *id) { if (!pnp_port_valid(device, 0) || -- cgit 1.2.3-korg From 1caef6aa97a3a43a82f238d8b31bf177de34a4bf Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 20 May 2006 15:00:35 -0700 Subject: [PATCH] es18xx build fix sound/isa/es18xx.c: In function `snd_es18xx_identify': sound/isa/es18xx.c:1606: warning: implicit declaration of function `udelay' Cc: Jaroslav Kysela Cc: Takashi Iwai Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- sound/isa/es18xx.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c index a36ec1daa5cb9e..e6945db8ed1b8a 100644 --- a/sound/isa/es18xx.c +++ b/sound/isa/es18xx.c @@ -85,6 +85,8 @@ #include #include #include +#include + #include #include #include -- cgit 1.2.3-korg From db31419404e5ccc7e8e07000a5f1ac440a0eafa0 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 20 May 2006 15:00:35 -0700 Subject: [PATCH] nm256_audio section fix WARNING: sound/oss/nm256_audio.o - Section mismatch: reference to .init.text:nm256_peek_for_sig from .text between 'nm256_install' (at offset 0x3ba4) and 'nm256_probe' WARNING: sound/oss/nm256_audio.o - Section mismatch: reference to .init.text:nm256_peek_for_sig from .text between 'nm256_install' (at offset 0x3bac) and 'nm256_probe' WARNING: sound/oss/nm256_audio.o - Section mismatch: reference to .init.text: from .text between 'nm256_install' (at offset 0x3dcc) and 'nm256_probe' WARNING: sound/oss/nm256_audio.o - Section mismatch: reference to .init.text: from .text between 'nm256_install' (at offset 0x3dd0) and 'nm256_probe' Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- sound/oss/nm256_audio.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/oss/nm256_audio.c b/sound/oss/nm256_audio.c index 7de079b202f214..6e662ac009ae5f 100644 --- a/sound/oss/nm256_audio.c +++ b/sound/oss/nm256_audio.c @@ -960,7 +960,7 @@ static struct ac97_mixer_value_list mixer_defaults[] = { /* Installs the AC97 mixer into CARD. */ -static int __init +static int __devinit nm256_install_mixer (struct nm256_info *card) { int mixer; @@ -995,7 +995,7 @@ nm256_install_mixer (struct nm256_info *card) * RAM. */ -static void __init +static void __devinit nm256_peek_for_sig (struct nm256_info *card) { u32 port1offset @@ -1056,7 +1056,7 @@ nm256_install(struct pci_dev *pcidev, enum nm256rev rev, char *verstr) card->playing = 0; card->recording = 0; card->rev = rev; - spin_lock_init(&card->lock); + spin_lock_init(&card->lock); /* Init the memory port info. */ for (x = 0; x < 2; x++) { -- cgit 1.2.3-korg From b307e8548921c686d2eb948ca418ab2941876daa Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sat, 20 May 2006 15:00:36 -0700 Subject: [PATCH] ad1848 section fix WARNING: sound/oss/ad1848.o - Section mismatch: reference to .init.data:ad1848_isapnp_list from .text between 'ad1848_init_generic' (at offset 0x46f0) and 'kmalloc' WARNING: sound/oss/ad1848.o - Section mismatch: reference to .init.data:ad1848_isapnp_list from .text between 'ad1848_init_generic' (at offset 0x46f8) and 'kmalloc' WARNING: sound/oss/ad1848.o - Section mismatch: reference to .init.data:ad1848_isapnp_list from .text between 'ad1848_init_generic' (at offset 0x4818) and 'kmalloc' Also, sound/oss/ad1848.c: In function `ad1848_init': sound/oss/ad1848.c:2029: warning: cast to pointer from integer of different size sound/oss/ad1848.c: In function `ad1848_unload': sound/oss/ad1848.c:2178: warning: cast to pointer from integer of different size sound/oss/ad1848.c: In function `adintr': sound/oss/ad1848.c:2207: warning: cast from pointer to integer of different size Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- sound/oss/ad1848.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c index 49796be955f32c..e04fa49b0dc8e5 100644 --- a/sound/oss/ad1848.c +++ b/sound/oss/ad1848.c @@ -2026,7 +2026,8 @@ int ad1848_init (char *name, struct resource *ports, int irq, int dma_playback, if (irq > 0) { devc->dev_no = my_dev; - if (request_irq(devc->irq, adintr, 0, devc->name, (void *)my_dev) < 0) + if (request_irq(devc->irq, adintr, 0, devc->name, + (void *)(long)my_dev) < 0) { printk(KERN_WARNING "ad1848: Unable to allocate IRQ\n"); /* Don't free it either then.. */ @@ -2175,7 +2176,7 @@ void ad1848_unload(int io_base, int irq, int dma_playback, int dma_capture, int if (!share_dma) { if (devc->irq > 0) /* There is no point in freeing irq, if it wasn't allocated */ - free_irq(devc->irq, (void *)devc->dev_no); + free_irq(devc->irq, (void *)(long)devc->dev_no); sound_free_dma(dma_playback); @@ -2204,7 +2205,7 @@ irqreturn_t adintr(int irq, void *dev_id, struct pt_regs *dummy) unsigned char c930_stat = 0; int cnt = 0; - dev = (int)dev_id; + dev = (long)dev_id; devc = (ad1848_info *) audio_devs[dev]->devc; interrupt_again: /* Jump back here if int status doesn't reset */ @@ -2900,7 +2901,8 @@ static struct pnp_dev *activate_dev(char *devname, char *resname, struct pnp_dev return(dev); } -static struct pnp_dev *ad1848_init_generic(struct pnp_card *bus, struct address_info *hw_config, int slot) +static struct pnp_dev __init *ad1848_init_generic(struct pnp_card *bus, + struct address_info *hw_config, int slot) { /* Configure Audio device */ -- cgit 1.2.3-korg From f1adad78dd2fc8edaa513e0bde92b4c64340245c Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 21 May 2006 18:54:09 -0700 Subject: Revert "[PATCH] sched: fix interactive task starvation" This reverts commit 5ce74abe788a26698876e66b9c9ce7e7acc25413 (and its dependent commit 8a5bc075b8d8cf7a87b3f08fad2fba0f5d13295e), because of audio underruns. Reported by Rene Herman , who also pinpointed the exact cause of the underruns: "Audio underruns galore, with only ogg123 and firefox (browsing the GIT tree online is also a nice trigger by the way). If I back it out, everything is fine for me again." Cc: Rene Herman Cc: Mike Galbraith Acked-by: Con Kolivas Signed-off-by: Linus Torvalds --- kernel/sched.c | 62 +++++++++++++++++----------------------------------------- 1 file changed, 18 insertions(+), 44 deletions(-) diff --git a/kernel/sched.c b/kernel/sched.c index 4c64f85698aee2..c13f1bd2df7d3c 100644 --- a/kernel/sched.c +++ b/kernel/sched.c @@ -664,48 +664,6 @@ static int effective_prio(task_t *p) return prio; } -/* - * We place interactive tasks back into the active array, if possible. - * - * To guarantee that this does not starve expired tasks we ignore the - * interactivity of a task if the first expired task had to wait more - * than a 'reasonable' amount of time. This deadline timeout is - * load-dependent, as the frequency of array switched decreases with - * increasing number of running tasks. We also ignore the interactivity - * if a better static_prio task has expired, and switch periodically - * regardless, to ensure that highly interactive tasks do not starve - * the less fortunate for unreasonably long periods. - */ -static inline int expired_starving(runqueue_t *rq) -{ - int limit; - - /* - * Arrays were recently switched, all is well - */ - if (!rq->expired_timestamp) - return 0; - - limit = STARVATION_LIMIT * rq->nr_running; - - /* - * It's time to switch arrays - */ - if (jiffies - rq->expired_timestamp >= limit) - return 1; - - /* - * There's a better selection in the expired array - */ - if (rq->curr->static_prio > rq->best_expired_prio) - return 1; - - /* - * All is well - */ - return 0; -} - /* * __activate_task - move a task to the runqueue. */ @@ -713,7 +671,7 @@ static void __activate_task(task_t *p, runqueue_t *rq) { prio_array_t *target = rq->active; - if (unlikely(batch_task(p) || (expired_starving(rq) && !rt_task(p)))) + if (batch_task(p)) target = rq->expired; enqueue_task(p, target); rq->nr_running++; @@ -2531,6 +2489,22 @@ unsigned long long current_sched_time(const task_t *tsk) return ns; } +/* + * We place interactive tasks back into the active array, if possible. + * + * To guarantee that this does not starve expired tasks we ignore the + * interactivity of a task if the first expired task had to wait more + * than a 'reasonable' amount of time. This deadline timeout is + * load-dependent, as the frequency of array switched decreases with + * increasing number of running tasks. We also ignore the interactivity + * if a better static_prio task has expired: + */ +#define EXPIRED_STARVING(rq) \ + ((STARVATION_LIMIT && ((rq)->expired_timestamp && \ + (jiffies - (rq)->expired_timestamp >= \ + STARVATION_LIMIT * ((rq)->nr_running) + 1))) || \ + ((rq)->curr->static_prio > (rq)->best_expired_prio)) + /* * Account user cpu time to a process. * @p: the process that the cpu time gets accounted to @@ -2666,7 +2640,7 @@ void scheduler_tick(void) if (!rq->expired_timestamp) rq->expired_timestamp = jiffies; - if (!TASK_INTERACTIVE(p) || expired_starving(rq)) { + if (!TASK_INTERACTIVE(p) || EXPIRED_STARVING(rq)) { enqueue_task(p, rq->expired); if (p->static_prio < rq->best_expired_prio) rq->best_expired_prio = p->static_prio; -- cgit 1.2.3-korg From 9a2a9bb2010ed7e56547e2bb2041dab14ab0510a Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 15 May 2006 14:10:11 -0700 Subject: [SUNSU]: Fix license. FATAL: modpost: GPL-incompatible module sunsu uses the GPL-only symbol tty_insert_flip_string_flags Signed-off-by: Andrew Morton Signed-off-by: David S. Miller --- drivers/serial/sunsu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index 1c4396c2962d0d..2b4f96541b8e6a 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c @@ -1730,3 +1730,4 @@ static void __exit sunsu_exit(void) module_init(sunsu_probe); module_exit(sunsu_exit); +MODULE_LICENSE("GPL"); -- cgit 1.2.3-korg From 353b28bafd1b962359a866ff263a7fad833d29a1 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 21 May 2006 21:22:53 -0700 Subject: [SPARC]: Add robust futex syscall entries. Signed-off-by: David S. Miller --- arch/sparc/kernel/systbls.S | 3 ++- arch/sparc64/kernel/systbls.S | 8 +++++--- include/asm-sparc/unistd.h | 8 +++++--- include/asm-sparc64/unistd.h | 8 +++++--- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index 6e1135cc03b08a..2856551bddf1b7 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -79,6 +79,7 @@ sys_call_table: /*285*/ .long sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64 /*290*/ .long sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat /*295*/ .long sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare +/*300*/ .long sys_set_robust_list, sys_get_robust_list #ifdef CONFIG_SUNOS_EMUL /* Now the SunOS syscall table. */ @@ -190,6 +191,6 @@ sunos_sys_table: /*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys, sunos_nosys, sunos_nosys .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys + .long sunos_nosys, sunos_nosys, sunos_nosys #endif diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index d4b39cd3031004..1136fc465e3755 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -78,8 +78,9 @@ sys_call_table32: .word compat_sys_mq_timedsend, compat_sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid /*280*/ .word sys32_tee, sys_add_key, sys_request_key, sys_keyctl, compat_sys_openat .word sys_mkdirat, sys_mknodat, sys_fchownat, compat_sys_futimesat, compat_sys_fstatat64 -/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat +/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat .word sys_fchmodat, sys_faccessat, compat_sys_pselect6, compat_sys_ppoll, sys_unshare +/*300*/ .word compat_sys_set_robust_list, compat_sys_get_robust_list #endif /* CONFIG_COMPAT */ @@ -147,8 +148,9 @@ sys_call_table: .word sys_mq_timedsend, sys_mq_timedreceive, sys_mq_notify, sys_mq_getsetattr, sys_waitid /*280*/ .word sys_tee, sys_add_key, sys_request_key, sys_keyctl, sys_openat .word sys_mkdirat, sys_mknodat, sys_fchownat, sys_futimesat, sys_fstatat64 -/*285*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat +/*290*/ .word sys_unlinkat, sys_renameat, sys_linkat, sys_symlinkat, sys_readlinkat .word sys_fchmodat, sys_faccessat, sys_pselect6, sys_ppoll, sys_unshare +/*300*/ .word sys_set_robust_list, sys_get_robust_list #if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ defined(CONFIG_SOLARIS_EMUL_MODULE) @@ -261,5 +263,5 @@ sunos_sys_table: /*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys + .word sunos_nosys, sunos_nosys, sunos_nosys #endif diff --git a/include/asm-sparc/unistd.h b/include/asm-sparc/unistd.h index f5611a721fbd6e..45a576507785df 100644 --- a/include/asm-sparc/unistd.h +++ b/include/asm-sparc/unistd.h @@ -316,11 +316,13 @@ #define __NR_pselect6 297 #define __NR_ppoll 298 #define __NR_unshare 299 +#define __NR_set_robust_list 300 +#define __NR_get_robust_list 301 -/* WARNING: You MAY NOT add syscall numbers larger than 299, since +/* WARNING: You MAY NOT add syscall numbers larger than 301, since * all of the syscall tables in the Sparc kernel are - * sized to have 299 entries (starting at zero). Therefore - * find a free slot in the 0-299 range. + * sized to have 301 entries (starting at zero). Therefore + * find a free slot in the 0-301 range. */ #define _syscall0(type,name) \ diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h index 68705748bec0f1..998ef4ab0e068f 100644 --- a/include/asm-sparc64/unistd.h +++ b/include/asm-sparc64/unistd.h @@ -318,11 +318,13 @@ #define __NR_pselect6 297 #define __NR_ppoll 298 #define __NR_unshare 299 +#define __NR_set_robust_list 300 +#define __NR_get_robust_list 301 -/* WARNING: You MAY NOT add syscall numbers larger than 299, since +/* WARNING: You MAY NOT add syscall numbers larger than 301, since * all of the syscall tables in the Sparc kernel are - * sized to have 299 entries (starting at zero). Therefore - * find a free slot in the 0-299 range. + * sized to have 301 entries (starting at zero). Therefore + * find a free slot in the 0-301 range. */ #define _syscall0(type,name) \ -- cgit 1.2.3-korg From 463d305bc51b8f5d0750a17ec0c9caf5181ec6d4 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 22 May 2006 16:36:27 -0700 Subject: [TG3]: Add some missing rx error counters Add some missing rx error counters for 5705 and newer chips. Update version to 3.58. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e1b33a25a25f50..49ad60b726579e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -69,8 +69,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.57" -#define DRV_MODULE_RELDATE "Apr 28, 2006" +#define DRV_MODULE_VERSION "3.58" +#define DRV_MODULE_RELDATE "May 22, 2006" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 @@ -6488,6 +6488,10 @@ static void tg3_periodic_fetch_stats(struct tg3 *tp) TG3_STAT_ADD32(&sp->rx_frame_too_long_errors, MAC_RX_STATS_FRAME_TOO_LONG); TG3_STAT_ADD32(&sp->rx_jabbers, MAC_RX_STATS_JABBERS); TG3_STAT_ADD32(&sp->rx_undersize_packets, MAC_RX_STATS_UNDERSIZE); + + TG3_STAT_ADD32(&sp->rxbds_empty, RCVLPC_NO_RCV_BD_CNT); + TG3_STAT_ADD32(&sp->rx_discards, RCVLPC_IN_DISCARDS_CNT); + TG3_STAT_ADD32(&sp->rx_errors, RCVLPC_IN_ERRORS_CNT); } static void tg3_timer(unsigned long __opaque) -- cgit 1.2.3-korg From bae25761c92c5eec781b6ea72bbe7e98fc8382a0 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 22 May 2006 16:38:38 -0700 Subject: [BNX2]: Fix bug in bnx2_nvram_write() Fix a bug in bnx2_nvram_write() caused by a counter variable not correctly incremented by 4. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 5ca99e26660af7..509f104ec3dbd6 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3061,7 +3061,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, } /* Loop to write the new data from data_start to data_end */ - for (addr = data_start; addr < data_end; addr += 4, i++) { + for (addr = data_start; addr < data_end; addr += 4, i += 4) { if ((addr == page_end - 4) || ((bp->flash_info->buffered) && (addr == data_end - 4))) { -- cgit 1.2.3-korg From ae181bc44c65fdc93d0d2d908534b22e43f60f56 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Mon, 22 May 2006 16:39:20 -0700 Subject: [BNX2]: Use kmalloc instead of array Use kmalloc() instead of a local array in bnx2_nvram_write(). Update version to 1.4.40. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 509f104ec3dbd6..54161aef3cac0c 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -55,8 +55,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.4.39" -#define DRV_MODULE_RELDATE "March 22, 2006" +#define DRV_MODULE_VERSION "1.4.40" +#define DRV_MODULE_RELDATE "May 22, 2006" #define RUN_AT(x) (jiffies + (x)) @@ -2945,7 +2945,7 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, int buf_size) { u32 written, offset32, len32; - u8 *buf, start[4], end[4]; + u8 *buf, start[4], end[4], *flash_buffer = NULL; int rc = 0; int align_start, align_end; @@ -2985,12 +2985,19 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, memcpy(buf + align_start, data_buf, buf_size); } + if (bp->flash_info->buffered == 0) { + flash_buffer = kmalloc(264, GFP_KERNEL); + if (flash_buffer == NULL) { + rc = -ENOMEM; + goto nvram_write_end; + } + } + written = 0; while ((written < len32) && (rc == 0)) { u32 page_start, page_end, data_start, data_end; u32 addr, cmd_flags; int i; - u8 flash_buffer[264]; /* Find the page_start addr */ page_start = offset32 + written; @@ -3109,6 +3116,9 @@ bnx2_nvram_write(struct bnx2 *bp, u32 offset, u8 *data_buf, } nvram_write_end: + if (bp->flash_info->buffered == 0) + kfree(flash_buffer); + if (align_start || align_end) kfree(buf); return rc; -- cgit 1.2.3-korg From 4195f81453b9727f82bb8ceae03411b7fe52a994 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 22 May 2006 16:53:22 -0700 Subject: [NET]: Fix "ntohl(ntohs" bugs Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/ipv4/ipcomp.c | 2 +- net/ipv4/xfrm4_policy.c | 2 +- net/ipv6/ipcomp6.c | 2 +- net/xfrm/xfrm_input.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index cd810f41af1a71..95278b22b669ab 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c @@ -210,7 +210,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) skb->h.icmph->code != ICMP_FRAG_NEEDED) return; - spi = ntohl(ntohs(ipch->cpi)); + spi = htonl(ntohs(ipch->cpi)); x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET); if (!x) diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index f285bbf296e28d..8604c747bca5fa 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c @@ -221,7 +221,7 @@ _decode_session4(struct sk_buff *skb, struct flowi *fl) if (pskb_may_pull(skb, xprth + 4 - skb->data)) { u16 *ipcomp_hdr = (u16 *)xprth; - fl->fl_ipsec_spi = ntohl(ntohs(ipcomp_hdr[1])); + fl->fl_ipsec_spi = htonl(ntohs(ipcomp_hdr[1])); } break; default: diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 05eb67def39f17..48636436028ab2 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c @@ -208,7 +208,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, if (type != ICMPV6_DEST_UNREACH && type != ICMPV6_PKT_TOOBIG) return; - spi = ntohl(ntohs(ipcomph->cpi)); + spi = htonl(ntohs(ipcomph->cpi)); x = xfrm_state_lookup((xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); if (!x) return; diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index b54971059f1641..891a6090cc099d 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c @@ -62,7 +62,7 @@ int xfrm_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq) case IPPROTO_COMP: if (!pskb_may_pull(skb, sizeof(struct ip_comp_hdr))) return -EINVAL; - *spi = ntohl(ntohs(*(u16*)(skb->h.raw + 2))); + *spi = htonl(ntohs(*(u16*)(skb->h.raw + 2))); *seq = 0; return 0; default: -- cgit 1.2.3-korg From 405a42c5c8bd5731087c0ff01310731a3c1c9c24 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 22 May 2006 16:54:08 -0700 Subject: [IRDA]: fix 16/32 bit confusion Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- net/irda/iriap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/irda/iriap.c b/net/irda/iriap.c index 254f9074690011..2d2e2b1919f40f 100644 --- a/net/irda/iriap.c +++ b/net/irda/iriap.c @@ -544,7 +544,8 @@ static void iriap_getvaluebyclass_response(struct iriap_cb *self, { struct sk_buff *tx_skb; int n; - __u32 tmp_be32, tmp_be16; + __u32 tmp_be32; + __be16 tmp_be16; __u8 *fp; IRDA_DEBUG(4, "%s()\n", __FUNCTION__); -- cgit 1.2.3-korg From f5565f4a90bdfea99e4bcd8411ff5272ebdbdbf8 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Mon, 22 May 2006 16:54:30 -0700 Subject: [IRDA]: fixup type of ->lsap_state Signed-off-by: Alexey Dobriyan Signed-off-by: David S. Miller --- include/net/irda/irlmp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/irda/irlmp.h b/include/net/irda/irlmp.h index 86aefb1fda5e0b..c0c895d379ba1b 100644 --- a/include/net/irda/irlmp.h +++ b/include/net/irda/irlmp.h @@ -112,7 +112,7 @@ struct lsap_cb { struct timer_list watchdog_timer; - IRLMP_STATE lsap_state; /* Connection state */ + LSAP_STATE lsap_state; /* Connection state */ notify_t notify; /* Indication/Confirm entry points */ struct qos_info qos; /* QoS for this connection */ -- cgit 1.2.3-korg From f41d5bb1d9f49b03af7126d07a511facbe283a92 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Mon, 22 May 2006 16:55:14 -0700 Subject: [NETFILTER]: SNMP NAT: fix memory corruption Fix memory corruption caused by snmp_trap_decode: - When snmp_trap_decode fails before the id and address are allocated, the pointers contain random memory, but are freed by the caller (snmp_parse_mangle). - When snmp_trap_decode fails after allocating just the ID, it tries to free both address and ID, but the address pointer still contains random memory. The caller frees both ID and random memory again. - When snmp_trap_decode fails after allocating both, it frees both, and the callers frees both again. The corruption can be triggered remotely when the ip_nat_snmp_basic module is loaded and traffic on port 161 or 162 is NATed. Found by multiple testcases of the trap-app and trap-enc groups of the PROTOS c06-snmpv1 testsuite. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_nat_snmp_basic.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c index c622538455385d..688a2f29fadf67 100644 --- a/net/ipv4/netfilter/ip_nat_snmp_basic.c +++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c @@ -1003,12 +1003,12 @@ static unsigned char snmp_trap_decode(struct asn1_ctx *ctx, return 1; +err_addr_free: + kfree((unsigned long *)trap->ip_address); + err_id_free: kfree(trap->id); -err_addr_free: - kfree((unsigned long *)trap->ip_address); - return 0; } @@ -1126,11 +1126,10 @@ static int snmp_parse_mangle(unsigned char *msg, struct snmp_v1_trap trap; unsigned char ret = snmp_trap_decode(&ctx, &trap, map, check); - /* Discard trap allocations regardless */ - kfree(trap.id); - kfree((unsigned long *)trap.ip_address); - - if (!ret) + if (ret) { + kfree(trap.id); + kfree((unsigned long *)trap.ip_address); + } else return ret; } else { -- cgit 1.2.3-korg From 42f142371e48fbc44956d57b4e506bb6ce673cd7 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Tue, 23 May 2006 02:07:22 -0700 Subject: [SPARC64]: Respect gfp_t argument to dma_alloc_coherent(). Using asm-generic/dma-mapping.h does not work because pushing the call down to pci_alloc_coherent() causes the gfp_t argument of dma_alloc_coherent() to be ignored. Fix this by implementing things directly, and adding a gfp_t argument we can use in the internal call down to the PCI DMA implementation of pci_alloc_coherent(). This fixes massive memory corruption when using the sound driver layer, which passes things like __GFP_COMP down into these routines and (correctly) expects that to work. Signed-off-by: David S. Miller --- arch/sparc64/kernel/pci_iommu.c | 4 +- arch/sparc64/kernel/pci_sun4v.c | 4 +- include/asm-sparc64/dma-mapping.h | 141 +++++++++++++++++++++++++++++++++++++- include/asm-sparc64/pci.h | 4 +- 4 files changed, 146 insertions(+), 7 deletions(-) diff --git a/arch/sparc64/kernel/pci_iommu.c b/arch/sparc64/kernel/pci_iommu.c index 8efbc139769d22..82e5455134c677 100644 --- a/arch/sparc64/kernel/pci_iommu.c +++ b/arch/sparc64/kernel/pci_iommu.c @@ -218,7 +218,7 @@ static inline void iommu_free_ctx(struct pci_iommu *iommu, int ctx) * DMA for PCI device PDEV. Return non-NULL cpu-side address if * successful and set *DMA_ADDRP to the PCI side dma address. */ -static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp) +static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp) { struct pcidev_cookie *pcp; struct pci_iommu *iommu; @@ -232,7 +232,7 @@ static void *pci_4u_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr if (order >= 10) return NULL; - first_page = __get_free_pages(GFP_ATOMIC, order); + first_page = __get_free_pages(gfp, order); if (first_page == 0UL) return NULL; memset((char *)first_page, 0, PAGE_SIZE << order); diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index 9e94db2573a2f8..2b7a1f316a937e 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c @@ -154,7 +154,7 @@ static void pci_arena_free(struct pci_iommu_arena *arena, unsigned long base, un __clear_bit(i, arena->map); } -static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp) +static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr_t *dma_addrp, gfp_t gfp) { struct pcidev_cookie *pcp; struct pci_iommu *iommu; @@ -169,7 +169,7 @@ static void *pci_4v_alloc_consistent(struct pci_dev *pdev, size_t size, dma_addr npages = size >> IO_PAGE_SHIFT; - first_page = __get_free_pages(GFP_ATOMIC, order); + first_page = __get_free_pages(gfp, order); if (unlikely(first_page == 0UL)) return NULL; diff --git a/include/asm-sparc64/dma-mapping.h b/include/asm-sparc64/dma-mapping.h index c7d5804ba76df1..a8d39f23d43b77 100644 --- a/include/asm-sparc64/dma-mapping.h +++ b/include/asm-sparc64/dma-mapping.h @@ -4,7 +4,146 @@ #include #ifdef CONFIG_PCI -#include + +/* we implement the API below in terms of the existing PCI one, + * so include it */ +#include +/* need struct page definitions */ +#include + +static inline int +dma_supported(struct device *dev, u64 mask) +{ + BUG_ON(dev->bus != &pci_bus_type); + + return pci_dma_supported(to_pci_dev(dev), mask); +} + +static inline int +dma_set_mask(struct device *dev, u64 dma_mask) +{ + BUG_ON(dev->bus != &pci_bus_type); + + return pci_set_dma_mask(to_pci_dev(dev), dma_mask); +} + +static inline void * +dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, + gfp_t flag) +{ + BUG_ON(dev->bus != &pci_bus_type); + + return pci_iommu_ops->alloc_consistent(to_pci_dev(dev), size, dma_handle, flag); +} + +static inline void +dma_free_coherent(struct device *dev, size_t size, void *cpu_addr, + dma_addr_t dma_handle) +{ + BUG_ON(dev->bus != &pci_bus_type); + + pci_free_consistent(to_pci_dev(dev), size, cpu_addr, dma_handle); +} + +static inline dma_addr_t +dma_map_single(struct device *dev, void *cpu_addr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(dev->bus != &pci_bus_type); + + return pci_map_single(to_pci_dev(dev), cpu_addr, size, (int)direction); +} + +static inline void +dma_unmap_single(struct device *dev, dma_addr_t dma_addr, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(dev->bus != &pci_bus_type); + + pci_unmap_single(to_pci_dev(dev), dma_addr, size, (int)direction); +} + +static inline dma_addr_t +dma_map_page(struct device *dev, struct page *page, + unsigned long offset, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(dev->bus != &pci_bus_type); + + return pci_map_page(to_pci_dev(dev), page, offset, size, (int)direction); +} + +static inline void +dma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(dev->bus != &pci_bus_type); + + pci_unmap_page(to_pci_dev(dev), dma_address, size, (int)direction); +} + +static inline int +dma_map_sg(struct device *dev, struct scatterlist *sg, int nents, + enum dma_data_direction direction) +{ + BUG_ON(dev->bus != &pci_bus_type); + + return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); +} + +static inline void +dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nhwentries, + enum dma_data_direction direction) +{ + BUG_ON(dev->bus != &pci_bus_type); + + pci_unmap_sg(to_pci_dev(dev), sg, nhwentries, (int)direction); +} + +static inline void +dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(dev->bus != &pci_bus_type); + + pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle, + size, (int)direction); +} + +static inline void +dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, size_t size, + enum dma_data_direction direction) +{ + BUG_ON(dev->bus != &pci_bus_type); + + pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle, + size, (int)direction); +} + +static inline void +dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG_ON(dev->bus != &pci_bus_type); + + pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, nelems, (int)direction); +} + +static inline void +dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems, + enum dma_data_direction direction) +{ + BUG_ON(dev->bus != &pci_bus_type); + + pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, nelems, (int)direction); +} + +static inline int +dma_mapping_error(dma_addr_t dma_addr) +{ + return pci_dma_mapping_error(dma_addr); +} + #else struct device; diff --git a/include/asm-sparc64/pci.h b/include/asm-sparc64/pci.h index 7c5a589ea437a6..e1ea67bc32f22f 100644 --- a/include/asm-sparc64/pci.h +++ b/include/asm-sparc64/pci.h @@ -42,7 +42,7 @@ static inline void pcibios_penalize_isa_irq(int irq, int active) struct pci_dev; struct pci_iommu_ops { - void *(*alloc_consistent)(struct pci_dev *, size_t, dma_addr_t *); + void *(*alloc_consistent)(struct pci_dev *, size_t, dma_addr_t *, gfp_t); void (*free_consistent)(struct pci_dev *, size_t, void *, dma_addr_t); dma_addr_t (*map_single)(struct pci_dev *, void *, size_t, int); void (*unmap_single)(struct pci_dev *, dma_addr_t, size_t, int); @@ -59,7 +59,7 @@ extern struct pci_iommu_ops *pci_iommu_ops; */ static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) { - return pci_iommu_ops->alloc_consistent(hwdev, size, dma_handle); + return pci_iommu_ops->alloc_consistent(hwdev, size, dma_handle, GFP_ATOMIC); } /* Free and unmap a consistent DMA buffer. -- cgit 1.2.3-korg From e46e490368f87032a6e54969194413339b35a385 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Mon, 22 May 2006 22:35:24 -0700 Subject: [PATCH] sys_sync_file_range(): move exported flags outside __KERNEL__ These flags are needed by userspace - move them outside __KERNEL__ (Pointed out by dwmw2) Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/fs.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/fs.h b/include/linux/fs.h index 3de2bfb2410ffc..f813bc8266aa59 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -213,6 +213,10 @@ extern int dir_notify_enable; #define FIBMAP _IO(0x00,1) /* bmap access */ #define FIGETBSZ _IO(0x00,2) /* get the block size used for bmap */ +#define SYNC_FILE_RANGE_WAIT_BEFORE 1 +#define SYNC_FILE_RANGE_WRITE 2 +#define SYNC_FILE_RANGE_WAIT_AFTER 4 + #ifdef __KERNEL__ #include @@ -758,9 +762,6 @@ extern int fcntl_setlease(unsigned int fd, struct file *filp, long arg); extern int fcntl_getlease(struct file *filp); /* fs/sync.c */ -#define SYNC_FILE_RANGE_WAIT_BEFORE 1 -#define SYNC_FILE_RANGE_WRITE 2 -#define SYNC_FILE_RANGE_WAIT_AFTER 4 extern int do_sync_file_range(struct file *file, loff_t offset, loff_t endbyte, unsigned int flags); -- cgit 1.2.3-korg From f2d395865faa2a7cd4620b07178e58cbb160ba08 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 22 May 2006 22:35:25 -0700 Subject: [PATCH] knfsd: Fix two problems that can cause rmmod nfsd to die Both cause the 'entries' count in the export cache to be non-zero at module removal time, so unregistering that cache fails and results in an oops. 1/ exp_pseudoroot (used for NFSv4 only) leaks a reference to an export entry. 2/ sunrpc_cache_update doesn't increment the entries count when it adds an entry. Thanks to "david m. richter" for triggering the problem and finding one of the bugs. Cc: "david m. richter" Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/export.c | 4 +++- net/sunrpc/cache.c | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c index 4e0578121d9a62..3eec30000f3fb3 100644 --- a/fs/nfsd/export.c +++ b/fs/nfsd/export.c @@ -1066,9 +1066,11 @@ exp_pseudoroot(struct auth_domain *clp, struct svc_fh *fhp, rv = nfserr_perm; else if (IS_ERR(exp)) rv = nfserrno(PTR_ERR(exp)); - else + else { rv = fh_compose(fhp, exp, fsid_key->ek_dentry, NULL); + exp_put(exp); + } cache_put(&fsid_key->h, &svc_expkey_cache); return rv; } diff --git a/net/sunrpc/cache.c b/net/sunrpc/cache.c index 3ac4193a78edf2..7026b0866b7b0d 100644 --- a/net/sunrpc/cache.c +++ b/net/sunrpc/cache.c @@ -159,6 +159,7 @@ struct cache_head *sunrpc_cache_update(struct cache_detail *detail, detail->update(tmp, new); tmp->next = *head; *head = tmp; + detail->entries++; cache_get(tmp); is_new = cache_fresh_locked(tmp, new->expiry_time); cache_fresh_locked(old, 0); -- cgit 1.2.3-korg From 5c4c33318d26620fa552f15bbb6d0f9775a1b4df Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 22 May 2006 22:35:26 -0700 Subject: [PATCH] md: fix possible oops when starting a raid0 array This loop that sets up the hash_table has problems. Careful examination will show that the last time through, everything but the first line is pointless. This is because all it does is change 'cur' and 'size' and neither of these are used after the loop. This should ring warning bells... That last time through the loop, size += conf->strip_zone[cur].size can index off the end of the strip_zone array. Depending on what it finds there, it might exit the loop cleanly, or it might spin going further and further beyond the array until it hits an unmapped address. This patch rearranges the code so that the last, pointless, iteration of the loop never happens. i.e. the one statement of the last loop that is needed is moved the the end of the previous loop - or to before the loop starts - and the loop counter starts from 1 instead of 0. Cc: "Don Dupuis" Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/md/raid0.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 678f4dbbea1d5c..cb8c6317e4e5fc 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c @@ -331,13 +331,14 @@ static int raid0_run (mddev_t *mddev) goto out_free_conf; size = conf->strip_zone[cur].size; - for (i=0; i< nb_zone; i++) { - conf->hash_table[i] = conf->strip_zone + cur; + conf->hash_table[0] = conf->strip_zone + cur; + for (i=1; i< nb_zone; i++) { while (size <= conf->hash_spacing) { cur++; size += conf->strip_zone[cur].size; } size -= conf->hash_spacing; + conf->hash_table[i] = conf->strip_zone + cur; } if (conf->preshift) { conf->hash_spacing >>= conf->preshift; -- cgit 1.2.3-korg From a2eb0c101d24aca9d3d16c30c4f79f3a70c89208 Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Mon, 22 May 2006 22:35:27 -0700 Subject: [PATCH] md: Make sure bi_max_vecs is set properly in bio_split Else a subsequent bio_clone might make a mess. Signed-off-by: Neil Brown Cc: "Don Dupuis" Acked-by: Jens Axboe Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/bio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/bio.c b/fs/bio.c index eb8fbc53f2cd73..098c12b2d60a9d 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1116,6 +1116,9 @@ struct bio_pair *bio_split(struct bio *bi, mempool_t *pool, int first_sectors) bp->bio1.bi_io_vec = &bp->bv1; bp->bio2.bi_io_vec = &bp->bv2; + bp->bio1.bi_max_vecs = 1; + bp->bio2.bi_max_vecs = 1; + bp->bio1.bi_end_io = bio_pair_end_1; bp->bio2.bi_end_io = bio_pair_end_2; -- cgit 1.2.3-korg From ff4547f4aa9823908e9866495598fc65772c2a09 Mon Sep 17 00:00:00 2001 From: Tobias Powalowski Date: Mon, 22 May 2006 22:35:28 -0700 Subject: [PATCH] tty_insert_flip_string_flags() license fix We still don't have the tty layer licensing compatibility quite right. tty_insert_flip_char() used to be inlined in include/linux/tty_flip.h. It is now out-of-lined and hence needs EXPORT_SYMBOL() to be back-compatible. One known offender is the Intel Modem driver. Cc: Alan Cox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index f07637a8f88fd0..a88b94a82b140f 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -398,7 +398,7 @@ int tty_insert_flip_string_flags(struct tty_struct *tty, while (unlikely(size > copied)); return copied; } -EXPORT_SYMBOL_GPL(tty_insert_flip_string_flags); +EXPORT_SYMBOL(tty_insert_flip_string_flags); void tty_schedule_flip(struct tty_struct *tty) { -- cgit 1.2.3-korg From 30d6b2f3749e41ce37170ebc445948222b2db4ee Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 22 May 2006 22:35:29 -0700 Subject: [PATCH] swsusp: fix typo in cr0 handling Writing cr0 to cr2 register can't be right. This fixes the typo. I wonder how it could survive so long. Signed-off-by: Pavel Machek Cc: Zachary Amsden Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/i386/power/cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/i386/power/cpu.c b/arch/i386/power/cpu.c index 50a0bef8c85f69..79b2370c7facda 100644 --- a/arch/i386/power/cpu.c +++ b/arch/i386/power/cpu.c @@ -92,7 +92,7 @@ void __restore_processor_state(struct saved_context *ctxt) write_cr4(ctxt->cr4); write_cr3(ctxt->cr3); write_cr2(ctxt->cr2); - write_cr2(ctxt->cr0); + write_cr0(ctxt->cr0); /* * now restore the descriptor tables to their proper values -- cgit 1.2.3-korg From bb6e093da23ace2724fdadd27738027468eb82b3 Mon Sep 17 00:00:00 2001 From: Florin Malita Date: Mon, 22 May 2006 22:35:30 -0700 Subject: [PATCH] orinoco: possible null pointer dereference in orinoco_rx_monitor() If the skb allocation fails, the current error path calls dev_kfree_skb_irq() with a NULL argument. Also, 'err' is not being used. Coverity CID: 275. Signed-off-by: Florin Malita Cc: "John W. Linville" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/net/wireless/orinoco.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/net/wireless/orinoco.c b/drivers/net/wireless/orinoco.c index 06523e2a8471f0..c2d0b09e0418e1 100644 --- a/drivers/net/wireless/orinoco.c +++ b/drivers/net/wireless/orinoco.c @@ -812,7 +812,6 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, if (datalen > IEEE80211_DATA_LEN + 12) { printk(KERN_DEBUG "%s: oversized monitor frame, " "data length = %d\n", dev->name, datalen); - err = -EIO; stats->rx_length_errors++; goto update_stats; } @@ -821,8 +820,7 @@ static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, if (!skb) { printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n", dev->name); - err = -ENOMEM; - goto drop; + goto update_stats; } /* Copy the 802.11 header to the skb */ -- cgit 1.2.3-korg From 5a4fa1639622b85d7e4422242308fc6cef7e503e Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 23 May 2006 07:46:38 -0700 Subject: [PATCH] powerpc: fill hole in Cell SPU syscall table Syscall number 224 was absent from the table, which I believe means that the SPU can cause an oops by attempting to use it. Signed-off-by: David Woodhouse Cc: Benjamin Herrenschmidt Acked-by: Paul Mackerras Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/platforms/cell/spu_callbacks.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index 95b36430aa0fa4..67453147cd9902 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c @@ -258,6 +258,7 @@ void *spu_syscall_table[] = { [__NR_futex] sys_futex, [__NR_sched_setaffinity] sys_sched_setaffinity, [__NR_sched_getaffinity] sys_sched_getaffinity, + [224] sys_ni_syscall, [__NR_tuxcall] sys_ni_syscall, [226] sys_ni_syscall, [__NR_io_setup] sys_io_setup, -- cgit 1.2.3-korg From b471f55427ee94d6de2b33b88a7409f8cbc6b5dc Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 23 May 2006 07:46:39 -0700 Subject: [PATCH] powerpc: check Cell SPU syscall number range _before_ using it Signed-off-by: David Woodhouse Cc: Benjamin Herrenschmidt Acked-by: Paul Mackerras Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/platforms/cell/spu_callbacks.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index 67453147cd9902..5a0f9e3beb2467 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c @@ -339,13 +339,13 @@ long spu_sys_callback(struct spu_syscall_block *s) { long (*syscall)(u64 a1, u64 a2, u64 a3, u64 a4, u64 a5, u64 a6); - syscall = spu_syscall_table[s->nr_ret]; - if (s->nr_ret >= ARRAY_SIZE(spu_syscall_table)) { pr_debug("%s: invalid syscall #%ld", __FUNCTION__, s->nr_ret); return -ENOSYS; } + syscall = spu_syscall_table[s->nr_ret]; + #ifdef DEBUG print_symbol(KERN_DEBUG "SPU-syscall %s:", (unsigned long)syscall); printk("syscall%ld(%lx, %lx, %lx, %lx, %lx, %lx)\n", -- cgit 1.2.3-korg From 0f0410823792ae0ecb45f2578598b115835ffdbb Mon Sep 17 00:00:00 2001 From: David Woodhouse Date: Tue, 23 May 2006 07:46:40 -0700 Subject: [PATCH] powerpc: wire up sys_[gs]et_robust_list Signed-off-by: David Woodhouse Cc: Benjamin Herrenschmidt Acked-by: Paul Mackerras Cc: Arnd Bergmann Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/powerpc/kernel/systbl.S | 2 ++ arch/powerpc/platforms/cell/spu_callbacks.c | 2 ++ include/asm-powerpc/unistd.h | 4 +++- include/linux/syscalls.h | 6 ++++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/kernel/systbl.S b/arch/powerpc/kernel/systbl.S index cf56a1d499ff74..26ed1f5ef16e12 100644 --- a/arch/powerpc/kernel/systbl.S +++ b/arch/powerpc/kernel/systbl.S @@ -338,6 +338,8 @@ SYSCALL(symlinkat) SYSCALL(readlinkat) SYSCALL(fchmodat) SYSCALL(faccessat) +COMPAT_SYS(get_robust_list) +COMPAT_SYS(set_robust_list) /* * please add new calls to arch/powerpc/platforms/cell/spu_callbacks.c diff --git a/arch/powerpc/platforms/cell/spu_callbacks.c b/arch/powerpc/platforms/cell/spu_callbacks.c index 5a0f9e3beb2467..b47fcc5ddb7867 100644 --- a/arch/powerpc/platforms/cell/spu_callbacks.c +++ b/arch/powerpc/platforms/cell/spu_callbacks.c @@ -333,6 +333,8 @@ void *spu_syscall_table[] = { [__NR_readlinkat] sys_readlinkat, [__NR_fchmodat] sys_fchmodat, [__NR_faccessat] sys_faccessat, + [__NR_get_robust_list] sys_get_robust_list, + [__NR_set_robust_list] sys_set_robust_list, }; long spu_sys_callback(struct spu_syscall_block *s) diff --git a/include/asm-powerpc/unistd.h b/include/asm-powerpc/unistd.h index 908acb44cb8a11..edde2462bf52d5 100644 --- a/include/asm-powerpc/unistd.h +++ b/include/asm-powerpc/unistd.h @@ -321,8 +321,10 @@ #define __NR_readlinkat 296 #define __NR_fchmodat 297 #define __NR_faccessat 298 +#define __NR_get_robust_list 299 +#define __NR_set_robust_list 300 -#define __NR_syscalls 299 +#define __NR_syscalls 301 #ifdef __KERNEL__ #define __NR__exit __NR_exit diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 3996960fc5654e..60d49e5456e79c 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -52,6 +52,7 @@ struct utimbuf; struct mq_attr; struct compat_stat; struct compat_timeval; +struct robust_list_head; #include #include @@ -581,5 +582,10 @@ asmlinkage long sys_tee(int fdin, int fdout, size_t len, unsigned int flags); asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, unsigned int flags); +asmlinkage long sys_get_robust_list(int pid, + struct robust_list_head __user **head_ptr, + size_t __user *len_ptr); +asmlinkage long sys_set_robust_list(struct robust_list_head __user *head, + size_t len); #endif -- cgit 1.2.3-korg From fd0ff8aa1d95a896b3627bc62d42d6d002ac0bc3 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Tue, 23 May 2006 11:23:49 +0200 Subject: [PATCH] blk: fix gendisk->in_flight accounting during barrier sequence While executing barrrier sequence, the bar_rq which carries actual write was accounted as normal IO on completion, while it wasn't on queueing. This caused gendisk->in_flight to be decremented by 1 after each barrier thus messed up statistics. This patch makes bar_rq not accounted as normal IO. As the containing barrier request as a whole is accounted, part of it shouldn't be. Signed-off-by: Tejun Heo Signed-off-by: Jens Axboe Signed-off-by: Linus Torvalds --- block/ll_rw_blk.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/block/ll_rw_blk.c b/block/ll_rw_blk.c index eac48bec147915..7eb36c53f4b786 100644 --- a/block/ll_rw_blk.c +++ b/block/ll_rw_blk.c @@ -3452,7 +3452,12 @@ void end_that_request_last(struct request *req, int uptodate) if (unlikely(laptop_mode) && blk_fs_request(req)) laptop_io_completion(); - if (disk && blk_fs_request(req)) { + /* + * Account IO completion. bar_rq isn't accounted as a normal + * IO on queueing nor completion. Accounting the containing + * request is enough. + */ + if (disk && blk_fs_request(req) && req != &req->q->bar_rq) { unsigned long duration = jiffies - req->start_time; const int rw = rq_data_dir(req); -- cgit 1.2.3-korg From 9d8a51f80117a9d672b455d60901842ad50aa69f Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 23 May 2006 15:56:20 -0300 Subject: V4L/DVB (3927): Fix VIDEO_DEV=m, VIDEO_V4L1_COMPAT=y If CONFIG_VIDEO_DEV=m and CONFIG_VIDEO_V4L1_COMPAT=y, v4l1-compat should be built as a module (currently, it isn't built at all leading to problems with modules using it). Signed-off-by: Adrian Bunk Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index 9debef9be8c887..e5bf2687b76de8 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile @@ -11,7 +11,10 @@ tuner-objs := tuner-core.o tuner-types.o tuner-simple.o \ msp3400-objs := msp3400-driver.o msp3400-kthreads.o obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-common.o compat_ioctl32.o -obj-$(CONFIG_VIDEO_V4L1_COMPAT) += v4l1-compat.o + +ifeq ($(CONFIG_VIDEO_V4L1_COMPAT),y) + obj-$(CONFIG_VIDEO_DEV) += v4l1-compat.o +endif obj-$(CONFIG_VIDEO_BT848) += bt8xx/ obj-$(CONFIG_VIDEO_BT848) += tvaudio.o tda7432.o tda9875.o ir-kbd-i2c.o -- cgit 1.2.3-korg From 3c2c54910f277f3abd3763dbc64b9dbf8b4479e9 Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Sat, 20 May 2006 13:17:00 -0300 Subject: V4L/DVB (4037): Make the bridge devices that depend on I2C dependant on I2C Ref: Bugzilla 6179, 6589 Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/Kconfig | 10 +++++----- drivers/media/dvb/b2c2/Kconfig | 6 +++--- drivers/media/dvb/bt8xx/Kconfig | 2 +- drivers/media/dvb/dvb-usb/Kconfig | 2 +- drivers/media/dvb/pluto2/Kconfig | 2 +- drivers/media/dvb/ttpci/Kconfig | 8 ++++---- 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig index 3f0ec6be03ae35..a97c8f5e9a5d1d 100644 --- a/drivers/media/dvb/Kconfig +++ b/drivers/media/dvb/Kconfig @@ -22,26 +22,26 @@ config DVB source "drivers/media/dvb/dvb-core/Kconfig" comment "Supported SAA7146 based PCI Adapters" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && I2C source "drivers/media/dvb/ttpci/Kconfig" comment "Supported USB Adapters" - depends on DVB_CORE && USB + depends on DVB_CORE && USB && I2C source "drivers/media/dvb/dvb-usb/Kconfig" source "drivers/media/dvb/ttusb-budget/Kconfig" source "drivers/media/dvb/ttusb-dec/Kconfig" source "drivers/media/dvb/cinergyT2/Kconfig" comment "Supported FlexCopII (B2C2) Adapters" - depends on DVB_CORE && (PCI || USB) + depends on DVB_CORE && (PCI || USB) && I2C source "drivers/media/dvb/b2c2/Kconfig" comment "Supported BT878 Adapters" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && I2C source "drivers/media/dvb/bt8xx/Kconfig" comment "Supported Pluto2 Adapters" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && I2C source "drivers/media/dvb/pluto2/Kconfig" comment "Supported DVB Frontends" diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig index 2963605c0ecc23..d7f1fd5b7b02a8 100644 --- a/drivers/media/dvb/b2c2/Kconfig +++ b/drivers/media/dvb/b2c2/Kconfig @@ -1,6 +1,6 @@ config DVB_B2C2_FLEXCOP tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters" - depends on DVB_CORE + depends on DVB_CORE && I2C select DVB_STV0299 select DVB_MT352 select DVB_MT312 @@ -16,7 +16,7 @@ config DVB_B2C2_FLEXCOP config DVB_B2C2_FLEXCOP_PCI tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI" - depends on DVB_B2C2_FLEXCOP && PCI + depends on DVB_B2C2_FLEXCOP && PCI && I2C help Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2. @@ -24,7 +24,7 @@ config DVB_B2C2_FLEXCOP_PCI config DVB_B2C2_FLEXCOP_USB tristate "Technisat/B2C2 Air/Sky/Cable2PC USB" - depends on DVB_B2C2_FLEXCOP && USB + depends on DVB_B2C2_FLEXCOP && USB && I2C help Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by Technisat/B2C2, diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig index f28d721b8bb549..f394002118f81d 100644 --- a/drivers/media/dvb/bt8xx/Kconfig +++ b/drivers/media/dvb/bt8xx/Kconfig @@ -1,6 +1,6 @@ config DVB_BT8XX tristate "BT8xx based PCI cards" - depends on DVB_CORE && PCI && VIDEO_BT848 + depends on DVB_CORE && PCI && I2C && VIDEO_BT848 select DVB_MT352 select DVB_SP887X select DVB_NXT6000 diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig index d3df12039b066d..e388fb1567d6ec 100644 --- a/drivers/media/dvb/dvb-usb/Kconfig +++ b/drivers/media/dvb/dvb-usb/Kconfig @@ -1,6 +1,6 @@ config DVB_USB tristate "Support for various USB DVB devices" - depends on DVB_CORE && USB + depends on DVB_CORE && USB && I2C select FW_LOADER help By enabling this you will be able to choose the various supported diff --git a/drivers/media/dvb/pluto2/Kconfig b/drivers/media/dvb/pluto2/Kconfig index 84f8f9f52869a7..48252e9ce5864e 100644 --- a/drivers/media/dvb/pluto2/Kconfig +++ b/drivers/media/dvb/pluto2/Kconfig @@ -1,6 +1,6 @@ config DVB_PLUTO2 tristate "Pluto2 cards" - depends on DVB_CORE && PCI + depends on DVB_CORE && PCI && I2C select I2C select I2C_ALGOBIT select DVB_TDA1004X diff --git a/drivers/media/dvb/ttpci/Kconfig b/drivers/media/dvb/ttpci/Kconfig index c26e23291511ea..b5ac7dfde52f74 100644 --- a/drivers/media/dvb/ttpci/Kconfig +++ b/drivers/media/dvb/ttpci/Kconfig @@ -1,6 +1,6 @@ config DVB_AV7110 tristate "AV7110 cards" - depends on DVB_CORE && PCI && VIDEO_V4L1 + depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select FW_LOADER select VIDEO_SAA7146_VV select DVB_VES1820 @@ -58,7 +58,7 @@ config DVB_AV7110_OSD config DVB_BUDGET tristate "Budget cards" - depends on DVB_CORE && PCI && VIDEO_V4L1 + depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146 select DVB_STV0299 select DVB_VES1X93 @@ -79,7 +79,7 @@ config DVB_BUDGET config DVB_BUDGET_CI tristate "Budget cards with onboard CI connector" - depends on DVB_CORE && PCI && VIDEO_V4L1 + depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146 select DVB_STV0297 select DVB_STV0299 @@ -99,7 +99,7 @@ config DVB_BUDGET_CI config DVB_BUDGET_AV tristate "Budget cards with analog video inputs" - depends on DVB_CORE && PCI && VIDEO_V4L1 + depends on DVB_CORE && PCI && I2C && VIDEO_V4L1 select VIDEO_SAA7146_VV select DVB_STV0299 select DVB_TDA1004X -- cgit 1.2.3-korg From 8b6c879c81e8f00077607f83e024eedf388839b4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Tue, 23 May 2006 15:56:50 -0300 Subject: V4L/DVB (4040a): Fix the following section warnings: reference to .init.text: from .text between 'dvb_bt8xx_probe' (at offset 0x122c) and 'dvb_bt8xx_remove' reference to .init.text: from .text between 'dvb_bt8xx_probe' (at offset 0x1267) and 'dvb_bt8xx_remove' Signed-off-by: Jean Delvare Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dvb-bt8xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/media/dvb/bt8xx/dvb-bt8xx.c b/drivers/media/dvb/bt8xx/dvb-bt8xx.c index baa8227ef87c8d..ccc7b2eb4a2d33 100644 --- a/drivers/media/dvb/bt8xx/dvb-bt8xx.c +++ b/drivers/media/dvb/bt8xx/dvb-bt8xx.c @@ -115,7 +115,7 @@ static int is_pci_slot_eq(struct pci_dev* adev, struct pci_dev* bdev) return 0; } -static struct bt878 __init *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev) +static struct bt878 __devinit *dvb_bt8xx_878_match(unsigned int bttv_nr, struct pci_dev* bttv_pci_dev) { unsigned int card_nr; @@ -709,7 +709,7 @@ static void frontend_init(struct dvb_bt8xx_card *card, u32 type) } } -static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) +static int __devinit dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) { int result; @@ -794,7 +794,7 @@ static int __init dvb_bt8xx_load_card(struct dvb_bt8xx_card *card, u32 type) return 0; } -static int dvb_bt8xx_probe(struct bttv_sub_device *sub) +static int __devinit dvb_bt8xx_probe(struct bttv_sub_device *sub) { struct dvb_bt8xx_card *card; struct pci_dev* bttv_pci_dev; -- cgit 1.2.3-korg From 14ba3e7b3103a12b6f6a1057a1ecbfb15e1b48c0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 23 May 2006 16:02:03 -0300 Subject: V4L/DVB (4041): Fix compilation on PPC 64 Those functions don't exist on PPC64 architecture. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index 7124e534cc7fd4..6b419701856107 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig @@ -170,7 +170,7 @@ config VIDEO_VINO config VIDEO_STRADIS tristate "Stradis 4:2:2 MPEG-2 video driver (EXPERIMENTAL)" - depends on EXPERIMENTAL && PCI && VIDEO_V4L1 + depends on EXPERIMENTAL && PCI && VIDEO_V4L1 && !PPC64 help Say Y here to enable support for the Stradis 4:2:2 MPEG-2 video driver for PCI. There is a product page at @@ -178,7 +178,7 @@ config VIDEO_STRADIS config VIDEO_ZORAN tristate "Zoran ZR36057/36067 Video For Linux" - depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 + depends on PCI && I2C_ALGOBIT && VIDEO_V4L1 && !PPC64 help Say Y for support for MJPEG capture cards based on the Zoran 36057/36067 PCI controller chipset. This includes the Iomega -- cgit 1.2.3-korg From 7185989db4d926dbef1a2f638c464f35599c83e0 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 23 May 2006 15:07:07 -0700 Subject: [NETFILTER]: H.323 helper: fix parser error propagation The condition "> H323_ERROR_STOP" can never be true since H323_ERROR_STOP is positive and is the highest possible return code, while real errors are negative, fix the checks. Also only abort on real errors in some spots that were just interpreting any return value != 0 as error. Fixes crashes caused by use of stale data after a parsing error occured: BUG: unable to handle kernel paging request at virtual address bfffffff printing eip: c01aa0f8 *pde = 1a801067 *pte = 00000000 Oops: 0000 [#1] PREEMPT Modules linked in: ip_nat_h323 ip_conntrack_h323 nfsd exportfs sch_sfq sch_red cls_fw sch_hfsc xt_length ipt_owner xt_MARK iptable_mangle nfs lockd sunrpc pppoe pppoxx CPU: 0 EIP: 0060:[] Not tainted VLI EFLAGS: 00210646 (2.6.17-rc4 #8) EIP is at memmove+0x19/0x22 eax: d77264e9 ebx: d77264e9 ecx: e88d9b17 edx: d77264e9 esi: bfffffff edi: bfffffff ebp: de6a7680 esp: c0349db8 ds: 007b es: 007b ss: 0068 Process asterisk (pid: 3765, threadinfo=c0349000 task=da068540) Stack: <0>00000006 c0349e5e d77264e3 e09a2b4e e09a38a0 d7726052 d7726124 00000491 00000006 00000006 00000006 00000491 de6a7680 d772601e d7726032 c0349f74 e09a2dc2 00000006 c0349e5e 00000006 00000000 d76dda28 00000491 c0349f74 Call Trace: [] mangle_contents+0x62/0xfe [ip_nat] [] ip_nat_mangle_tcp_packet+0xa1/0x191 [ip_nat] [] set_addr+0x74/0x14c [ip_nat_h323] [] process_setup+0x11b/0x29e [ip_conntrack_h323] [] process_setup+0x14c/0x29e [ip_conntrack_h323] [] process_q931+0x3c/0x142 [ip_conntrack_h323] [] q931_help+0xe0/0x144 [ip_conntrack_h323] ... Found by the PROTOS c07-h2250v4 testsuite. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c | 34 ++++++++++++---------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c index 355a53a5b6cddf..5d04438dda4b07 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c @@ -528,14 +528,15 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) /* Decode */ if ((err = (Decoders[son->type]) (bs, son, base, - level + 1)) > - H323_ERROR_STOP) + level + 1)) < + H323_ERROR_NONE) return err; bs->cur = beg + len; bs->bit = 0; } else if ((err = (Decoders[son->type]) (bs, son, base, - level + 1))) + level + 1)) < + H323_ERROR_NONE) return err; } @@ -584,8 +585,8 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) beg = bs->cur; if ((err = (Decoders[son->type]) (bs, son, base, - level + 1)) > - H323_ERROR_STOP) + level + 1)) < + H323_ERROR_NONE) return err; bs->cur = beg + len; @@ -660,18 +661,20 @@ int decode_seqof(bitstr_t * bs, field_t * f, char *base, int level) i < effective_count ? base : NULL, - level + 1)) > - H323_ERROR_STOP) + level + 1)) < + H323_ERROR_NONE) return err; bs->cur = beg + len; bs->bit = 0; } else - if ((err = (Decoders[son->type]) (bs, son, - i < effective_count ? - base : NULL, - level + 1))) - return err; + if ((err = (Decoders[son->type]) (bs, son, + i < + effective_count ? + base : NULL, + level + 1)) < + H323_ERROR_NONE) + return err; if (base) base += son->offset; @@ -735,13 +738,14 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) } beg = bs->cur; - if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) > - H323_ERROR_STOP) + if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < + H323_ERROR_NONE) return err; bs->cur = beg + len; bs->bit = 0; - } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1))) + } else if ((err = (Decoders[son->type]) (bs, son, base, level + 1)) < + H323_ERROR_NONE) return err; return H323_ERROR_NONE; -- cgit 1.2.3-korg From 4d942d8b39bf7d43ce93d85964aeb63aeace0593 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Tue, 23 May 2006 15:07:46 -0700 Subject: [NETFILTER]: H.323 helper: fix sequence extension parsing When parsing unknown sequence extensions the "son"-pointer points behind the last known extension for this type, don't try to interpret it. Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c index 5d04438dda4b07..26dfecadb33568 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c @@ -555,7 +555,7 @@ int decode_seq(bitstr_t * bs, field_t * f, char *base, int level) /* Decode the extension components */ for (opt = 0; opt < bmp2_len; opt++, i++, son++) { - if (son->attr & STOP) { + if (i < f->ub && son->attr & STOP) { PRINT("%*.s%s\n", (level + 1) * TAB_SIZE, " ", son->name); return H323_ERROR_STOP; -- cgit 1.2.3-korg From 4a063739138e2c4e933188d641f1593e01ce8285 Mon Sep 17 00:00:00 2001 From: Chris Wright Date: Tue, 23 May 2006 15:08:13 -0700 Subject: [NETFILTER]: SNMP NAT: fix memleak in snmp_object_decode If kmalloc fails, error path leaks data allocated from asn1_oid_decode(). Signed-off-by: Chris Wright Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- net/ipv4/netfilter/ip_nat_snmp_basic.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ipv4/netfilter/ip_nat_snmp_basic.c b/net/ipv4/netfilter/ip_nat_snmp_basic.c index 688a2f29fadf67..c33244263b9035 100644 --- a/net/ipv4/netfilter/ip_nat_snmp_basic.c +++ b/net/ipv4/netfilter/ip_nat_snmp_basic.c @@ -768,6 +768,7 @@ static unsigned char snmp_object_decode(struct asn1_ctx *ctx, len *= sizeof(unsigned long); *obj = kmalloc(sizeof(struct snmp_object) + len, GFP_ATOMIC); if (*obj == NULL) { + kfree(lp); kfree(id); if (net_ratelimit()) printk("OOM in bsalg (%d)\n", __LINE__); -- cgit 1.2.3-korg From 387e2b0439026aa738a9edca15a57e5c0bcb4dfc Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Tue, 23 May 2006 15:20:25 -0700 Subject: [BRIDGE]: need to ref count the LLC sap Bridge will OOPS on removal if other application has the SAP open. The bridge SAP might be shared with other usages, so need to do reference counting on module removal rather than explicit close/delete. Since packet might arrive after or during removal, need to clear the receive function handle, so LLC only hands it to user (if any). Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/bridge/br.c b/net/bridge/br.c index 22d806cf40caf8..12da21afb9ca63 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c @@ -55,7 +55,7 @@ static int __init br_init(void) static void __exit br_deinit(void) { - llc_sap_close(br_stp_sap); + rcu_assign_pointer(br_stp_sap->rcv_func, NULL); #ifdef CONFIG_BRIDGE_NETFILTER br_netfilter_fini(); @@ -67,6 +67,7 @@ static void __exit br_deinit(void) synchronize_net(); + llc_sap_put(br_stp_sap); br_fdb_get_hook = NULL; br_fdb_put_hook = NULL; -- cgit 1.2.3-korg