From 758021bfa9ea25c58e62d2f68512628b19502ce7 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Jan 2009 15:17:09 +0100 Subject: drivers/media: Convert to snd_card_create() Convert from snd_card_new() to the new snd_card_create() function. Signed-off-by: Takashi Iwai --- drivers/media/video/cx88/cx88-alsa.c | 7 ++++--- drivers/media/video/em28xx/em28xx-audio.c | 7 ++++--- drivers/media/video/saa7134/saa7134-alsa.c | 8 ++++---- 3 files changed, 12 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/media/video/cx88/cx88-alsa.c b/drivers/media/video/cx88/cx88-alsa.c index 66c755c116d..ce98d955231 100644 --- a/drivers/media/video/cx88/cx88-alsa.c +++ b/drivers/media/video/cx88/cx88-alsa.c @@ -803,9 +803,10 @@ static int __devinit cx88_audio_initdev(struct pci_dev *pci, return (-ENOENT); } - card = snd_card_new(index[devno], id[devno], THIS_MODULE, sizeof(snd_cx88_card_t)); - if (!card) - return (-ENOMEM); + err = snd_card_create(index[devno], id[devno], THIS_MODULE, + sizeof(snd_cx88_card_t), &card); + if (err < 0) + return err; card->private_free = snd_cx88_dev_free; diff --git a/drivers/media/video/em28xx/em28xx-audio.c b/drivers/media/video/em28xx/em28xx-audio.c index 94378ccb750..66579508e17 100644 --- a/drivers/media/video/em28xx/em28xx-audio.c +++ b/drivers/media/video/em28xx/em28xx-audio.c @@ -438,9 +438,10 @@ static int em28xx_audio_init(struct em28xx *dev) printk(KERN_INFO "em28xx-audio.c: Copyright (C) 2006 Markus " "Rechberger\n"); - card = snd_card_new(index[devnr], "Em28xx Audio", THIS_MODULE, 0); - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnr], "Em28xx Audio", THIS_MODULE, 0, + &card); + if (err < 0) + return err; spin_lock_init(&adev->slock); err = snd_pcm_new(card, "Em28xx Audio", 0, 0, 1, &pcm); diff --git a/drivers/media/video/saa7134/saa7134-alsa.c b/drivers/media/video/saa7134/saa7134-alsa.c index 26194a0ce92..482be1436e9 100644 --- a/drivers/media/video/saa7134/saa7134-alsa.c +++ b/drivers/media/video/saa7134/saa7134-alsa.c @@ -990,10 +990,10 @@ static int alsa_card_saa7134_create(struct saa7134_dev *dev, int devnum) if (!enable[devnum]) return -ENODEV; - card = snd_card_new(index[devnum], id[devnum], THIS_MODULE, sizeof(snd_card_saa7134_t)); - - if (card == NULL) - return -ENOMEM; + err = snd_card_create(index[devnum], id[devnum], THIS_MODULE, + sizeof(snd_card_saa7134_t), &card); + if (err < 0) + return err; strcpy(card->driver, "SAA7134"); -- cgit v1.2.3 From 6ff1871617a3ea1eeaf88b42f652f9a311826bad Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Jan 2009 15:18:28 +0100 Subject: drivers/staging: Convert to snd_card_create() for go7007 Convert from snd_card_new to the new snd_card_create() for go7007. Signed-off-by: Takashi Iwai --- drivers/staging/go7007/snd-go7007.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/staging/go7007/snd-go7007.c b/drivers/staging/go7007/snd-go7007.c index a7de401f61a..cd19be6c00e 100644 --- a/drivers/staging/go7007/snd-go7007.c +++ b/drivers/staging/go7007/snd-go7007.c @@ -248,10 +248,11 @@ int go7007_snd_init(struct go7007 *go) spin_lock_init(&gosnd->lock); gosnd->hw_ptr = gosnd->w_idx = gosnd->avail = 0; gosnd->capturing = 0; - gosnd->card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); - if (gosnd->card == NULL) { + ret = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, + &gosnd->card); + if (ret < 0) { kfree(gosnd); - return -ENOMEM; + return ret; } ret = snd_device_new(gosnd->card, SNDRV_DEV_LOWLEVEL, go, &go7007_snd_device_ops); -- cgit v1.2.3 From 183c6e0fb4e39c860960de4abd7541bd260491bb Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Mon, 12 Jan 2009 15:19:08 +0100 Subject: drivers/usb/gadget: Convert to snd_card_create() Convert from snd_card_new() to the new snd_card_create() function for gmidi. Signed-off-by: Takashi Iwai --- drivers/usb/gadget/gmidi.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 60d3f9e9b51..14e09abbddf 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -1099,10 +1099,9 @@ static int gmidi_register_card(struct gmidi_device *dev) .dev_free = gmidi_snd_free, }; - card = snd_card_new(index, id, THIS_MODULE, 0); - if (!card) { - ERROR(dev, "snd_card_new failed\n"); - err = -ENOMEM; + err = snd_card_create(index, id, THIS_MODULE, 0, &card); + if (err < 0) { + ERROR(dev, "snd_card_create failed\n"); goto fail; } dev->card = card; -- cgit v1.2.3 From 69edbba0021a48fe034849501513930f6175cb5d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 25 Dec 2008 18:17:34 +0900 Subject: sh: use gpiolib This patch updates the SuperH gpio code to make use of gpiolib. The gpiolib callbacks get() and set() are lockless, but we use our own spinlock for the other operations to make sure hardware register bitfield accesses stay atomic. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index 3599828b976..6a7cd498023 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -1,6 +1,6 @@ #include #include -#include +#include #if defined(CONFIG_H83007) || defined(CONFIG_H83068) #include -- cgit v1.2.3 From 3fb1b6ad0679ad671bd496712b2a088550ee86b2 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 22 Jan 2009 09:55:59 +0000 Subject: sh: CMT clockevent platform driver SuperH CMT clockevent driver. Both 16-bit and 32-bit CMT versions are supported, but only 32-bit is tested. This driver contains support for both clockevents and clocksources, but no unregistration is supported at this point. Works fine as clock source and/or event in periodic or oneshot mode. Tested on sh7722 and sh7723, but should work with any cpu/architecture. This version is lacking clocksource and early platform driver support for now - this to minimize the amount of dependencies. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/clocksource/Makefile | 1 + drivers/clocksource/sh_cmt.c | 615 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 616 insertions(+) create mode 100644 drivers/clocksource/sh_cmt.c (limited to 'drivers') diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 1525882190f..1efb2879a94 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -2,3 +2,4 @@ obj-$(CONFIG_ATMEL_TCB_CLKSRC) += tcb_clksrc.o obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o +obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c new file mode 100644 index 00000000000..7783b42f691 --- /dev/null +++ b/drivers/clocksource/sh_cmt.c @@ -0,0 +1,615 @@ +/* + * SuperH Timer Support - CMT + * + * Copyright (C) 2008 Magnus Damm + * + * 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 + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct sh_cmt_priv { + void __iomem *mapbase; + struct clk *clk; + unsigned long width; /* 16 or 32 bit version of hardware block */ + unsigned long overflow_bit; + unsigned long clear_bits; + struct irqaction irqaction; + struct platform_device *pdev; + + unsigned long flags; + unsigned long match_value; + unsigned long next_match_value; + unsigned long max_match_value; + unsigned long rate; + spinlock_t lock; + struct clock_event_device ced; + unsigned long total_cycles; +}; + +static DEFINE_SPINLOCK(sh_cmt_lock); + +#define CMSTR -1 /* shared register */ +#define CMCSR 0 /* channel register */ +#define CMCNT 1 /* channel register */ +#define CMCOR 2 /* channel register */ + +static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr) +{ + struct sh_cmt_config *cfg = p->pdev->dev.platform_data; + void __iomem *base = p->mapbase; + unsigned long offs; + + if (reg_nr == CMSTR) { + offs = 0; + base -= cfg->channel_offset; + } else + offs = reg_nr; + + if (p->width == 16) + offs <<= 1; + else { + offs <<= 2; + if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) + return ioread32(base + offs); + } + + return ioread16(base + offs); +} + +static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr, + unsigned long value) +{ + struct sh_cmt_config *cfg = p->pdev->dev.platform_data; + void __iomem *base = p->mapbase; + unsigned long offs; + + if (reg_nr == CMSTR) { + offs = 0; + base -= cfg->channel_offset; + } else + offs = reg_nr; + + if (p->width == 16) + offs <<= 1; + else { + offs <<= 2; + if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) { + iowrite32(value, base + offs); + return; + } + } + + iowrite16(value, base + offs); +} + +static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, + int *has_wrapped) +{ + unsigned long v1, v2, v3; + + /* Make sure the timer value is stable. Stolen from acpi_pm.c */ + do { + v1 = sh_cmt_read(p, CMCNT); + v2 = sh_cmt_read(p, CMCNT); + v3 = sh_cmt_read(p, CMCNT); + } while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) + || (v3 > v1 && v3 < v2))); + + *has_wrapped = sh_cmt_read(p, CMCSR) & p->overflow_bit; + return v2; +} + + +static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) +{ + struct sh_cmt_config *cfg = p->pdev->dev.platform_data; + unsigned long flags, value; + + /* start stop register shared by multiple timer channels */ + spin_lock_irqsave(&sh_cmt_lock, flags); + value = sh_cmt_read(p, CMSTR); + + if (start) + value |= 1 << cfg->timer_bit; + else + value &= ~(1 << cfg->timer_bit); + + sh_cmt_write(p, CMSTR, value); + spin_unlock_irqrestore(&sh_cmt_lock, flags); +} + +static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) +{ + struct sh_cmt_config *cfg = p->pdev->dev.platform_data; + int ret; + + /* enable clock */ + ret = clk_enable(p->clk); + if (ret) { + pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk); + return ret; + } + *rate = clk_get_rate(p->clk) / 8; + + /* make sure channel is disabled */ + sh_cmt_start_stop_ch(p, 0); + + /* configure channel, periodic mode and maximum timeout */ + if (p->width == 16) + sh_cmt_write(p, CMCSR, 0); + else + sh_cmt_write(p, CMCSR, 0x01a4); + + sh_cmt_write(p, CMCOR, 0xffffffff); + sh_cmt_write(p, CMCNT, 0); + + /* enable channel */ + sh_cmt_start_stop_ch(p, 1); + return 0; +} + +static void sh_cmt_disable(struct sh_cmt_priv *p) +{ + /* disable channel */ + sh_cmt_start_stop_ch(p, 0); + + /* stop clock */ + clk_disable(p->clk); +} + +/* private flags */ +#define FLAG_CLOCKEVENT (1 << 0) +#define FLAG_CLOCKSOURCE (1 << 1) +#define FLAG_REPROGRAM (1 << 2) +#define FLAG_SKIPEVENT (1 << 3) +#define FLAG_IRQCONTEXT (1 << 4) + +static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p, + int absolute) +{ + unsigned long new_match; + unsigned long value = p->next_match_value; + unsigned long delay = 0; + unsigned long now = 0; + int has_wrapped; + + now = sh_cmt_get_counter(p, &has_wrapped); + p->flags |= FLAG_REPROGRAM; /* force reprogram */ + + if (has_wrapped) { + /* we're competing with the interrupt handler. + * -> let the interrupt handler reprogram the timer. + * -> interrupt number two handles the event. + */ + p->flags |= FLAG_SKIPEVENT; + return; + } + + if (absolute) + now = 0; + + do { + /* reprogram the timer hardware, + * but don't save the new match value yet. + */ + new_match = now + value + delay; + if (new_match > p->max_match_value) + new_match = p->max_match_value; + + sh_cmt_write(p, CMCOR, new_match); + + now = sh_cmt_get_counter(p, &has_wrapped); + if (has_wrapped && (new_match > p->match_value)) { + /* we are changing to a greater match value, + * so this wrap must be caused by the counter + * matching the old value. + * -> first interrupt reprograms the timer. + * -> interrupt number two handles the event. + */ + p->flags |= FLAG_SKIPEVENT; + break; + } + + if (has_wrapped) { + /* we are changing to a smaller match value, + * so the wrap must be caused by the counter + * matching the new value. + * -> save programmed match value. + * -> let isr handle the event. + */ + p->match_value = new_match; + break; + } + + /* be safe: verify hardware settings */ + if (now < new_match) { + /* timer value is below match value, all good. + * this makes sure we won't miss any match events. + * -> save programmed match value. + * -> let isr handle the event. + */ + p->match_value = new_match; + break; + } + + /* the counter has reached a value greater + * than our new match value. and since the + * has_wrapped flag isn't set we must have + * programmed a too close event. + * -> increase delay and retry. + */ + if (delay) + delay <<= 1; + else + delay = 1; + + if (!delay) + pr_warning("sh_cmt: too long delay\n"); + + } while (delay); +} + +static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) +{ + unsigned long flags; + + if (delta > p->max_match_value) + pr_warning("sh_cmt: delta out of range\n"); + + spin_lock_irqsave(&p->lock, flags); + p->next_match_value = delta; + sh_cmt_clock_event_program_verify(p, 0); + spin_unlock_irqrestore(&p->lock, flags); +} + +static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) +{ + struct sh_cmt_priv *p = dev_id; + + /* clear flags */ + sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits); + + /* update clock source counter to begin with if enabled + * the wrap flag should be cleared by the timer specific + * isr before we end up here. + */ + if (p->flags & FLAG_CLOCKSOURCE) + p->total_cycles += p->match_value; + + if (!(p->flags & FLAG_REPROGRAM)) + p->next_match_value = p->max_match_value; + + p->flags |= FLAG_IRQCONTEXT; + + if (p->flags & FLAG_CLOCKEVENT) { + if (!(p->flags & FLAG_SKIPEVENT)) { + if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT) { + p->next_match_value = p->max_match_value; + p->flags |= FLAG_REPROGRAM; + } + + p->ced.event_handler(&p->ced); + } + } + + p->flags &= ~FLAG_SKIPEVENT; + + if (p->flags & FLAG_REPROGRAM) { + p->flags &= ~FLAG_REPROGRAM; + sh_cmt_clock_event_program_verify(p, 1); + + if (p->flags & FLAG_CLOCKEVENT) + if ((p->ced.mode == CLOCK_EVT_MODE_SHUTDOWN) + || (p->match_value == p->next_match_value)) + p->flags &= ~FLAG_REPROGRAM; + } + + p->flags &= ~FLAG_IRQCONTEXT; + + return IRQ_HANDLED; +} + +static int sh_cmt_start(struct sh_cmt_priv *p, unsigned long flag) +{ + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&p->lock, flags); + + if (!(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) + ret = sh_cmt_enable(p, &p->rate); + + if (ret) + goto out; + p->flags |= flag; + + /* setup timeout if no clockevent */ + if ((flag == FLAG_CLOCKSOURCE) && (!(p->flags & FLAG_CLOCKEVENT))) + sh_cmt_set_next(p, p->max_match_value); + out: + spin_unlock_irqrestore(&p->lock, flags); + + return ret; +} + +static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag) +{ + unsigned long flags; + unsigned long f; + + spin_lock_irqsave(&p->lock, flags); + + f = p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE); + p->flags &= ~flag; + + if (f && !(p->flags & (FLAG_CLOCKEVENT | FLAG_CLOCKSOURCE))) + sh_cmt_disable(p); + + /* adjust the timeout to maximum if only clocksource left */ + if ((flag == FLAG_CLOCKEVENT) && (p->flags & FLAG_CLOCKSOURCE)) + sh_cmt_set_next(p, p->max_match_value); + + spin_unlock_irqrestore(&p->lock, flags); +} + +static struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced) +{ + return container_of(ced, struct sh_cmt_priv, ced); +} + +static void sh_cmt_clock_event_start(struct sh_cmt_priv *p, int periodic) +{ + struct clock_event_device *ced = &p->ced; + + sh_cmt_start(p, FLAG_CLOCKEVENT); + + /* TODO: calculate good shift from rate and counter bit width */ + + ced->shift = 32; + ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift); + ced->max_delta_ns = clockevent_delta2ns(p->max_match_value, ced); + ced->min_delta_ns = clockevent_delta2ns(0x1f, ced); + + if (periodic) + sh_cmt_set_next(p, (p->rate + HZ/2) / HZ); + else + sh_cmt_set_next(p, p->max_match_value); +} + +static void sh_cmt_clock_event_mode(enum clock_event_mode mode, + struct clock_event_device *ced) +{ + struct sh_cmt_priv *p = ced_to_sh_cmt(ced); + + /* deal with old setting first */ + switch (ced->mode) { + case CLOCK_EVT_MODE_PERIODIC: + case CLOCK_EVT_MODE_ONESHOT: + sh_cmt_stop(p, FLAG_CLOCKEVENT); + break; + default: + break; + } + + switch (mode) { + case CLOCK_EVT_MODE_PERIODIC: + pr_info("sh_cmt: %s used for periodic clock events\n", + ced->name); + sh_cmt_clock_event_start(p, 1); + break; + case CLOCK_EVT_MODE_ONESHOT: + pr_info("sh_cmt: %s used for oneshot clock events\n", + ced->name); + sh_cmt_clock_event_start(p, 0); + break; + case CLOCK_EVT_MODE_SHUTDOWN: + case CLOCK_EVT_MODE_UNUSED: + sh_cmt_stop(p, FLAG_CLOCKEVENT); + break; + default: + break; + } +} + +static int sh_cmt_clock_event_next(unsigned long delta, + struct clock_event_device *ced) +{ + struct sh_cmt_priv *p = ced_to_sh_cmt(ced); + + BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT); + if (likely(p->flags & FLAG_IRQCONTEXT)) + p->next_match_value = delta; + else + sh_cmt_set_next(p, delta); + + return 0; +} + +static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, + char *name, unsigned long rating) +{ + struct clock_event_device *ced = &p->ced; + + memset(ced, 0, sizeof(*ced)); + + ced->name = name; + ced->features = CLOCK_EVT_FEAT_PERIODIC; + ced->features |= CLOCK_EVT_FEAT_ONESHOT; + ced->rating = rating; + ced->cpumask = cpumask_of(0); + ced->set_next_event = sh_cmt_clock_event_next; + ced->set_mode = sh_cmt_clock_event_mode; + + pr_info("sh_cmt: %s used for clock events\n", ced->name); + ced->mult = 1; /* work around misplaced WARN_ON() in clockevents.c */ + clockevents_register_device(ced); +} + +int sh_cmt_register(struct sh_cmt_priv *p, char *name, + unsigned long clockevent_rating, + unsigned long clocksource_rating) +{ + if (p->width == (sizeof(p->max_match_value) * 8)) + p->max_match_value = ~0; + else + p->max_match_value = (1 << p->width) - 1; + + p->match_value = p->max_match_value; + spin_lock_init(&p->lock); + + if (clockevent_rating) + sh_cmt_register_clockevent(p, name, clockevent_rating); + + return 0; +} + +static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) +{ + struct sh_cmt_config *cfg = pdev->dev.platform_data; + struct resource *res; + int irq, ret; + ret = -ENXIO; + + memset(p, 0, sizeof(*p)); + p->pdev = pdev; + + if (!cfg) { + dev_err(&p->pdev->dev, "missing platform data\n"); + goto err0; + } + + platform_set_drvdata(pdev, p); + + res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&p->pdev->dev, "failed to get I/O memory\n"); + goto err0; + } + + irq = platform_get_irq(p->pdev, 0); + if (irq < 0) { + dev_err(&p->pdev->dev, "failed to get irq\n"); + goto err0; + } + + /* map memory, let mapbase point to our channel */ + p->mapbase = ioremap_nocache(res->start, resource_size(res)); + if (p->mapbase == NULL) { + pr_err("sh_cmt: failed to remap I/O memory\n"); + goto err0; + } + + /* request irq using setup_irq() (too early for request_irq()) */ + p->irqaction.name = cfg->name; + p->irqaction.handler = sh_cmt_interrupt; + p->irqaction.dev_id = p; + p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; + p->irqaction.mask = CPU_MASK_NONE; + ret = setup_irq(irq, &p->irqaction); + if (ret) { + pr_err("sh_cmt: failed to request irq %d\n", irq); + goto err1; + } + + /* get hold of clock */ + p->clk = clk_get(&p->pdev->dev, cfg->clk); + if (IS_ERR(p->clk)) { + pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk); + ret = PTR_ERR(p->clk); + goto err2; + } + + if (resource_size(res) == 6) { + p->width = 16; + p->overflow_bit = 0x80; + p->clear_bits = ~0xc0; + } else { + p->width = 32; + p->overflow_bit = 0x8000; + p->clear_bits = ~0xc000; + } + + return sh_cmt_register(p, cfg->name, + cfg->clockevent_rating, + cfg->clocksource_rating); + err2: + free_irq(irq, p); + err1: + iounmap(p->mapbase); + err0: + return ret; +} + +static int __devinit sh_cmt_probe(struct platform_device *pdev) +{ + struct sh_cmt_priv *p = platform_get_drvdata(pdev); + int ret; + + p = kmalloc(sizeof(*p), GFP_KERNEL); + if (p == NULL) { + dev_err(&pdev->dev, "failed to allocate driver data\n"); + return -ENOMEM; + } + + ret = sh_cmt_setup(p, pdev); + if (ret) { + kfree(p); + + platform_set_drvdata(pdev, NULL); + } + return ret; +} + +static int __devexit sh_cmt_remove(struct platform_device *pdev) +{ + return -EBUSY; /* cannot unregister clockevent and clocksource */ +} + +static struct platform_driver sh_cmt_device_driver = { + .probe = sh_cmt_probe, + .remove = __devexit_p(sh_cmt_remove), + .driver = { + .name = "sh_cmt", + } +}; + +static int __init sh_cmt_init(void) +{ + return platform_driver_register(&sh_cmt_device_driver); +} + +static void __exit sh_cmt_exit(void) +{ + platform_driver_unregister(&sh_cmt_device_driver); +} + +module_init(sh_cmt_init); +module_exit(sh_cmt_exit); + +MODULE_AUTHOR("Magnus Damm"); +MODULE_DESCRIPTION("SuperH CMT Timer Driver"); +MODULE_LICENSE("GPL v2"); -- cgit v1.2.3 From 0883743825e34b81f3ff78aaee3a97cba57586c5 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Mon, 2 Feb 2009 15:23:43 -0200 Subject: TPM: sysfs functions consolidation According to Dave Hansen's comments on the tpm_show_*, some of these functions present a pattern when allocating data[] memory space and also when setting its content. A new function was created so that this pattern could be consolidated. Also, replaced the data[] command vectors and its indexes by meaningful structures as pointed out by Matt Helsley too. Signed-off-by: Rajiv Andrade Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 411 +++++++++++++++++-------------------------------- drivers/char/tpm/tpm.h | 124 +++++++++++++++ 2 files changed, 266 insertions(+), 269 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 9c47dc48c9f..9b9eb761cba 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -429,134 +429,148 @@ out: #define TPM_DIGEST_SIZE 20 #define TPM_ERROR_SIZE 10 #define TPM_RET_CODE_IDX 6 -#define TPM_GET_CAP_RET_SIZE_IDX 10 -#define TPM_GET_CAP_RET_UINT32_1_IDX 14 -#define TPM_GET_CAP_RET_UINT32_2_IDX 18 -#define TPM_GET_CAP_RET_UINT32_3_IDX 22 -#define TPM_GET_CAP_RET_UINT32_4_IDX 26 -#define TPM_GET_CAP_PERM_DISABLE_IDX 16 -#define TPM_GET_CAP_PERM_INACTIVE_IDX 18 -#define TPM_GET_CAP_RET_BOOL_1_IDX 14 -#define TPM_GET_CAP_TEMP_INACTIVE_IDX 16 - -#define TPM_CAP_IDX 13 -#define TPM_CAP_SUBCAP_IDX 21 enum tpm_capabilities { - TPM_CAP_FLAG = 4, - TPM_CAP_PROP = 5, + TPM_CAP_FLAG = cpu_to_be32(4), + TPM_CAP_PROP = cpu_to_be32(5), + CAP_VERSION_1_1 = cpu_to_be32(0x06), + CAP_VERSION_1_2 = cpu_to_be32(0x1A) }; enum tpm_sub_capabilities { - TPM_CAP_PROP_PCR = 0x1, - TPM_CAP_PROP_MANUFACTURER = 0x3, - TPM_CAP_FLAG_PERM = 0x8, - TPM_CAP_FLAG_VOL = 0x9, - TPM_CAP_PROP_OWNER = 0x11, - TPM_CAP_PROP_TIS_TIMEOUT = 0x15, - TPM_CAP_PROP_TIS_DURATION = 0x20, -}; + TPM_CAP_PROP_PCR = cpu_to_be32(0x101), + TPM_CAP_PROP_MANUFACTURER = cpu_to_be32(0x103), + TPM_CAP_FLAG_PERM = cpu_to_be32(0x108), + TPM_CAP_FLAG_VOL = cpu_to_be32(0x109), + TPM_CAP_PROP_OWNER = cpu_to_be32(0x111), + TPM_CAP_PROP_TIS_TIMEOUT = cpu_to_be32(0x115), + TPM_CAP_PROP_TIS_DURATION = cpu_to_be32(0x120), -/* - * This is a semi generic GetCapability command for use - * with the capability type TPM_CAP_PROP or TPM_CAP_FLAG - * and their associated sub_capabilities. - */ - -static const u8 tpm_cap[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 22, /* length */ - 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 0, /* TPM_CAP_ */ - 0, 0, 0, 4, /* TPM_CAP_SUB_ size */ - 0, 0, 1, 0 /* TPM_CAP_SUB_ */ }; -static ssize_t transmit_cmd(struct tpm_chip *chip, u8 *data, int len, - char *desc) +static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, + int len, const char *desc) { int err; - len = tpm_transmit(chip, data, len); + len = tpm_transmit(chip,(u8 *) cmd, len); if (len < 0) return len; if (len == TPM_ERROR_SIZE) { - err = be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX))); + err = be32_to_cpu(cmd->header.out.return_code); dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); return err; } return 0; } +#define TPM_INTERNAL_RESULT_SIZE 200 +#define TPM_TAG_RQU_COMMAND cpu_to_be16(193) +#define TPM_ORD_GET_CAP cpu_to_be32(101) + +static const struct tpm_input_header tpm_getcap_header = { + .tag = TPM_TAG_RQU_COMMAND, + .length = cpu_to_be32(22), + .ordinal = TPM_ORD_GET_CAP +}; + +ssize_t tpm_getcap(struct device *dev, __be32 subcap_id, cap_t *cap, + const char *desc) +{ + struct tpm_cmd_t tpm_cmd; + int rc; + struct tpm_chip *chip = dev_get_drvdata(dev); + + tpm_cmd.header.in = tpm_getcap_header; + if (subcap_id == CAP_VERSION_1_1 || subcap_id == CAP_VERSION_1_2) { + tpm_cmd.params.getcap_in.cap = subcap_id; + /*subcap field not necessary */ + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(0); + tpm_cmd.header.in.length -= cpu_to_be32(sizeof(__be32)); + } else { + if (subcap_id == TPM_CAP_FLAG_PERM || + subcap_id == TPM_CAP_FLAG_VOL) + tpm_cmd.params.getcap_in.cap = TPM_CAP_FLAG; + else + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); + tpm_cmd.params.getcap_in.subcap = subcap_id; + } + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc); + if (!rc) + *cap = tpm_cmd.params.getcap_out.cap; + return rc; +} + void tpm_gen_interrupt(struct tpm_chip *chip) { - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; + struct tpm_cmd_t tpm_cmd; ssize_t rc; - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; + tpm_cmd.header.in = tpm_getcap_header; + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); + tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the timeouts"); } EXPORT_SYMBOL_GPL(tpm_gen_interrupt); void tpm_get_timeouts(struct tpm_chip *chip) { - u8 data[max_t(int, ARRAY_SIZE(tpm_cap), 30)]; + struct tpm_cmd_t tpm_cmd; + struct timeout_t *timeout_cap; + struct duration_t *duration_cap; ssize_t rc; u32 timeout; - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_TIMEOUT; + tpm_cmd.header.in = tpm_getcap_header; + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); + tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the timeouts"); if (rc) goto duration; - if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) + if (be32_to_cpu(tpm_cmd.header.out.length) != 4 * sizeof(u32)) goto duration; + timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; /* Don't overwrite default if value is 0 */ - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX))); + timeout = be32_to_cpu(timeout_cap->a); if (timeout) chip->vendor.timeout_a = usecs_to_jiffies(timeout); - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_2_IDX))); + timeout = be32_to_cpu(timeout_cap->b); if (timeout) chip->vendor.timeout_b = usecs_to_jiffies(timeout); - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_3_IDX))); + timeout = be32_to_cpu(timeout_cap->c); if (timeout) chip->vendor.timeout_c = usecs_to_jiffies(timeout); - timeout = - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_4_IDX))); + timeout = be32_to_cpu(timeout_cap->d); if (timeout) chip->vendor.timeout_d = usecs_to_jiffies(timeout); duration: - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_TIS_DURATION; + tpm_cmd.header.in = tpm_getcap_header; + tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; + tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); + tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; - rc = transmit_cmd(chip, data, sizeof(data), + rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, "attempting to determine the durations"); if (rc) return; - if (be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_SIZE_IDX))) + if (be32_to_cpu(tpm_cmd.header.out.return_code) != 3 * sizeof(u32)) return; - + duration_cap = &tpm_cmd.params.getcap_out.cap.duration; chip->vendor.duration[TPM_SHORT] = - usecs_to_jiffies(be32_to_cpu - (*((__be32 *) (data + - TPM_GET_CAP_RET_UINT32_1_IDX)))); + usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_short)); /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above * value wrong and apparently reports msecs rather than usecs. So we * fix up the resulting too-small TPM_SHORT value to make things work. @@ -565,13 +579,9 @@ duration: chip->vendor.duration[TPM_SHORT] = HZ; chip->vendor.duration[TPM_MEDIUM] = - usecs_to_jiffies(be32_to_cpu - (*((__be32 *) (data + - TPM_GET_CAP_RET_UINT32_2_IDX)))); + usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_medium)); chip->vendor.duration[TPM_LONG] = - usecs_to_jiffies(be32_to_cpu - (*((__be32 *) (data + - TPM_GET_CAP_RET_UINT32_3_IDX)))); + usecs_to_jiffies(be32_to_cpu(duration_cap->tpm_long)); } EXPORT_SYMBOL_GPL(tpm_get_timeouts); @@ -587,36 +597,18 @@ void tpm_continue_selftest(struct tpm_chip *chip) } EXPORT_SYMBOL_GPL(tpm_continue_selftest); -#define TPM_INTERNAL_RESULT_SIZE 200 - ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, char *buf) { - u8 *data; + cap_t cap; ssize_t rc; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_FLAG; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attemtping to determine the permanent enabled state"); - if (rc) { - kfree(data); + rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, + "attempting to determine the permanent enabled state"); + if (rc) return 0; - } - - rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_DISABLE_IDX]); - kfree(data); + rc = sprintf(buf, "%d\n", !cap.perm_flags.disable); return rc; } EXPORT_SYMBOL_GPL(tpm_show_enabled); @@ -624,31 +616,15 @@ EXPORT_SYMBOL_GPL(tpm_show_enabled); ssize_t tpm_show_active(struct device * dev, struct device_attribute * attr, char *buf) { - u8 *data; + cap_t cap; ssize_t rc; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_FLAG; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_PERM; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attemtping to determine the permanent active state"); - if (rc) { - kfree(data); + rc = tpm_getcap(dev, TPM_CAP_FLAG_PERM, &cap, + "attempting to determine the permanent active state"); + if (rc) return 0; - } - rc = sprintf(buf, "%d\n", !data[TPM_GET_CAP_PERM_INACTIVE_IDX]); - - kfree(data); + rc = sprintf(buf, "%d\n", !cap.perm_flags.deactivated); return rc; } EXPORT_SYMBOL_GPL(tpm_show_active); @@ -656,31 +632,15 @@ EXPORT_SYMBOL_GPL(tpm_show_active); ssize_t tpm_show_owned(struct device * dev, struct device_attribute * attr, char *buf) { - u8 *data; + cap_t cap; ssize_t rc; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_OWNER; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attempting to determine the owner state"); - if (rc) { - kfree(data); + rc = tpm_getcap(dev, TPM_CAP_PROP_OWNER, &cap, + "attempting to determine the owner state"); + if (rc) return 0; - } - - rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_RET_BOOL_1_IDX]); - kfree(data); + rc = sprintf(buf, "%d\n", cap.owned); return rc; } EXPORT_SYMBOL_GPL(tpm_show_owned); @@ -688,31 +648,15 @@ EXPORT_SYMBOL_GPL(tpm_show_owned); ssize_t tpm_show_temp_deactivated(struct device * dev, struct device_attribute * attr, char *buf) { - u8 *data; + cap_t cap; ssize_t rc; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_FLAG; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_FLAG_VOL; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attempting to determine the temporary state"); - if (rc) { - kfree(data); + rc = tpm_getcap(dev, TPM_CAP_FLAG_VOL, &cap, + "attempting to determine the temporary state"); + if (rc) return 0; - } - rc = sprintf(buf, "%d\n", data[TPM_GET_CAP_TEMP_INACTIVE_IDX]); - - kfree(data); + rc = sprintf(buf, "%d\n", cap.stclear_flags.deactivated); return rc; } EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); @@ -727,77 +671,64 @@ static const u8 pcrread[] = { ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, char *buf) { + cap_t cap; u8 *data; ssize_t rc; int i, j, num_pcrs; __be32 index; char *str = buf; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); if (!data) return -ENOMEM; - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_PCR; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, + rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap, "attempting to determine the number of PCRS"); - if (rc) { - kfree(data); + if (rc) return 0; - } - num_pcrs = be32_to_cpu(*((__be32 *) (data + 14))); + num_pcrs = be32_to_cpu(cap.num_pcrs); for (i = 0; i < num_pcrs; i++) { memcpy(data, pcrread, sizeof(pcrread)); index = cpu_to_be32(i); memcpy(data + 10, &index, 4); - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attempting to read a PCR"); + rc = transmit_cmd(chip, (struct tpm_cmd_t *)data, + TPM_INTERNAL_RESULT_SIZE, + "attempting to read a PCR"); if (rc) - goto out; + break; str += sprintf(str, "PCR-%02d: ", i); for (j = 0; j < TPM_DIGEST_SIZE; j++) str += sprintf(str, "%02X ", *(data + 10 + j)); str += sprintf(str, "\n"); } -out: kfree(data); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_pcrs); #define READ_PUBEK_RESULT_SIZE 314 -static const u8 readpubek[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 30, /* length */ - 0, 0, 0, 124, /* TPM_ORD_ReadPubek */ +#define TPM_ORD_READPUBEK cpu_to_be32(124) +struct tpm_input_header tpm_readpubek_header = { + .tag = TPM_TAG_RQU_COMMAND, + .length = cpu_to_be32(30), + .ordinal = TPM_ORD_READPUBEK }; ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, char *buf) { u8 *data; + struct tpm_cmd_t tpm_cmd; ssize_t err; int i, rc; char *str = buf; struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - data = kzalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, readpubek, sizeof(readpubek)); - - err = transmit_cmd(chip, data, READ_PUBEK_RESULT_SIZE, + tpm_cmd.header.in = tpm_readpubek_header; + err = transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, "attempting to read the PUBEK"); if (err) goto out; @@ -812,7 +743,7 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, 256 byte modulus ignore checksum 20 bytes */ - + data = tpm_cmd.params.readpubek_out_buffer; str += sprintf(str, "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" @@ -832,65 +763,33 @@ ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr, } out: rc = str - buf; - kfree(data); return rc; } EXPORT_SYMBOL_GPL(tpm_show_pubek); -#define CAP_VERSION_1_1 6 -#define CAP_VERSION_1_2 0x1A -#define CAP_VERSION_IDX 13 -static const u8 cap_version[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 18, /* length */ - 0, 0, 0, 101, /* TPM_ORD_GetCapability */ - 0, 0, 0, 0, - 0, 0, 0, 0 -}; ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr, char *buf) { - u8 *data; + cap_t cap; ssize_t rc; char *str = buf; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; - - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, + rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, "attempting to determine the manufacturer"); - if (rc) { - kfree(data); + if (rc) return 0; - } - str += sprintf(str, "Manufacturer: 0x%x\n", - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); + be32_to_cpu(cap.manufacturer_id)); - memcpy(data, cap_version, sizeof(cap_version)); - data[CAP_VERSION_IDX] = CAP_VERSION_1_1; - rc = transmit_cmd(chip, data, TPM_INTERNAL_RESULT_SIZE, - "attempting to determine the 1.1 version"); + rc = tpm_getcap(dev, CAP_VERSION_1_1, &cap, + "attempting to determine the 1.1 version"); if (rc) - goto out; - + return 0; str += sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n", - (int) data[14], (int) data[15], (int) data[16], - (int) data[17]); - -out: - kfree(data); + cap.tpm_version.Major, cap.tpm_version.Minor, + cap.tpm_version.revMajor, cap.tpm_version.revMinor); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_caps); @@ -898,51 +797,25 @@ EXPORT_SYMBOL_GPL(tpm_show_caps); ssize_t tpm_show_caps_1_2(struct device * dev, struct device_attribute * attr, char *buf) { - u8 *data; - ssize_t len; + cap_t cap; + ssize_t rc; char *str = buf; - struct tpm_chip *chip = dev_get_drvdata(dev); - if (chip == NULL) - return -ENODEV; - - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - - memcpy(data, tpm_cap, sizeof(tpm_cap)); - data[TPM_CAP_IDX] = TPM_CAP_PROP; - data[TPM_CAP_SUBCAP_IDX] = TPM_CAP_PROP_MANUFACTURER; - - len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); - if (len <= TPM_ERROR_SIZE) { - dev_dbg(chip->dev, "A TPM error (%d) occurred " - "attempting to determine the manufacturer\n", - be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); - kfree(data); + rc = tpm_getcap(dev, TPM_CAP_PROP_MANUFACTURER, &cap, + "attempting to determine the manufacturer"); + if (rc) return 0; - } - str += sprintf(str, "Manufacturer: 0x%x\n", - be32_to_cpu(*((__be32 *) (data + TPM_GET_CAP_RET_UINT32_1_IDX)))); - - memcpy(data, cap_version, sizeof(cap_version)); - data[CAP_VERSION_IDX] = CAP_VERSION_1_2; - - len = tpm_transmit(chip, data, TPM_INTERNAL_RESULT_SIZE); - if (len <= TPM_ERROR_SIZE) { - dev_err(chip->dev, "A TPM error (%d) occurred " - "attempting to determine the 1.2 version\n", - be32_to_cpu(*((__be32 *) (data + TPM_RET_CODE_IDX)))); - goto out; - } + be32_to_cpu(cap.manufacturer_id)); + rc = tpm_getcap(dev, CAP_VERSION_1_2, &cap, + "attempting to determine the 1.2 version"); + if (rc) + return 0; str += sprintf(str, "TCG version: %d.%d\nFirmware version: %d.%d\n", - (int) data[16], (int) data[17], (int) data[18], - (int) data[19]); - -out: - kfree(data); + cap.tpm_version_1_2.Major, cap.tpm_version_1_2.Minor, + cap.tpm_version_1_2.revMajor, + cap.tpm_version_1_2.revMinor); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_caps_1_2); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 8e30df4a438..d64f6b7e5b8 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -123,6 +123,130 @@ static inline void tpm_write_index(int base, int index, int value) outb(index, base); outb(value & 0xFF, base+1); } +struct tpm_input_header { + __be16 tag; + __be32 length; + __be32 ordinal; +}__attribute__((packed)); + +struct tpm_output_header { + __be16 tag; + __be32 length; + __be32 return_code; +}__attribute__((packed)); + +struct stclear_flags_t { + __be16 tag; + u8 deactivated; + u8 disableForceClear; + u8 physicalPresence; + u8 physicalPresenceLock; + u8 bGlobalLock; +}__attribute__((packed)); + +struct tpm_version_t { + u8 Major; + u8 Minor; + u8 revMajor; + u8 revMinor; +}__attribute__((packed)); + +struct tpm_version_1_2_t { + __be16 tag; + u8 Major; + u8 Minor; + u8 revMajor; + u8 revMinor; +}__attribute__((packed)); + +struct timeout_t { + __be32 a; + __be32 b; + __be32 c; + __be32 d; +}__attribute__((packed)); + +struct duration_t { + __be32 tpm_short; + __be32 tpm_medium; + __be32 tpm_long; +}__attribute__((packed)); + +struct permanent_flags_t { + __be16 tag; + u8 disable; + u8 ownership; + u8 deactivated; + u8 readPubek; + u8 disableOwnerClear; + u8 allowMaintenance; + u8 physicalPresenceLifetimeLock; + u8 physicalPresenceHWEnable; + u8 physicalPresenceCMDEnable; + u8 CEKPUsed; + u8 TPMpost; + u8 TPMpostLock; + u8 FIPS; + u8 operator; + u8 enableRevokeEK; + u8 nvLocked; + u8 readSRKPub; + u8 tpmEstablished; + u8 maintenanceDone; + u8 disableFullDALogicInfo; +}__attribute__((packed)); + +typedef union { + struct permanent_flags_t perm_flags; + struct stclear_flags_t stclear_flags; + bool owned; + __be32 num_pcrs; + struct tpm_version_t tpm_version; + struct tpm_version_1_2_t tpm_version_1_2; + __be32 manufacturer_id; + struct timeout_t timeout; + struct duration_t duration; +} cap_t; + +struct tpm_getcap_params_in { + __be32 cap; + __be32 subcap_size; + __be32 subcap; +}__attribute__((packed)); + +struct tpm_getcap_params_out { + __be32 cap_size; + cap_t cap; +}__attribute__((packed)); + +struct tpm_readpubek_params_out { + u8 algorithm[4]; + u8 encscheme[2]; + u8 sigscheme[2]; + u8 parameters[12]; /*assuming RSA*/ + __be32 keysize; + u8 modulus[256]; + u8 checksum[20]; +}__attribute__((packed)); + +typedef union { + struct tpm_input_header in; + struct tpm_output_header out; +} tpm_cmd_header; + +typedef union { + struct tpm_getcap_params_out getcap_out; + struct tpm_readpubek_params_out readpubek_out; + u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; + struct tpm_getcap_params_in getcap_in; +} tpm_cmd_params; + +struct tpm_cmd_t { + tpm_cmd_header header; + tpm_cmd_params params; +}__attribute__((packed)); + +ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); extern void tpm_get_timeouts(struct tpm_chip *); extern void tpm_gen_interrupt(struct tpm_chip *); -- cgit v1.2.3 From 659aaf2bb5496a425ba14036b5b5900f593e4484 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Mon, 2 Feb 2009 15:23:44 -0200 Subject: TPM: integrity interface This patch adds internal kernel support for: - reading/extending a pcr value - looking up the tpm_chip for a given chip number Signed-off-by: Rajiv Andrade Signed-off-by: Mimi Zohar Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 129 +++++++++++++++++++++++++++++++++++++++++-------- drivers/char/tpm/tpm.h | 18 +++++++ 2 files changed, 128 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 9b9eb761cba..62a5682578c 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -661,28 +661,125 @@ ssize_t tpm_show_temp_deactivated(struct device * dev, } EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); -static const u8 pcrread[] = { - 0, 193, /* TPM_TAG_RQU_COMMAND */ - 0, 0, 0, 14, /* length */ - 0, 0, 0, 21, /* TPM_ORD_PcrRead */ - 0, 0, 0, 0 /* PCR index */ +/* + * tpm_chip_find_get - return tpm_chip for given chip number + */ +static struct tpm_chip *tpm_chip_find_get(int chip_num) +{ + struct tpm_chip *pos; + + rcu_read_lock(); + list_for_each_entry_rcu(pos, &tpm_chip_list, list) { + if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) + continue; + + if (try_module_get(pos->dev->driver->owner)) + break; + } + rcu_read_unlock(); + return pos; +} + +#define TPM_ORDINAL_PCRREAD cpu_to_be32(21) +#define READ_PCR_RESULT_SIZE 30 +static struct tpm_input_header pcrread_header = { + .tag = TPM_TAG_RQU_COMMAND, + .length = cpu_to_be32(14), + .ordinal = TPM_ORDINAL_PCRREAD +}; + +int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) +{ + int rc; + struct tpm_cmd_t cmd; + + cmd.header.in = pcrread_header; + cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); + BUILD_BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE); + rc = transmit_cmd(chip, &cmd, cmd.header.in.length, + "attempting to read a pcr value"); + + if (rc == 0) + memcpy(res_buf, cmd.params.pcrread_out.pcr_result, + TPM_DIGEST_SIZE); + return rc; +} + +/** + * tpm_pcr_read - read a pcr value + * @chip_num: tpm idx # or ANY + * @pcr_idx: pcr idx to retrieve + * @res_buf: TPM_PCR value + * size of res_buf is 20 bytes (or NULL if you don't care) + * + * The TPM driver should be built-in, but for whatever reason it + * isn't, protect against the chip disappearing, by incrementing + * the module usage count. + */ +int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) +{ + struct tpm_chip *chip; + int rc; + + chip = tpm_chip_find_get(chip_num); + if (chip == NULL) + return -ENODEV; + rc = __tpm_pcr_read(chip, pcr_idx, res_buf); + module_put(chip->dev->driver->owner); + return rc; +} +EXPORT_SYMBOL_GPL(tpm_pcr_read); + +/** + * tpm_pcr_extend - extend pcr value with hash + * @chip_num: tpm idx # or AN& + * @pcr_idx: pcr idx to extend + * @hash: hash value used to extend pcr value + * + * The TPM driver should be built-in, but for whatever reason it + * isn't, protect against the chip disappearing, by incrementing + * the module usage count. + */ +#define TPM_ORD_PCR_EXTEND cpu_to_be32(20) +#define EXTEND_PCR_SIZE 34 +static struct tpm_input_header pcrextend_header = { + .tag = TPM_TAG_RQU_COMMAND, + .length = cpu_to_be32(34), + .ordinal = TPM_ORD_PCR_EXTEND }; +int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) +{ + struct tpm_cmd_t cmd; + int rc; + struct tpm_chip *chip; + + chip = tpm_chip_find_get(chip_num); + if (chip == NULL) + return -ENODEV; + + cmd.header.in = pcrextend_header; + BUILD_BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE); + cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); + memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); + rc = transmit_cmd(chip, &cmd, cmd.header.in.length, + "attempting extend a PCR value"); + + module_put(chip->dev->driver->owner); + return rc; +} +EXPORT_SYMBOL_GPL(tpm_pcr_extend); + ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, char *buf) { cap_t cap; - u8 *data; + u8 digest[TPM_DIGEST_SIZE]; ssize_t rc; int i, j, num_pcrs; - __be32 index; char *str = buf; struct tpm_chip *chip = dev_get_drvdata(dev); - data = kzalloc(TPM_INTERNAL_RESULT_SIZE, GFP_KERNEL); - if (!data) - return -ENOMEM; - rc = tpm_getcap(dev, TPM_CAP_PROP_PCR, &cap, "attempting to determine the number of PCRS"); if (rc) @@ -690,20 +787,14 @@ ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr, num_pcrs = be32_to_cpu(cap.num_pcrs); for (i = 0; i < num_pcrs; i++) { - memcpy(data, pcrread, sizeof(pcrread)); - index = cpu_to_be32(i); - memcpy(data + 10, &index, 4); - rc = transmit_cmd(chip, (struct tpm_cmd_t *)data, - TPM_INTERNAL_RESULT_SIZE, - "attempting to read a PCR"); + rc = __tpm_pcr_read(chip, i, digest); if (rc) break; str += sprintf(str, "PCR-%02d: ", i); for (j = 0; j < TPM_DIGEST_SIZE; j++) - str += sprintf(str, "%02X ", *(data + 10 + j)); + str += sprintf(str, "%02X ", digest[j]); str += sprintf(str, "\n"); } - kfree(data); return str - buf; } EXPORT_SYMBOL_GPL(tpm_show_pcrs); diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index d64f6b7e5b8..8e00b4ddd08 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -26,6 +26,7 @@ #include #include #include +#include enum tpm_timeout { TPM_TIMEOUT = 5, /* msecs */ @@ -234,11 +235,28 @@ typedef union { struct tpm_output_header out; } tpm_cmd_header; +#define TPM_DIGEST_SIZE 20 +struct tpm_pcrread_out { + u8 pcr_result[TPM_DIGEST_SIZE]; +}__attribute__((packed)); + +struct tpm_pcrread_in { + __be32 pcr_idx; +}__attribute__((packed)); + +struct tpm_pcrextend_in { + __be32 pcr_idx; + u8 hash[TPM_DIGEST_SIZE]; +}__attribute__((packed)); + typedef union { struct tpm_getcap_params_out getcap_out; struct tpm_readpubek_params_out readpubek_out; u8 readpubek_out_buffer[sizeof(struct tpm_readpubek_params_out)]; struct tpm_getcap_params_in getcap_in; + struct tpm_pcrread_in pcrread_in; + struct tpm_pcrread_out pcrread_out; + struct tpm_pcrextend_in pcrextend_in; } tpm_cmd_params; struct tpm_cmd_t { -- cgit v1.2.3 From 8920d5ad6ba74ae8ab020e90cc4d976980e68701 Mon Sep 17 00:00:00 2001 From: Rajiv Andrade Date: Thu, 5 Feb 2009 13:06:30 -0200 Subject: TPM: integrity fix Fix to function which is called by IMA, now tpm_chip_find_get() considers the case in which the machine doesn't have a TPM or, if it has, its TPM isn't enabled. Signed-off-by: Mimi Zohar Signed-off-by: Rajiv Andrade Acked-by: Serge Hallyn Signed-off-by: James Morris --- drivers/char/tpm/tpm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 62a5682578c..ccdd828adce 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c @@ -666,18 +666,20 @@ EXPORT_SYMBOL_GPL(tpm_show_temp_deactivated); */ static struct tpm_chip *tpm_chip_find_get(int chip_num) { - struct tpm_chip *pos; + struct tpm_chip *pos, *chip = NULL; rcu_read_lock(); list_for_each_entry_rcu(pos, &tpm_chip_list, list) { if (chip_num != TPM_ANY_NUM && chip_num != pos->dev_num) continue; - if (try_module_get(pos->dev->driver->owner)) + if (try_module_get(pos->dev->driver->owner)) { + chip = pos; break; + } } rcu_read_unlock(); - return pos; + return chip; } #define TPM_ORDINAL_PCRREAD cpu_to_be32(21) -- cgit v1.2.3 From 563f346d04e8373739240604a51ce8529dd9f07e Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Sun, 18 Jan 2009 20:33:33 +1100 Subject: crypto: sha-s390 - Switch to shash This patch converts the S390 sha algorithms to the new shash interface. With fixes by Jan Glauber. Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index e522144cba3..5adbae71454 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -86,7 +86,7 @@ config ZCRYPT_MONOLITHIC config CRYPTO_SHA1_S390 tristate "SHA1 digest algorithm" depends on S390 - select CRYPTO_ALGAPI + select CRYPTO_HASH help This is the s390 hardware accelerated implementation of the SHA-1 secure hash standard (FIPS 180-1/DFIPS 180-2). @@ -94,7 +94,7 @@ config CRYPTO_SHA1_S390 config CRYPTO_SHA256_S390 tristate "SHA256 digest algorithm" depends on S390 - select CRYPTO_ALGAPI + select CRYPTO_HASH help This is the s390 hardware accelerated implementation of the SHA256 secure hash standard (DFIPS 180-2). @@ -105,7 +105,7 @@ config CRYPTO_SHA256_S390 config CRYPTO_SHA512_S390 tristate "SHA384 and SHA512 digest algorithm" depends on S390 - select CRYPTO_ALGAPI + select CRYPTO_HASH help This is the s390 hardware accelerated implementation of the SHA512 secure hash standard. -- cgit v1.2.3 From 049359d655277c382683a6030ae0bac485568ffc Mon Sep 17 00:00:00 2001 From: James Hsiao Date: Thu, 5 Feb 2009 16:18:13 +1100 Subject: crypto: amcc - Add crypt4xx driver This patch adds support for AMCC ppc4xx security device driver. This is the initial release that includes the driver framework with AES and SHA1 algorithms support. The remaining algorithms will be released in the near future. Signed-off-by: James Hsiao Signed-off-by: Herbert Xu --- drivers/crypto/Kconfig | 9 + drivers/crypto/Makefile | 1 + drivers/crypto/amcc/Makefile | 2 + drivers/crypto/amcc/crypto4xx_alg.c | 293 +++++++ drivers/crypto/amcc/crypto4xx_core.c | 1310 +++++++++++++++++++++++++++++++ drivers/crypto/amcc/crypto4xx_core.h | 177 +++++ drivers/crypto/amcc/crypto4xx_reg_def.h | 284 +++++++ drivers/crypto/amcc/crypto4xx_sa.c | 108 +++ drivers/crypto/amcc/crypto4xx_sa.h | 243 ++++++ 9 files changed, 2427 insertions(+) create mode 100644 drivers/crypto/amcc/Makefile create mode 100644 drivers/crypto/amcc/crypto4xx_alg.c create mode 100644 drivers/crypto/amcc/crypto4xx_core.c create mode 100644 drivers/crypto/amcc/crypto4xx_core.h create mode 100644 drivers/crypto/amcc/crypto4xx_reg_def.h create mode 100644 drivers/crypto/amcc/crypto4xx_sa.c create mode 100644 drivers/crypto/amcc/crypto4xx_sa.h (limited to 'drivers') diff --git a/drivers/crypto/Kconfig b/drivers/crypto/Kconfig index 5adbae71454..01afd758072 100644 --- a/drivers/crypto/Kconfig +++ b/drivers/crypto/Kconfig @@ -200,4 +200,13 @@ config CRYPTO_DEV_IXP4XX help Driver for the IXP4xx NPE crypto engine. +config CRYPTO_DEV_PPC4XX + tristate "Driver AMCC PPC4xx crypto accelerator" + depends on PPC && 4xx + select CRYPTO_HASH + select CRYPTO_ALGAPI + select CRYPTO_BLKCIPHER + help + This option allows you to have support for AMCC crypto acceleration. + endif # CRYPTO_HW diff --git a/drivers/crypto/Makefile b/drivers/crypto/Makefile index 73557b2968d..9bf4a2bc884 100644 --- a/drivers/crypto/Makefile +++ b/drivers/crypto/Makefile @@ -4,3 +4,4 @@ obj-$(CONFIG_CRYPTO_DEV_GEODE) += geode-aes.o obj-$(CONFIG_CRYPTO_DEV_HIFN_795X) += hifn_795x.o obj-$(CONFIG_CRYPTO_DEV_TALITOS) += talitos.o obj-$(CONFIG_CRYPTO_DEV_IXP4XX) += ixp4xx_crypto.o +obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/ diff --git a/drivers/crypto/amcc/Makefile b/drivers/crypto/amcc/Makefile new file mode 100644 index 00000000000..aa376e8d5ed --- /dev/null +++ b/drivers/crypto/amcc/Makefile @@ -0,0 +1,2 @@ +obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += crypto4xx.o +crypto4xx-objs := crypto4xx_core.o crypto4xx_alg.o crypto4xx_sa.o diff --git a/drivers/crypto/amcc/crypto4xx_alg.c b/drivers/crypto/amcc/crypto4xx_alg.c new file mode 100644 index 00000000000..61b6e1bec8c --- /dev/null +++ b/drivers/crypto/amcc/crypto4xx_alg.c @@ -0,0 +1,293 @@ +/** + * AMCC SoC PPC4xx Crypto Driver + * + * Copyright (c) 2008 Applied Micro Circuits Corporation. + * All rights reserved. James Hsiao + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file implements the Linux crypto algorithms. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crypto4xx_reg_def.h" +#include "crypto4xx_sa.h" +#include "crypto4xx_core.h" + +void set_dynamic_sa_command_0(struct dynamic_sa_ctl *sa, u32 save_h, + u32 save_iv, u32 ld_h, u32 ld_iv, u32 hdr_proc, + u32 h, u32 c, u32 pad_type, u32 op_grp, u32 op, + u32 dir) +{ + sa->sa_command_0.w = 0; + sa->sa_command_0.bf.save_hash_state = save_h; + sa->sa_command_0.bf.save_iv = save_iv; + sa->sa_command_0.bf.load_hash_state = ld_h; + sa->sa_command_0.bf.load_iv = ld_iv; + sa->sa_command_0.bf.hdr_proc = hdr_proc; + sa->sa_command_0.bf.hash_alg = h; + sa->sa_command_0.bf.cipher_alg = c; + sa->sa_command_0.bf.pad_type = pad_type & 3; + sa->sa_command_0.bf.extend_pad = pad_type >> 2; + sa->sa_command_0.bf.op_group = op_grp; + sa->sa_command_0.bf.opcode = op; + sa->sa_command_0.bf.dir = dir; +} + +void set_dynamic_sa_command_1(struct dynamic_sa_ctl *sa, u32 cm, u32 hmac_mc, + u32 cfb, u32 esn, u32 sn_mask, u32 mute, + u32 cp_pad, u32 cp_pay, u32 cp_hdr) +{ + sa->sa_command_1.w = 0; + sa->sa_command_1.bf.crypto_mode31 = (cm & 4) >> 2; + sa->sa_command_1.bf.crypto_mode9_8 = cm & 3; + sa->sa_command_1.bf.feedback_mode = cfb, + sa->sa_command_1.bf.sa_rev = 1; + sa->sa_command_1.bf.extended_seq_num = esn; + sa->sa_command_1.bf.seq_num_mask = sn_mask; + sa->sa_command_1.bf.mutable_bit_proc = mute; + sa->sa_command_1.bf.copy_pad = cp_pad; + sa->sa_command_1.bf.copy_payload = cp_pay; + sa->sa_command_1.bf.copy_hdr = cp_hdr; +} + +int crypto4xx_encrypt(struct ablkcipher_request *req) +{ + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + + ctx->direction = DIR_OUTBOUND; + ctx->hash_final = 0; + ctx->is_hash = 0; + ctx->pd_ctl = 0x1; + + return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst, + req->nbytes, req->info, + get_dynamic_sa_iv_size(ctx)); +} + +int crypto4xx_decrypt(struct ablkcipher_request *req) +{ + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + + ctx->direction = DIR_INBOUND; + ctx->hash_final = 0; + ctx->is_hash = 0; + ctx->pd_ctl = 1; + + return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst, + req->nbytes, req->info, + get_dynamic_sa_iv_size(ctx)); +} + +/** + * AES Functions + */ +static int crypto4xx_setkey_aes(struct crypto_ablkcipher *cipher, + const u8 *key, + unsigned int keylen, + unsigned char cm, + u8 fb) +{ + struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher); + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm); + struct dynamic_sa_ctl *sa; + int rc; + + if (keylen != AES_KEYSIZE_256 && + keylen != AES_KEYSIZE_192 && keylen != AES_KEYSIZE_128) { + crypto_ablkcipher_set_flags(cipher, + CRYPTO_TFM_RES_BAD_KEY_LEN); + return -EINVAL; + } + + /* Create SA */ + if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr) + crypto4xx_free_sa(ctx); + + rc = crypto4xx_alloc_sa(ctx, SA_AES128_LEN + (keylen-16) / 4); + if (rc) + return rc; + + if (ctx->state_record_dma_addr == 0) { + rc = crypto4xx_alloc_state_record(ctx); + if (rc) { + crypto4xx_free_sa(ctx); + return rc; + } + } + /* Setup SA */ + sa = (struct dynamic_sa_ctl *) ctx->sa_in; + ctx->hash_final = 0; + + set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV, + SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE, + SA_NO_HEADER_PROC, SA_HASH_ALG_NULL, + SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO, + SA_OP_GROUP_BASIC, SA_OPCODE_DECRYPT, + DIR_INBOUND); + + set_dynamic_sa_command_1(sa, cm, SA_HASH_MODE_HASH, + fb, SA_EXTENDED_SN_OFF, + SA_SEQ_MASK_OFF, SA_MC_ENABLE, + SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD, + SA_NOT_COPY_HDR); + crypto4xx_memcpy_le(ctx->sa_in + get_dynamic_sa_offset_key_field(ctx), + key, keylen); + sa->sa_contents = SA_AES_CONTENTS | (keylen << 2); + sa->sa_command_1.bf.key_len = keylen >> 3; + ctx->is_hash = 0; + ctx->direction = DIR_INBOUND; + memcpy(ctx->sa_in + get_dynamic_sa_offset_state_ptr_field(ctx), + (void *)&ctx->state_record_dma_addr, 4); + ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(ctx); + + memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4); + sa = (struct dynamic_sa_ctl *) ctx->sa_out; + sa->sa_command_0.bf.dir = DIR_OUTBOUND; + + return 0; +} + +int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher, + const u8 *key, unsigned int keylen) +{ + return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_CBC, + CRYPTO_FEEDBACK_MODE_NO_FB); +} + +/** + * HASH SHA1 Functions + */ +static int crypto4xx_hash_alg_init(struct crypto_tfm *tfm, + unsigned int sa_len, + unsigned char ha, + unsigned char hm) +{ + struct crypto_alg *alg = tfm->__crt_alg; + struct crypto4xx_alg *my_alg = crypto_alg_to_crypto4xx_alg(alg); + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm); + struct dynamic_sa_ctl *sa; + struct dynamic_sa_hash160 *sa_in; + int rc; + + ctx->dev = my_alg->dev; + ctx->is_hash = 1; + ctx->hash_final = 0; + + /* Create SA */ + if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr) + crypto4xx_free_sa(ctx); + + rc = crypto4xx_alloc_sa(ctx, sa_len); + if (rc) + return rc; + + if (ctx->state_record_dma_addr == 0) { + crypto4xx_alloc_state_record(ctx); + if (!ctx->state_record_dma_addr) { + crypto4xx_free_sa(ctx); + return -ENOMEM; + } + } + + tfm->crt_ahash.reqsize = sizeof(struct crypto4xx_ctx); + sa = (struct dynamic_sa_ctl *) ctx->sa_in; + set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV, + SA_NOT_LOAD_HASH, SA_LOAD_IV_FROM_SA, + SA_NO_HEADER_PROC, ha, SA_CIPHER_ALG_NULL, + SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC, + SA_OPCODE_HASH, DIR_INBOUND); + set_dynamic_sa_command_1(sa, 0, SA_HASH_MODE_HASH, + CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF, + SA_SEQ_MASK_OFF, SA_MC_ENABLE, + SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD, + SA_NOT_COPY_HDR); + ctx->direction = DIR_INBOUND; + sa->sa_contents = SA_HASH160_CONTENTS; + sa_in = (struct dynamic_sa_hash160 *) ctx->sa_in; + /* Need to zero hash digest in SA */ + memset(sa_in->inner_digest, 0, sizeof(sa_in->inner_digest)); + memset(sa_in->outer_digest, 0, sizeof(sa_in->outer_digest)); + sa_in->state_ptr = ctx->state_record_dma_addr; + ctx->offset_to_sr_ptr = get_dynamic_sa_offset_state_ptr_field(ctx); + + return 0; +} + +int crypto4xx_hash_init(struct ahash_request *req) +{ + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + int ds; + struct dynamic_sa_ctl *sa; + + sa = (struct dynamic_sa_ctl *) ctx->sa_in; + ds = crypto_ahash_digestsize( + __crypto_ahash_cast(req->base.tfm)); + sa->sa_command_0.bf.digest_len = ds >> 2; + sa->sa_command_0.bf.load_hash_state = SA_LOAD_HASH_FROM_SA; + ctx->is_hash = 1; + ctx->direction = DIR_INBOUND; + + return 0; +} + +int crypto4xx_hash_update(struct ahash_request *req) +{ + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + + ctx->is_hash = 1; + ctx->hash_final = 0; + ctx->pd_ctl = 0x11; + ctx->direction = DIR_INBOUND; + + return crypto4xx_build_pd(&req->base, ctx, req->src, + (struct scatterlist *) req->result, + req->nbytes, NULL, 0); +} + +int crypto4xx_hash_final(struct ahash_request *req) +{ + return 0; +} + +int crypto4xx_hash_digest(struct ahash_request *req) +{ + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(req->base.tfm); + + ctx->hash_final = 1; + ctx->pd_ctl = 0x11; + ctx->direction = DIR_INBOUND; + + return crypto4xx_build_pd(&req->base, ctx, req->src, + (struct scatterlist *) req->result, + req->nbytes, NULL, 0); +} + +/** + * SHA1 Algorithm + */ +int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm) +{ + return crypto4xx_hash_alg_init(tfm, SA_HASH160_LEN, SA_HASH_ALG_SHA1, + SA_HASH_MODE_HASH); +} + + diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c new file mode 100644 index 00000000000..4c0dfb2b872 --- /dev/null +++ b/drivers/crypto/amcc/crypto4xx_core.c @@ -0,0 +1,1310 @@ +/** + * AMCC SoC PPC4xx Crypto Driver + * + * Copyright (c) 2008 Applied Micro Circuits Corporation. + * All rights reserved. James Hsiao + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file implements AMCC crypto offload Linux device driver for use with + * Linux CryptoAPI. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crypto4xx_reg_def.h" +#include "crypto4xx_core.h" +#include "crypto4xx_sa.h" + +#define PPC4XX_SEC_VERSION_STR "0.5" + +/** + * PPC4xx Crypto Engine Initialization Routine + */ +static void crypto4xx_hw_init(struct crypto4xx_device *dev) +{ + union ce_ring_size ring_size; + union ce_ring_contol ring_ctrl; + union ce_part_ring_size part_ring_size; + union ce_io_threshold io_threshold; + u32 rand_num; + union ce_pe_dma_cfg pe_dma_cfg; + + writel(PPC4XX_BYTE_ORDER, dev->ce_base + CRYPTO4XX_BYTE_ORDER_CFG); + /* setup pe dma, include reset sg, pdr and pe, then release reset */ + pe_dma_cfg.w = 0; + pe_dma_cfg.bf.bo_sgpd_en = 1; + pe_dma_cfg.bf.bo_data_en = 0; + pe_dma_cfg.bf.bo_sa_en = 1; + pe_dma_cfg.bf.bo_pd_en = 1; + pe_dma_cfg.bf.dynamic_sa_en = 1; + pe_dma_cfg.bf.reset_sg = 1; + pe_dma_cfg.bf.reset_pdr = 1; + pe_dma_cfg.bf.reset_pe = 1; + writel(pe_dma_cfg.w, dev->ce_base + CRYPTO4XX_PE_DMA_CFG); + /* un reset pe,sg and pdr */ + pe_dma_cfg.bf.pe_mode = 0; + pe_dma_cfg.bf.reset_sg = 0; + pe_dma_cfg.bf.reset_pdr = 0; + pe_dma_cfg.bf.reset_pe = 0; + pe_dma_cfg.bf.bo_td_en = 0; + writel(pe_dma_cfg.w, dev->ce_base + CRYPTO4XX_PE_DMA_CFG); + writel(dev->pdr_pa, dev->ce_base + CRYPTO4XX_PDR_BASE); + writel(dev->pdr_pa, dev->ce_base + CRYPTO4XX_RDR_BASE); + writel(PPC4XX_PRNG_CTRL_AUTO_EN, dev->ce_base + CRYPTO4XX_PRNG_CTRL); + get_random_bytes(&rand_num, sizeof(rand_num)); + writel(rand_num, dev->ce_base + CRYPTO4XX_PRNG_SEED_L); + get_random_bytes(&rand_num, sizeof(rand_num)); + writel(rand_num, dev->ce_base + CRYPTO4XX_PRNG_SEED_H); + ring_size.w = 0; + ring_size.bf.ring_offset = PPC4XX_PD_SIZE; + ring_size.bf.ring_size = PPC4XX_NUM_PD; + writel(ring_size.w, dev->ce_base + CRYPTO4XX_RING_SIZE); + ring_ctrl.w = 0; + writel(ring_ctrl.w, dev->ce_base + CRYPTO4XX_RING_CTRL); + writel(PPC4XX_DC_3DES_EN, dev->ce_base + CRYPTO4XX_DEVICE_CTRL); + writel(dev->gdr_pa, dev->ce_base + CRYPTO4XX_GATH_RING_BASE); + writel(dev->sdr_pa, dev->ce_base + CRYPTO4XX_SCAT_RING_BASE); + part_ring_size.w = 0; + part_ring_size.bf.sdr_size = PPC4XX_SDR_SIZE; + part_ring_size.bf.gdr_size = PPC4XX_GDR_SIZE; + writel(part_ring_size.w, dev->ce_base + CRYPTO4XX_PART_RING_SIZE); + writel(PPC4XX_SD_BUFFER_SIZE, dev->ce_base + CRYPTO4XX_PART_RING_CFG); + io_threshold.w = 0; + io_threshold.bf.output_threshold = PPC4XX_OUTPUT_THRESHOLD; + io_threshold.bf.input_threshold = PPC4XX_INPUT_THRESHOLD; + writel(io_threshold.w, dev->ce_base + CRYPTO4XX_IO_THRESHOLD); + writel(0, dev->ce_base + CRYPTO4XX_PDR_BASE_UADDR); + writel(0, dev->ce_base + CRYPTO4XX_RDR_BASE_UADDR); + writel(0, dev->ce_base + CRYPTO4XX_PKT_SRC_UADDR); + writel(0, dev->ce_base + CRYPTO4XX_PKT_DEST_UADDR); + writel(0, dev->ce_base + CRYPTO4XX_SA_UADDR); + writel(0, dev->ce_base + CRYPTO4XX_GATH_RING_BASE_UADDR); + writel(0, dev->ce_base + CRYPTO4XX_SCAT_RING_BASE_UADDR); + /* un reset pe,sg and pdr */ + pe_dma_cfg.bf.pe_mode = 1; + pe_dma_cfg.bf.reset_sg = 0; + pe_dma_cfg.bf.reset_pdr = 0; + pe_dma_cfg.bf.reset_pe = 0; + pe_dma_cfg.bf.bo_td_en = 0; + writel(pe_dma_cfg.w, dev->ce_base + CRYPTO4XX_PE_DMA_CFG); + /*clear all pending interrupt*/ + writel(PPC4XX_INTERRUPT_CLR, dev->ce_base + CRYPTO4XX_INT_CLR); + writel(PPC4XX_INT_DESCR_CNT, dev->ce_base + CRYPTO4XX_INT_DESCR_CNT); + writel(PPC4XX_INT_DESCR_CNT, dev->ce_base + CRYPTO4XX_INT_DESCR_CNT); + writel(PPC4XX_INT_CFG, dev->ce_base + CRYPTO4XX_INT_CFG); + writel(PPC4XX_PD_DONE_INT, dev->ce_base + CRYPTO4XX_INT_EN); +} + +int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size) +{ + ctx->sa_in = dma_alloc_coherent(ctx->dev->core_dev->device, size * 4, + &ctx->sa_in_dma_addr, GFP_ATOMIC); + if (ctx->sa_in == NULL) + return -ENOMEM; + + ctx->sa_out = dma_alloc_coherent(ctx->dev->core_dev->device, size * 4, + &ctx->sa_out_dma_addr, GFP_ATOMIC); + if (ctx->sa_out == NULL) { + dma_free_coherent(ctx->dev->core_dev->device, + ctx->sa_len * 4, + ctx->sa_in, ctx->sa_in_dma_addr); + return -ENOMEM; + } + + memset(ctx->sa_in, 0, size * 4); + memset(ctx->sa_out, 0, size * 4); + ctx->sa_len = size; + + return 0; +} + +void crypto4xx_free_sa(struct crypto4xx_ctx *ctx) +{ + if (ctx->sa_in != NULL) + dma_free_coherent(ctx->dev->core_dev->device, ctx->sa_len * 4, + ctx->sa_in, ctx->sa_in_dma_addr); + if (ctx->sa_out != NULL) + dma_free_coherent(ctx->dev->core_dev->device, ctx->sa_len * 4, + ctx->sa_out, ctx->sa_out_dma_addr); + + ctx->sa_in_dma_addr = 0; + ctx->sa_out_dma_addr = 0; + ctx->sa_len = 0; +} + +u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx) +{ + ctx->state_record = dma_alloc_coherent(ctx->dev->core_dev->device, + sizeof(struct sa_state_record), + &ctx->state_record_dma_addr, GFP_ATOMIC); + if (!ctx->state_record_dma_addr) + return -ENOMEM; + memset(ctx->state_record, 0, sizeof(struct sa_state_record)); + + return 0; +} + +void crypto4xx_free_state_record(struct crypto4xx_ctx *ctx) +{ + if (ctx->state_record != NULL) + dma_free_coherent(ctx->dev->core_dev->device, + sizeof(struct sa_state_record), + ctx->state_record, + ctx->state_record_dma_addr); + ctx->state_record_dma_addr = 0; +} + +/** + * alloc memory for the gather ring + * no need to alloc buf for the ring + * gdr_tail, gdr_head and gdr_count are initialized by this function + */ +static u32 crypto4xx_build_pdr(struct crypto4xx_device *dev) +{ + int i; + struct pd_uinfo *pd_uinfo; + dev->pdr = dma_alloc_coherent(dev->core_dev->device, + sizeof(struct ce_pd) * PPC4XX_NUM_PD, + &dev->pdr_pa, GFP_ATOMIC); + if (!dev->pdr) + return -ENOMEM; + + dev->pdr_uinfo = kzalloc(sizeof(struct pd_uinfo) * PPC4XX_NUM_PD, + GFP_KERNEL); + if (!dev->pdr_uinfo) { + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_pd) * PPC4XX_NUM_PD, + dev->pdr, + dev->pdr_pa); + return -ENOMEM; + } + memset(dev->pdr, 0, sizeof(struct ce_pd) * PPC4XX_NUM_PD); + dev->shadow_sa_pool = dma_alloc_coherent(dev->core_dev->device, + 256 * PPC4XX_NUM_PD, + &dev->shadow_sa_pool_pa, + GFP_ATOMIC); + if (!dev->shadow_sa_pool) + return -ENOMEM; + + dev->shadow_sr_pool = dma_alloc_coherent(dev->core_dev->device, + sizeof(struct sa_state_record) * PPC4XX_NUM_PD, + &dev->shadow_sr_pool_pa, GFP_ATOMIC); + if (!dev->shadow_sr_pool) + return -ENOMEM; + for (i = 0; i < PPC4XX_NUM_PD; i++) { + pd_uinfo = (struct pd_uinfo *) (dev->pdr_uinfo + + sizeof(struct pd_uinfo) * i); + + /* alloc 256 bytes which is enough for any kind of dynamic sa */ + pd_uinfo->sa_va = dev->shadow_sa_pool + 256 * i; + pd_uinfo->sa_pa = dev->shadow_sa_pool_pa + 256 * i; + + /* alloc state record */ + pd_uinfo->sr_va = dev->shadow_sr_pool + + sizeof(struct sa_state_record) * i; + pd_uinfo->sr_pa = dev->shadow_sr_pool_pa + + sizeof(struct sa_state_record) * i; + } + + return 0; +} + +static void crypto4xx_destroy_pdr(struct crypto4xx_device *dev) +{ + if (dev->pdr != NULL) + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_pd) * PPC4XX_NUM_PD, + dev->pdr, dev->pdr_pa); + if (dev->shadow_sa_pool) + dma_free_coherent(dev->core_dev->device, 256 * PPC4XX_NUM_PD, + dev->shadow_sa_pool, dev->shadow_sa_pool_pa); + if (dev->shadow_sr_pool) + dma_free_coherent(dev->core_dev->device, + sizeof(struct sa_state_record) * PPC4XX_NUM_PD, + dev->shadow_sr_pool, dev->shadow_sr_pool_pa); + + kfree(dev->pdr_uinfo); +} + +static u32 crypto4xx_get_pd_from_pdr_nolock(struct crypto4xx_device *dev) +{ + u32 retval; + u32 tmp; + + retval = dev->pdr_head; + tmp = (dev->pdr_head + 1) % PPC4XX_NUM_PD; + + if (tmp == dev->pdr_tail) + return ERING_WAS_FULL; + + dev->pdr_head = tmp; + + return retval; +} + +static u32 crypto4xx_put_pd_to_pdr(struct crypto4xx_device *dev, u32 idx) +{ + struct pd_uinfo *pd_uinfo; + unsigned long flags; + + pd_uinfo = (struct pd_uinfo *)(dev->pdr_uinfo + + sizeof(struct pd_uinfo) * idx); + spin_lock_irqsave(&dev->core_dev->lock, flags); + if (dev->pdr_tail != PPC4XX_LAST_PD) + dev->pdr_tail++; + else + dev->pdr_tail = 0; + pd_uinfo->state = PD_ENTRY_FREE; + spin_unlock_irqrestore(&dev->core_dev->lock, flags); + + return 0; +} + +static struct ce_pd *crypto4xx_get_pdp(struct crypto4xx_device *dev, + dma_addr_t *pd_dma, u32 idx) +{ + *pd_dma = dev->pdr_pa + sizeof(struct ce_pd) * idx; + + return dev->pdr + sizeof(struct ce_pd) * idx; +} + +/** + * alloc memory for the gather ring + * no need to alloc buf for the ring + * gdr_tail, gdr_head and gdr_count are initialized by this function + */ +static u32 crypto4xx_build_gdr(struct crypto4xx_device *dev) +{ + dev->gdr = dma_alloc_coherent(dev->core_dev->device, + sizeof(struct ce_gd) * PPC4XX_NUM_GD, + &dev->gdr_pa, GFP_ATOMIC); + if (!dev->gdr) + return -ENOMEM; + + memset(dev->gdr, 0, sizeof(struct ce_gd) * PPC4XX_NUM_GD); + + return 0; +} + +static inline void crypto4xx_destroy_gdr(struct crypto4xx_device *dev) +{ + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_gd) * PPC4XX_NUM_GD, + dev->gdr, dev->gdr_pa); +} + +/* + * when this function is called. + * preemption or interrupt must be disabled + */ +u32 crypto4xx_get_n_gd(struct crypto4xx_device *dev, int n) +{ + u32 retval; + u32 tmp; + if (n >= PPC4XX_NUM_GD) + return ERING_WAS_FULL; + + retval = dev->gdr_head; + tmp = (dev->gdr_head + n) % PPC4XX_NUM_GD; + if (dev->gdr_head > dev->gdr_tail) { + if (tmp < dev->gdr_head && tmp >= dev->gdr_tail) + return ERING_WAS_FULL; + } else if (dev->gdr_head < dev->gdr_tail) { + if (tmp < dev->gdr_head || tmp >= dev->gdr_tail) + return ERING_WAS_FULL; + } + dev->gdr_head = tmp; + + return retval; +} + +static u32 crypto4xx_put_gd_to_gdr(struct crypto4xx_device *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->core_dev->lock, flags); + if (dev->gdr_tail == dev->gdr_head) { + spin_unlock_irqrestore(&dev->core_dev->lock, flags); + return 0; + } + + if (dev->gdr_tail != PPC4XX_LAST_GD) + dev->gdr_tail++; + else + dev->gdr_tail = 0; + + spin_unlock_irqrestore(&dev->core_dev->lock, flags); + + return 0; +} + +static inline struct ce_gd *crypto4xx_get_gdp(struct crypto4xx_device *dev, + dma_addr_t *gd_dma, u32 idx) +{ + *gd_dma = dev->gdr_pa + sizeof(struct ce_gd) * idx; + + return (struct ce_gd *) (dev->gdr + sizeof(struct ce_gd) * idx); +} + +/** + * alloc memory for the scatter ring + * need to alloc buf for the ring + * sdr_tail, sdr_head and sdr_count are initialized by this function + */ +static u32 crypto4xx_build_sdr(struct crypto4xx_device *dev) +{ + int i; + struct ce_sd *sd_array; + + /* alloc memory for scatter descriptor ring */ + dev->sdr = dma_alloc_coherent(dev->core_dev->device, + sizeof(struct ce_sd) * PPC4XX_NUM_SD, + &dev->sdr_pa, GFP_ATOMIC); + if (!dev->sdr) + return -ENOMEM; + + dev->scatter_buffer_size = PPC4XX_SD_BUFFER_SIZE; + dev->scatter_buffer_va = + dma_alloc_coherent(dev->core_dev->device, + dev->scatter_buffer_size * PPC4XX_NUM_SD, + &dev->scatter_buffer_pa, GFP_ATOMIC); + if (!dev->scatter_buffer_va) { + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_sd) * PPC4XX_NUM_SD, + dev->sdr, dev->sdr_pa); + return -ENOMEM; + } + + sd_array = dev->sdr; + + for (i = 0; i < PPC4XX_NUM_SD; i++) { + sd_array[i].ptr = dev->scatter_buffer_pa + + dev->scatter_buffer_size * i; + } + + return 0; +} + +static void crypto4xx_destroy_sdr(struct crypto4xx_device *dev) +{ + if (dev->sdr != NULL) + dma_free_coherent(dev->core_dev->device, + sizeof(struct ce_sd) * PPC4XX_NUM_SD, + dev->sdr, dev->sdr_pa); + + if (dev->scatter_buffer_va != NULL) + dma_free_coherent(dev->core_dev->device, + dev->scatter_buffer_size * PPC4XX_NUM_SD, + dev->scatter_buffer_va, + dev->scatter_buffer_pa); +} + +/* + * when this function is called. + * preemption or interrupt must be disabled + */ +static u32 crypto4xx_get_n_sd(struct crypto4xx_device *dev, int n) +{ + u32 retval; + u32 tmp; + + if (n >= PPC4XX_NUM_SD) + return ERING_WAS_FULL; + + retval = dev->sdr_head; + tmp = (dev->sdr_head + n) % PPC4XX_NUM_SD; + if (dev->sdr_head > dev->gdr_tail) { + if (tmp < dev->sdr_head && tmp >= dev->sdr_tail) + return ERING_WAS_FULL; + } else if (dev->sdr_head < dev->sdr_tail) { + if (tmp < dev->sdr_head || tmp >= dev->sdr_tail) + return ERING_WAS_FULL; + } /* the head = tail, or empty case is already take cared */ + dev->sdr_head = tmp; + + return retval; +} + +static u32 crypto4xx_put_sd_to_sdr(struct crypto4xx_device *dev) +{ + unsigned long flags; + + spin_lock_irqsave(&dev->core_dev->lock, flags); + if (dev->sdr_tail == dev->sdr_head) { + spin_unlock_irqrestore(&dev->core_dev->lock, flags); + return 0; + } + if (dev->sdr_tail != PPC4XX_LAST_SD) + dev->sdr_tail++; + else + dev->sdr_tail = 0; + spin_unlock_irqrestore(&dev->core_dev->lock, flags); + + return 0; +} + +static inline struct ce_sd *crypto4xx_get_sdp(struct crypto4xx_device *dev, + dma_addr_t *sd_dma, u32 idx) +{ + *sd_dma = dev->sdr_pa + sizeof(struct ce_sd) * idx; + + return (struct ce_sd *)(dev->sdr + sizeof(struct ce_sd) * idx); +} + +static u32 crypto4xx_fill_one_page(struct crypto4xx_device *dev, + dma_addr_t *addr, u32 *length, + u32 *idx, u32 *offset, u32 *nbytes) +{ + u32 len; + + if (*length > dev->scatter_buffer_size) { + memcpy(phys_to_virt(*addr), + dev->scatter_buffer_va + + *idx * dev->scatter_buffer_size + *offset, + dev->scatter_buffer_size); + *offset = 0; + *length -= dev->scatter_buffer_size; + *nbytes -= dev->scatter_buffer_size; + if (*idx == PPC4XX_LAST_SD) + *idx = 0; + else + (*idx)++; + *addr = *addr + dev->scatter_buffer_size; + return 1; + } else if (*length < dev->scatter_buffer_size) { + memcpy(phys_to_virt(*addr), + dev->scatter_buffer_va + + *idx * dev->scatter_buffer_size + *offset, *length); + if ((*offset + *length) == dev->scatter_buffer_size) { + if (*idx == PPC4XX_LAST_SD) + *idx = 0; + else + (*idx)++; + *nbytes -= *length; + *offset = 0; + } else { + *nbytes -= *length; + *offset += *length; + } + + return 0; + } else { + len = (*nbytes <= dev->scatter_buffer_size) ? + (*nbytes) : dev->scatter_buffer_size; + memcpy(phys_to_virt(*addr), + dev->scatter_buffer_va + + *idx * dev->scatter_buffer_size + *offset, + len); + *offset = 0; + *nbytes -= len; + + if (*idx == PPC4XX_LAST_SD) + *idx = 0; + else + (*idx)++; + + return 0; + } +} + +static void crypto4xx_copy_pkt_to_dst(struct crypto4xx_device *dev, + struct ce_pd *pd, + struct pd_uinfo *pd_uinfo, + u32 nbytes, + struct scatterlist *dst) +{ + dma_addr_t addr; + u32 this_sd; + u32 offset; + u32 len; + u32 i; + u32 sg_len; + struct scatterlist *sg; + + this_sd = pd_uinfo->first_sd; + offset = 0; + i = 0; + + while (nbytes) { + sg = &dst[i]; + sg_len = sg->length; + addr = dma_map_page(dev->core_dev->device, sg_page(sg), + sg->offset, sg->length, DMA_TO_DEVICE); + + if (offset == 0) { + len = (nbytes <= sg->length) ? nbytes : sg->length; + while (crypto4xx_fill_one_page(dev, &addr, &len, + &this_sd, &offset, &nbytes)) + ; + if (!nbytes) + return; + i++; + } else { + len = (nbytes <= (dev->scatter_buffer_size - offset)) ? + nbytes : (dev->scatter_buffer_size - offset); + len = (sg->length < len) ? sg->length : len; + while (crypto4xx_fill_one_page(dev, &addr, &len, + &this_sd, &offset, &nbytes)) + ; + if (!nbytes) + return; + sg_len -= len; + if (sg_len) { + addr += len; + while (crypto4xx_fill_one_page(dev, &addr, + &sg_len, &this_sd, &offset, &nbytes)) + ; + } + i++; + } + } +} + +static u32 crypto4xx_copy_digest_to_dst(struct pd_uinfo *pd_uinfo, + struct crypto4xx_ctx *ctx) +{ + struct dynamic_sa_ctl *sa = (struct dynamic_sa_ctl *) ctx->sa_in; + struct sa_state_record *state_record = + (struct sa_state_record *) pd_uinfo->sr_va; + + if (sa->sa_command_0.bf.hash_alg == SA_HASH_ALG_SHA1) { + memcpy((void *) pd_uinfo->dest_va, state_record->save_digest, + SA_HASH_ALG_SHA1_DIGEST_SIZE); + } + + return 0; +} + +static void crypto4xx_ret_sg_desc(struct crypto4xx_device *dev, + struct pd_uinfo *pd_uinfo) +{ + int i; + if (pd_uinfo->num_gd) { + for (i = 0; i < pd_uinfo->num_gd; i++) + crypto4xx_put_gd_to_gdr(dev); + pd_uinfo->first_gd = 0xffffffff; + pd_uinfo->num_gd = 0; + } + if (pd_uinfo->num_sd) { + for (i = 0; i < pd_uinfo->num_sd; i++) + crypto4xx_put_sd_to_sdr(dev); + + pd_uinfo->first_sd = 0xffffffff; + pd_uinfo->num_sd = 0; + } +} + +static u32 crypto4xx_ablkcipher_done(struct crypto4xx_device *dev, + struct pd_uinfo *pd_uinfo, + struct ce_pd *pd) +{ + struct crypto4xx_ctx *ctx; + struct ablkcipher_request *ablk_req; + struct scatterlist *dst; + dma_addr_t addr; + + ablk_req = ablkcipher_request_cast(pd_uinfo->async_req); + ctx = crypto_tfm_ctx(ablk_req->base.tfm); + + if (pd_uinfo->using_sd) { + crypto4xx_copy_pkt_to_dst(dev, pd, pd_uinfo, ablk_req->nbytes, + ablk_req->dst); + } else { + dst = pd_uinfo->dest_va; + addr = dma_map_page(dev->core_dev->device, sg_page(dst), + dst->offset, dst->length, DMA_FROM_DEVICE); + } + crypto4xx_ret_sg_desc(dev, pd_uinfo); + if (ablk_req->base.complete != NULL) + ablk_req->base.complete(&ablk_req->base, 0); + + return 0; +} + +static u32 crypto4xx_ahash_done(struct crypto4xx_device *dev, + struct pd_uinfo *pd_uinfo) +{ + struct crypto4xx_ctx *ctx; + struct ahash_request *ahash_req; + + ahash_req = ahash_request_cast(pd_uinfo->async_req); + ctx = crypto_tfm_ctx(ahash_req->base.tfm); + + crypto4xx_copy_digest_to_dst(pd_uinfo, + crypto_tfm_ctx(ahash_req->base.tfm)); + crypto4xx_ret_sg_desc(dev, pd_uinfo); + /* call user provided callback function x */ + if (ahash_req->base.complete != NULL) + ahash_req->base.complete(&ahash_req->base, 0); + + return 0; +} + +static u32 crypto4xx_pd_done(struct crypto4xx_device *dev, u32 idx) +{ + struct ce_pd *pd; + struct pd_uinfo *pd_uinfo; + + pd = dev->pdr + sizeof(struct ce_pd)*idx; + pd_uinfo = dev->pdr_uinfo + sizeof(struct pd_uinfo)*idx; + if (crypto_tfm_alg_type(pd_uinfo->async_req->tfm) == + CRYPTO_ALG_TYPE_ABLKCIPHER) + return crypto4xx_ablkcipher_done(dev, pd_uinfo, pd); + else + return crypto4xx_ahash_done(dev, pd_uinfo); +} + +/** + * Note: Only use this function to copy items that is word aligned. + */ +void crypto4xx_memcpy_le(unsigned int *dst, + const unsigned char *buf, + int len) +{ + u8 *tmp; + for (; len >= 4; buf += 4, len -= 4) + *dst++ = cpu_to_le32(*(unsigned int *) buf); + + tmp = (u8 *)dst; + switch (len) { + case 3: + *tmp++ = 0; + *tmp++ = *(buf+2); + *tmp++ = *(buf+1); + *tmp++ = *buf; + break; + case 2: + *tmp++ = 0; + *tmp++ = 0; + *tmp++ = *(buf+1); + *tmp++ = *buf; + break; + case 1: + *tmp++ = 0; + *tmp++ = 0; + *tmp++ = 0; + *tmp++ = *buf; + break; + default: + break; + } +} + +static void crypto4xx_stop_all(struct crypto4xx_core_device *core_dev) +{ + crypto4xx_destroy_pdr(core_dev->dev); + crypto4xx_destroy_gdr(core_dev->dev); + crypto4xx_destroy_sdr(core_dev->dev); + dev_set_drvdata(core_dev->device, NULL); + iounmap(core_dev->dev->ce_base); + kfree(core_dev->dev); + kfree(core_dev); +} + +void crypto4xx_return_pd(struct crypto4xx_device *dev, + u32 pd_entry, struct ce_pd *pd, + struct pd_uinfo *pd_uinfo) +{ + /* irq should be already disabled */ + dev->pdr_head = pd_entry; + pd->pd_ctl.w = 0; + pd->pd_ctl_len.w = 0; + pd_uinfo->state = PD_ENTRY_FREE; +} + +/* + * derive number of elements in scatterlist + * Shamlessly copy from talitos.c + */ +static int get_sg_count(struct scatterlist *sg_list, int nbytes) +{ + struct scatterlist *sg = sg_list; + int sg_nents = 0; + + while (nbytes) { + sg_nents++; + if (sg->length > nbytes) + break; + nbytes -= sg->length; + sg = sg_next(sg); + } + + return sg_nents; +} + +static u32 get_next_gd(u32 current) +{ + if (current != PPC4XX_LAST_GD) + return current + 1; + else + return 0; +} + +static u32 get_next_sd(u32 current) +{ + if (current != PPC4XX_LAST_SD) + return current + 1; + else + return 0; +} + +u32 crypto4xx_build_pd(struct crypto_async_request *req, + struct crypto4xx_ctx *ctx, + struct scatterlist *src, + struct scatterlist *dst, + unsigned int datalen, + void *iv, u32 iv_len) +{ + struct crypto4xx_device *dev = ctx->dev; + dma_addr_t addr, pd_dma, sd_dma, gd_dma; + struct dynamic_sa_ctl *sa; + struct scatterlist *sg; + struct ce_gd *gd; + struct ce_pd *pd; + u32 num_gd, num_sd; + u32 fst_gd = 0xffffffff; + u32 fst_sd = 0xffffffff; + u32 pd_entry; + unsigned long flags; + struct pd_uinfo *pd_uinfo = NULL; + unsigned int nbytes = datalen, idx; + unsigned int ivlen = 0; + u32 gd_idx = 0; + + /* figure how many gd is needed */ + num_gd = get_sg_count(src, datalen); + if (num_gd == 1) + num_gd = 0; + + /* figure how many sd is needed */ + if (sg_is_last(dst) || ctx->is_hash) { + num_sd = 0; + } else { + if (datalen > PPC4XX_SD_BUFFER_SIZE) { + num_sd = datalen / PPC4XX_SD_BUFFER_SIZE; + if (datalen % PPC4XX_SD_BUFFER_SIZE) + num_sd++; + } else { + num_sd = 1; + } + } + + /* + * The follow section of code needs to be protected + * The gather ring and scatter ring needs to be consecutive + * In case of run out of any kind of descriptor, the descriptor + * already got must be return the original place. + */ + spin_lock_irqsave(&dev->core_dev->lock, flags); + if (num_gd) { + fst_gd = crypto4xx_get_n_gd(dev, num_gd); + if (fst_gd == ERING_WAS_FULL) { + spin_unlock_irqrestore(&dev->core_dev->lock, flags); + return -EAGAIN; + } + } + if (num_sd) { + fst_sd = crypto4xx_get_n_sd(dev, num_sd); + if (fst_sd == ERING_WAS_FULL) { + if (num_gd) + dev->gdr_head = fst_gd; + spin_unlock_irqrestore(&dev->core_dev->lock, flags); + return -EAGAIN; + } + } + pd_entry = crypto4xx_get_pd_from_pdr_nolock(dev); + if (pd_entry == ERING_WAS_FULL) { + if (num_gd) + dev->gdr_head = fst_gd; + if (num_sd) + dev->sdr_head = fst_sd; + spin_unlock_irqrestore(&dev->core_dev->lock, flags); + return -EAGAIN; + } + spin_unlock_irqrestore(&dev->core_dev->lock, flags); + + pd_uinfo = (struct pd_uinfo *)(dev->pdr_uinfo + + sizeof(struct pd_uinfo) * pd_entry); + pd = crypto4xx_get_pdp(dev, &pd_dma, pd_entry); + pd_uinfo->async_req = req; + pd_uinfo->num_gd = num_gd; + pd_uinfo->num_sd = num_sd; + + if (iv_len || ctx->is_hash) { + ivlen = iv_len; + pd->sa = pd_uinfo->sa_pa; + sa = (struct dynamic_sa_ctl *) pd_uinfo->sa_va; + if (ctx->direction == DIR_INBOUND) + memcpy(sa, ctx->sa_in, ctx->sa_len * 4); + else + memcpy(sa, ctx->sa_out, ctx->sa_len * 4); + + memcpy((void *) sa + ctx->offset_to_sr_ptr, + &pd_uinfo->sr_pa, 4); + + if (iv_len) + crypto4xx_memcpy_le(pd_uinfo->sr_va, iv, iv_len); + } else { + if (ctx->direction == DIR_INBOUND) { + pd->sa = ctx->sa_in_dma_addr; + sa = (struct dynamic_sa_ctl *) ctx->sa_in; + } else { + pd->sa = ctx->sa_out_dma_addr; + sa = (struct dynamic_sa_ctl *) ctx->sa_out; + } + } + pd->sa_len = ctx->sa_len; + if (num_gd) { + /* get first gd we are going to use */ + gd_idx = fst_gd; + pd_uinfo->first_gd = fst_gd; + pd_uinfo->num_gd = num_gd; + gd = crypto4xx_get_gdp(dev, &gd_dma, gd_idx); + pd->src = gd_dma; + /* enable gather */ + sa->sa_command_0.bf.gather = 1; + idx = 0; + src = &src[0]; + /* walk the sg, and setup gather array */ + while (nbytes) { + sg = &src[idx]; + addr = dma_map_page(dev->core_dev->device, sg_page(sg), + sg->offset, sg->length, DMA_TO_DEVICE); + gd->ptr = addr; + gd->ctl_len.len = sg->length; + gd->ctl_len.done = 0; + gd->ctl_len.ready = 1; + if (sg->length >= nbytes) + break; + nbytes -= sg->length; + gd_idx = get_next_gd(gd_idx); + gd = crypto4xx_get_gdp(dev, &gd_dma, gd_idx); + idx++; + } + } else { + pd->src = (u32)dma_map_page(dev->core_dev->device, sg_page(src), + src->offset, src->length, DMA_TO_DEVICE); + /* + * Disable gather in sa command + */ + sa->sa_command_0.bf.gather = 0; + /* + * Indicate gather array is not used + */ + pd_uinfo->first_gd = 0xffffffff; + pd_uinfo->num_gd = 0; + } + if (ctx->is_hash || sg_is_last(dst)) { + /* + * we know application give us dst a whole piece of memory + * no need to use scatter ring. + * In case of is_hash, the icv is always at end of src data. + */ + pd_uinfo->using_sd = 0; + pd_uinfo->first_sd = 0xffffffff; + pd_uinfo->num_sd = 0; + pd_uinfo->dest_va = dst; + sa->sa_command_0.bf.scatter = 0; + if (ctx->is_hash) + pd->dest = virt_to_phys((void *)dst); + else + pd->dest = (u32)dma_map_page(dev->core_dev->device, + sg_page(dst), dst->offset, + dst->length, DMA_TO_DEVICE); + } else { + struct ce_sd *sd = NULL; + u32 sd_idx = fst_sd; + nbytes = datalen; + sa->sa_command_0.bf.scatter = 1; + pd_uinfo->using_sd = 1; + pd_uinfo->dest_va = dst; + pd_uinfo->first_sd = fst_sd; + pd_uinfo->num_sd = num_sd; + sd = crypto4xx_get_sdp(dev, &sd_dma, sd_idx); + pd->dest = sd_dma; + /* setup scatter descriptor */ + sd->ctl.done = 0; + sd->ctl.rdy = 1; + /* sd->ptr should be setup by sd_init routine*/ + idx = 0; + if (nbytes >= PPC4XX_SD_BUFFER_SIZE) + nbytes -= PPC4XX_SD_BUFFER_SIZE; + else + nbytes = 0; + while (nbytes) { + sd_idx = get_next_sd(sd_idx); + sd = crypto4xx_get_sdp(dev, &sd_dma, sd_idx); + /* setup scatter descriptor */ + sd->ctl.done = 0; + sd->ctl.rdy = 1; + if (nbytes >= PPC4XX_SD_BUFFER_SIZE) + nbytes -= PPC4XX_SD_BUFFER_SIZE; + else + /* + * SD entry can hold PPC4XX_SD_BUFFER_SIZE, + * which is more than nbytes, so done. + */ + nbytes = 0; + } + } + + sa->sa_command_1.bf.hash_crypto_offset = 0; + pd->pd_ctl.w = ctx->pd_ctl; + pd->pd_ctl_len.w = 0x00400000 | (ctx->bypass << 24) | datalen; + pd_uinfo->state = PD_ENTRY_INUSE; + wmb(); + /* write any value to push engine to read a pd */ + writel(1, dev->ce_base + CRYPTO4XX_INT_DESCR_RD); + return -EINPROGRESS; +} + +/** + * Algorithm Registration Functions + */ +static int crypto4xx_alg_init(struct crypto_tfm *tfm) +{ + struct crypto_alg *alg = tfm->__crt_alg; + struct crypto4xx_alg *amcc_alg = crypto_alg_to_crypto4xx_alg(alg); + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm); + + ctx->dev = amcc_alg->dev; + ctx->sa_in = NULL; + ctx->sa_out = NULL; + ctx->sa_in_dma_addr = 0; + ctx->sa_out_dma_addr = 0; + ctx->sa_len = 0; + + if (alg->cra_type == &crypto_ablkcipher_type) + tfm->crt_ablkcipher.reqsize = sizeof(struct crypto4xx_ctx); + else if (alg->cra_type == &crypto_ahash_type) + tfm->crt_ahash.reqsize = sizeof(struct crypto4xx_ctx); + + return 0; +} + +static void crypto4xx_alg_exit(struct crypto_tfm *tfm) +{ + struct crypto4xx_ctx *ctx = crypto_tfm_ctx(tfm); + + crypto4xx_free_sa(ctx); + crypto4xx_free_state_record(ctx); +} + +int crypto4xx_register_alg(struct crypto4xx_device *sec_dev, + struct crypto_alg *crypto_alg, int array_size) +{ + struct crypto4xx_alg *alg; + int i; + int rc = 0; + + for (i = 0; i < array_size; i++) { + alg = kzalloc(sizeof(struct crypto4xx_alg), GFP_KERNEL); + if (!alg) + return -ENOMEM; + + alg->alg = crypto_alg[i]; + INIT_LIST_HEAD(&alg->alg.cra_list); + if (alg->alg.cra_init == NULL) + alg->alg.cra_init = crypto4xx_alg_init; + if (alg->alg.cra_exit == NULL) + alg->alg.cra_exit = crypto4xx_alg_exit; + alg->dev = sec_dev; + rc = crypto_register_alg(&alg->alg); + if (rc) { + list_del(&alg->entry); + kfree(alg); + } else { + list_add_tail(&alg->entry, &sec_dev->alg_list); + } + } + + return 0; +} + +static void crypto4xx_unregister_alg(struct crypto4xx_device *sec_dev) +{ + struct crypto4xx_alg *alg, *tmp; + + list_for_each_entry_safe(alg, tmp, &sec_dev->alg_list, entry) { + list_del(&alg->entry); + crypto_unregister_alg(&alg->alg); + kfree(alg); + } +} + +static void crypto4xx_bh_tasklet_cb(unsigned long data) +{ + struct device *dev = (struct device *)data; + struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); + struct pd_uinfo *pd_uinfo; + struct ce_pd *pd; + u32 tail; + + while (core_dev->dev->pdr_head != core_dev->dev->pdr_tail) { + tail = core_dev->dev->pdr_tail; + pd_uinfo = core_dev->dev->pdr_uinfo + + sizeof(struct pd_uinfo)*tail; + pd = core_dev->dev->pdr + sizeof(struct ce_pd) * tail; + if ((pd_uinfo->state == PD_ENTRY_INUSE) && + pd->pd_ctl.bf.pe_done && + !pd->pd_ctl.bf.host_ready) { + pd->pd_ctl.bf.pe_done = 0; + crypto4xx_pd_done(core_dev->dev, tail); + crypto4xx_put_pd_to_pdr(core_dev->dev, tail); + pd_uinfo->state = PD_ENTRY_FREE; + } else { + /* if tail not done, break */ + break; + } + } +} + +/** + * Top Half of isr. + */ +static irqreturn_t crypto4xx_ce_interrupt_handler(int irq, void *data) +{ + struct device *dev = (struct device *)data; + struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); + + if (core_dev->dev->ce_base == 0) + return 0; + + writel(PPC4XX_INTERRUPT_CLR, + core_dev->dev->ce_base + CRYPTO4XX_INT_CLR); + tasklet_schedule(&core_dev->tasklet); + + return IRQ_HANDLED; +} + +/** + * Supported Crypto Algorithms + */ +struct crypto_alg crypto4xx_alg[] = { + /* Crypto AES modes */ + { + .cra_name = "cbc(aes)", + .cra_driver_name = "cbc-aes-ppc4xx", + .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY, + .cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC, + .cra_blocksize = AES_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypto4xx_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ablkcipher_type, + .cra_module = THIS_MODULE, + .cra_u = { + .ablkcipher = { + .min_keysize = AES_MIN_KEY_SIZE, + .max_keysize = AES_MAX_KEY_SIZE, + .ivsize = AES_IV_SIZE, + .setkey = crypto4xx_setkey_aes_cbc, + .encrypt = crypto4xx_encrypt, + .decrypt = crypto4xx_decrypt, + } + } + }, + /* Hash SHA1 */ + { + .cra_name = "sha1", + .cra_driver_name = "sha1-ppc4xx", + .cra_priority = CRYPTO4XX_CRYPTO_PRIORITY, + .cra_flags = CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC, + .cra_blocksize = SHA1_BLOCK_SIZE, + .cra_ctxsize = sizeof(struct crypto4xx_ctx), + .cra_alignmask = 0, + .cra_type = &crypto_ahash_type, + .cra_init = crypto4xx_sha1_alg_init, + .cra_module = THIS_MODULE, + .cra_u = { + .ahash = { + .digestsize = SHA1_DIGEST_SIZE, + .init = crypto4xx_hash_init, + .update = crypto4xx_hash_update, + .final = crypto4xx_hash_final, + .digest = crypto4xx_hash_digest, + } + } + }, +}; + +/** + * Module Initialization Routine + */ +static int __init crypto4xx_probe(struct of_device *ofdev, + const struct of_device_id *match) +{ + int rc; + struct resource res; + struct device *dev = &ofdev->dev; + struct crypto4xx_core_device *core_dev; + + rc = of_address_to_resource(ofdev->node, 0, &res); + if (rc) + return -ENODEV; + + if (of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-crypto")) { + mtdcri(SDR0, PPC460EX_SDR0_SRST, + mfdcri(SDR0, PPC460EX_SDR0_SRST) | PPC460EX_CE_RESET); + mtdcri(SDR0, PPC460EX_SDR0_SRST, + mfdcri(SDR0, PPC460EX_SDR0_SRST) & ~PPC460EX_CE_RESET); + } else if (of_find_compatible_node(NULL, NULL, + "amcc,ppc405ex-crypto")) { + mtdcri(SDR0, PPC405EX_SDR0_SRST, + mfdcri(SDR0, PPC405EX_SDR0_SRST) | PPC405EX_CE_RESET); + mtdcri(SDR0, PPC405EX_SDR0_SRST, + mfdcri(SDR0, PPC405EX_SDR0_SRST) & ~PPC405EX_CE_RESET); + } else if (of_find_compatible_node(NULL, NULL, + "amcc,ppc460sx-crypto")) { + mtdcri(SDR0, PPC460SX_SDR0_SRST, + mfdcri(SDR0, PPC460SX_SDR0_SRST) | PPC460SX_CE_RESET); + mtdcri(SDR0, PPC460SX_SDR0_SRST, + mfdcri(SDR0, PPC460SX_SDR0_SRST) & ~PPC460SX_CE_RESET); + } else { + printk(KERN_ERR "Crypto Function Not supported!\n"); + return -EINVAL; + } + + core_dev = kzalloc(sizeof(struct crypto4xx_core_device), GFP_KERNEL); + if (!core_dev) + return -ENOMEM; + + dev_set_drvdata(dev, core_dev); + core_dev->ofdev = ofdev; + core_dev->dev = kzalloc(sizeof(struct crypto4xx_device), GFP_KERNEL); + if (!core_dev->dev) + goto err_alloc_dev; + + core_dev->dev->core_dev = core_dev; + core_dev->device = dev; + spin_lock_init(&core_dev->lock); + INIT_LIST_HEAD(&core_dev->dev->alg_list); + rc = crypto4xx_build_pdr(core_dev->dev); + if (rc) + goto err_build_pdr; + + rc = crypto4xx_build_gdr(core_dev->dev); + if (rc) + goto err_build_gdr; + + rc = crypto4xx_build_sdr(core_dev->dev); + if (rc) + goto err_build_sdr; + + /* Init tasklet for bottom half processing */ + tasklet_init(&core_dev->tasklet, crypto4xx_bh_tasklet_cb, + (unsigned long) dev); + + /* Register for Crypto isr, Crypto Engine IRQ */ + core_dev->irq = irq_of_parse_and_map(ofdev->node, 0); + rc = request_irq(core_dev->irq, crypto4xx_ce_interrupt_handler, 0, + core_dev->dev->name, dev); + if (rc) + goto err_request_irq; + + core_dev->dev->ce_base = of_iomap(ofdev->node, 0); + if (!core_dev->dev->ce_base) { + dev_err(dev, "failed to of_iomap\n"); + goto err_iomap; + } + + /* need to setup pdr, rdr, gdr and sdr before this */ + crypto4xx_hw_init(core_dev->dev); + + /* Register security algorithms with Linux CryptoAPI */ + rc = crypto4xx_register_alg(core_dev->dev, crypto4xx_alg, + ARRAY_SIZE(crypto4xx_alg)); + if (rc) + goto err_start_dev; + + return 0; + +err_start_dev: + iounmap(core_dev->dev->ce_base); +err_iomap: + free_irq(core_dev->irq, dev); + irq_dispose_mapping(core_dev->irq); + tasklet_kill(&core_dev->tasklet); +err_request_irq: + crypto4xx_destroy_sdr(core_dev->dev); +err_build_sdr: + crypto4xx_destroy_gdr(core_dev->dev); +err_build_gdr: + crypto4xx_destroy_pdr(core_dev->dev); +err_build_pdr: + kfree(core_dev->dev); +err_alloc_dev: + kfree(core_dev); + + return rc; +} + +static int __exit crypto4xx_remove(struct of_device *ofdev) +{ + struct device *dev = &ofdev->dev; + struct crypto4xx_core_device *core_dev = dev_get_drvdata(dev); + + free_irq(core_dev->irq, dev); + irq_dispose_mapping(core_dev->irq); + + tasklet_kill(&core_dev->tasklet); + /* Un-register with Linux CryptoAPI */ + crypto4xx_unregister_alg(core_dev->dev); + /* Free all allocated memory */ + crypto4xx_stop_all(core_dev); + + return 0; +} + +static struct of_device_id crypto4xx_match[] = { + { .compatible = "amcc,ppc4xx-crypto",}, + { }, +}; + +static struct of_platform_driver crypto4xx_driver = { + .name = "crypto4xx", + .match_table = crypto4xx_match, + .probe = crypto4xx_probe, + .remove = crypto4xx_remove, +}; + +static int __init crypto4xx_init(void) +{ + return of_register_platform_driver(&crypto4xx_driver); +} + +static void __exit crypto4xx_exit(void) +{ + of_unregister_platform_driver(&crypto4xx_driver); +} + +module_init(crypto4xx_init); +module_exit(crypto4xx_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("James Hsiao "); +MODULE_DESCRIPTION("Driver for AMCC PPC4xx crypto accelerator"); + diff --git a/drivers/crypto/amcc/crypto4xx_core.h b/drivers/crypto/amcc/crypto4xx_core.h new file mode 100644 index 00000000000..1ef10344936 --- /dev/null +++ b/drivers/crypto/amcc/crypto4xx_core.h @@ -0,0 +1,177 @@ +/** + * AMCC SoC PPC4xx Crypto Driver + * + * Copyright (c) 2008 Applied Micro Circuits Corporation. + * All rights reserved. James Hsiao + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This is the header file for AMCC Crypto offload Linux device driver for + * use with Linux CryptoAPI. + + */ + +#ifndef __CRYPTO4XX_CORE_H__ +#define __CRYPTO4XX_CORE_H__ + +#define PPC460SX_SDR0_SRST 0x201 +#define PPC405EX_SDR0_SRST 0x200 +#define PPC460EX_SDR0_SRST 0x201 +#define PPC460EX_CE_RESET 0x08000000 +#define PPC460SX_CE_RESET 0x20000000 +#define PPC405EX_CE_RESET 0x00000008 + +#define CRYPTO4XX_CRYPTO_PRIORITY 300 +#define PPC4XX_LAST_PD 63 +#define PPC4XX_NUM_PD 64 +#define PPC4XX_LAST_GD 1023 +#define PPC4XX_NUM_GD 1024 +#define PPC4XX_LAST_SD 63 +#define PPC4XX_NUM_SD 64 +#define PPC4XX_SD_BUFFER_SIZE 2048 + +#define PD_ENTRY_INUSE 1 +#define PD_ENTRY_FREE 0 +#define ERING_WAS_FULL 0xffffffff + +struct crypto4xx_device; + +struct pd_uinfo { + struct crypto4xx_device *dev; + u32 state; + u32 using_sd; + u32 first_gd; /* first gather discriptor + used by this packet */ + u32 num_gd; /* number of gather discriptor + used by this packet */ + u32 first_sd; /* first scatter discriptor + used by this packet */ + u32 num_sd; /* number of scatter discriptors + used by this packet */ + void *sa_va; /* shadow sa, when using cp from ctx->sa */ + u32 sa_pa; + void *sr_va; /* state record for shadow sa */ + u32 sr_pa; + struct scatterlist *dest_va; + struct crypto_async_request *async_req; /* base crypto request + for this packet */ +}; + +struct crypto4xx_device { + struct crypto4xx_core_device *core_dev; + char *name; + u64 ce_phy_address; + void __iomem *ce_base; + + void *pdr; /* base address of packet + descriptor ring */ + dma_addr_t pdr_pa; /* physical address used to + program ce pdr_base_register */ + void *gdr; /* gather descriptor ring */ + dma_addr_t gdr_pa; /* physical address used to + program ce gdr_base_register */ + void *sdr; /* scatter descriptor ring */ + dma_addr_t sdr_pa; /* physical address used to + program ce sdr_base_register */ + void *scatter_buffer_va; + dma_addr_t scatter_buffer_pa; + u32 scatter_buffer_size; + + void *shadow_sa_pool; /* pool of memory for sa in pd_uinfo */ + dma_addr_t shadow_sa_pool_pa; + void *shadow_sr_pool; /* pool of memory for sr in pd_uinfo */ + dma_addr_t shadow_sr_pool_pa; + u32 pdr_tail; + u32 pdr_head; + u32 gdr_tail; + u32 gdr_head; + u32 sdr_tail; + u32 sdr_head; + void *pdr_uinfo; + struct list_head alg_list; /* List of algorithm supported + by this device */ +}; + +struct crypto4xx_core_device { + struct device *device; + struct of_device *ofdev; + struct crypto4xx_device *dev; + u32 int_status; + u32 irq; + struct tasklet_struct tasklet; + spinlock_t lock; +}; + +struct crypto4xx_ctx { + struct crypto4xx_device *dev; + void *sa_in; + dma_addr_t sa_in_dma_addr; + void *sa_out; + dma_addr_t sa_out_dma_addr; + void *state_record; + dma_addr_t state_record_dma_addr; + u32 sa_len; + u32 offset_to_sr_ptr; /* offset to state ptr, in dynamic sa */ + u32 direction; + u32 next_hdr; + u32 save_iv; + u32 pd_ctl_len; + u32 pd_ctl; + u32 bypass; + u32 is_hash; + u32 hash_final; +}; + +struct crypto4xx_req_ctx { + struct crypto4xx_device *dev; /* Device in which + operation to send to */ + void *sa; + u32 sa_dma_addr; + u16 sa_len; +}; + +struct crypto4xx_alg { + struct list_head entry; + struct crypto_alg alg; + struct crypto4xx_device *dev; +}; + +#define crypto_alg_to_crypto4xx_alg(x) \ + container_of(x, struct crypto4xx_alg, alg) + +extern int crypto4xx_alloc_sa(struct crypto4xx_ctx *ctx, u32 size); +extern void crypto4xx_free_sa(struct crypto4xx_ctx *ctx); +extern u32 crypto4xx_alloc_sa_rctx(struct crypto4xx_ctx *ctx, + struct crypto4xx_ctx *rctx); +extern void crypto4xx_free_sa_rctx(struct crypto4xx_ctx *rctx); +extern void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx); +extern u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx); +extern u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx *ctx); +extern u32 get_dynamic_sa_offset_key_field(struct crypto4xx_ctx *ctx); +extern u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx); +extern void crypto4xx_memcpy_le(unsigned int *dst, + const unsigned char *buf, int len); +extern u32 crypto4xx_build_pd(struct crypto_async_request *req, + struct crypto4xx_ctx *ctx, + struct scatterlist *src, + struct scatterlist *dst, + unsigned int datalen, + void *iv, u32 iv_len); +extern int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher, + const u8 *key, unsigned int keylen); +extern int crypto4xx_encrypt(struct ablkcipher_request *req); +extern int crypto4xx_decrypt(struct ablkcipher_request *req); +extern int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm); +extern int crypto4xx_hash_digest(struct ahash_request *req); +extern int crypto4xx_hash_final(struct ahash_request *req); +extern int crypto4xx_hash_update(struct ahash_request *req); +extern int crypto4xx_hash_init(struct ahash_request *req); +#endif diff --git a/drivers/crypto/amcc/crypto4xx_reg_def.h b/drivers/crypto/amcc/crypto4xx_reg_def.h new file mode 100644 index 00000000000..7d4edb00261 --- /dev/null +++ b/drivers/crypto/amcc/crypto4xx_reg_def.h @@ -0,0 +1,284 @@ +/** + * AMCC SoC PPC4xx Crypto Driver + * + * Copyright (c) 2008 Applied Micro Circuits Corporation. + * All rights reserved. James Hsiao + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This filr defines the register set for Security Subsystem + */ + +#ifndef __CRYPTO4XX_REG_DEF_H__ +#define __CRYPTO4XX_REG_DEF_H__ + +/* CRYPTO4XX Register offset */ +#define CRYPTO4XX_DESCRIPTOR 0x00000000 +#define CRYPTO4XX_CTRL_STAT 0x00000000 +#define CRYPTO4XX_SOURCE 0x00000004 +#define CRYPTO4XX_DEST 0x00000008 +#define CRYPTO4XX_SA 0x0000000C +#define CRYPTO4XX_SA_LENGTH 0x00000010 +#define CRYPTO4XX_LENGTH 0x00000014 + +#define CRYPTO4XX_PE_DMA_CFG 0x00000040 +#define CRYPTO4XX_PE_DMA_STAT 0x00000044 +#define CRYPTO4XX_PDR_BASE 0x00000048 +#define CRYPTO4XX_RDR_BASE 0x0000004c +#define CRYPTO4XX_RING_SIZE 0x00000050 +#define CRYPTO4XX_RING_CTRL 0x00000054 +#define CRYPTO4XX_INT_RING_STAT 0x00000058 +#define CRYPTO4XX_EXT_RING_STAT 0x0000005c +#define CRYPTO4XX_IO_THRESHOLD 0x00000060 +#define CRYPTO4XX_GATH_RING_BASE 0x00000064 +#define CRYPTO4XX_SCAT_RING_BASE 0x00000068 +#define CRYPTO4XX_PART_RING_SIZE 0x0000006c +#define CRYPTO4XX_PART_RING_CFG 0x00000070 + +#define CRYPTO4XX_PDR_BASE_UADDR 0x00000080 +#define CRYPTO4XX_RDR_BASE_UADDR 0x00000084 +#define CRYPTO4XX_PKT_SRC_UADDR 0x00000088 +#define CRYPTO4XX_PKT_DEST_UADDR 0x0000008c +#define CRYPTO4XX_SA_UADDR 0x00000090 +#define CRYPTO4XX_GATH_RING_BASE_UADDR 0x000000A0 +#define CRYPTO4XX_SCAT_RING_BASE_UADDR 0x000000A4 + +#define CRYPTO4XX_SEQ_RD 0x00000408 +#define CRYPTO4XX_SEQ_MASK_RD 0x0000040C + +#define CRYPTO4XX_SA_CMD_0 0x00010600 +#define CRYPTO4XX_SA_CMD_1 0x00010604 + +#define CRYPTO4XX_STATE_PTR 0x000106dc +#define CRYPTO4XX_STATE_IV 0x00010700 +#define CRYPTO4XX_STATE_HASH_BYTE_CNT_0 0x00010710 +#define CRYPTO4XX_STATE_HASH_BYTE_CNT_1 0x00010714 + +#define CRYPTO4XX_STATE_IDIGEST_0 0x00010718 +#define CRYPTO4XX_STATE_IDIGEST_1 0x0001071c + +#define CRYPTO4XX_DATA_IN 0x00018000 +#define CRYPTO4XX_DATA_OUT 0x0001c000 + +#define CRYPTO4XX_INT_UNMASK_STAT 0x000500a0 +#define CRYPTO4XX_INT_MASK_STAT 0x000500a4 +#define CRYPTO4XX_INT_CLR 0x000500a4 +#define CRYPTO4XX_INT_EN 0x000500a8 + +#define CRYPTO4XX_INT_PKA 0x00000002 +#define CRYPTO4XX_INT_PDR_DONE 0x00008000 +#define CRYPTO4XX_INT_MA_WR_ERR 0x00020000 +#define CRYPTO4XX_INT_MA_RD_ERR 0x00010000 +#define CRYPTO4XX_INT_PE_ERR 0x00000200 +#define CRYPTO4XX_INT_USER_DMA_ERR 0x00000040 +#define CRYPTO4XX_INT_SLAVE_ERR 0x00000010 +#define CRYPTO4XX_INT_MASTER_ERR 0x00000008 +#define CRYPTO4XX_INT_ERROR 0x00030258 + +#define CRYPTO4XX_INT_CFG 0x000500ac +#define CRYPTO4XX_INT_DESCR_RD 0x000500b0 +#define CRYPTO4XX_INT_DESCR_CNT 0x000500b4 +#define CRYPTO4XX_INT_TIMEOUT_CNT 0x000500b8 + +#define CRYPTO4XX_DEVICE_CTRL 0x00060080 +#define CRYPTO4XX_DEVICE_ID 0x00060084 +#define CRYPTO4XX_DEVICE_INFO 0x00060088 +#define CRYPTO4XX_DMA_USER_SRC 0x00060094 +#define CRYPTO4XX_DMA_USER_DEST 0x00060098 +#define CRYPTO4XX_DMA_USER_CMD 0x0006009C + +#define CRYPTO4XX_DMA_CFG 0x000600d4 +#define CRYPTO4XX_BYTE_ORDER_CFG 0x000600d8 +#define CRYPTO4XX_ENDIAN_CFG 0x000600d8 + +#define CRYPTO4XX_PRNG_STAT 0x00070000 +#define CRYPTO4XX_PRNG_CTRL 0x00070004 +#define CRYPTO4XX_PRNG_SEED_L 0x00070008 +#define CRYPTO4XX_PRNG_SEED_H 0x0007000c + +#define CRYPTO4XX_PRNG_RES_0 0x00070020 +#define CRYPTO4XX_PRNG_RES_1 0x00070024 +#define CRYPTO4XX_PRNG_RES_2 0x00070028 +#define CRYPTO4XX_PRNG_RES_3 0x0007002C + +#define CRYPTO4XX_PRNG_LFSR_L 0x00070030 +#define CRYPTO4XX_PRNG_LFSR_H 0x00070034 + +/** + * Initilize CRYPTO ENGINE registers, and memory bases. + */ +#define PPC4XX_PDR_POLL 0x3ff +#define PPC4XX_OUTPUT_THRESHOLD 2 +#define PPC4XX_INPUT_THRESHOLD 2 +#define PPC4XX_PD_SIZE 6 +#define PPC4XX_CTX_DONE_INT 0x2000 +#define PPC4XX_PD_DONE_INT 0x8000 +#define PPC4XX_BYTE_ORDER 0x22222 +#define PPC4XX_INTERRUPT_CLR 0x3ffff +#define PPC4XX_PRNG_CTRL_AUTO_EN 0x3 +#define PPC4XX_DC_3DES_EN 1 +#define PPC4XX_INT_DESCR_CNT 4 +#define PPC4XX_INT_TIMEOUT_CNT 0 +#define PPC4XX_INT_CFG 1 +/** + * all follow define are ad hoc + */ +#define PPC4XX_RING_RETRY 100 +#define PPC4XX_RING_POLL 100 +#define PPC4XX_SDR_SIZE PPC4XX_NUM_SD +#define PPC4XX_GDR_SIZE PPC4XX_NUM_GD + +/** + * Generic Security Association (SA) with all possible fields. These will + * never likely used except for reference purpose. These structure format + * can be not changed as the hardware expects them to be layout as defined. + * Field can be removed or reduced but ordering can not be changed. + */ +#define CRYPTO4XX_DMA_CFG_OFFSET 0x40 +union ce_pe_dma_cfg { + struct { + u32 rsv:7; + u32 dir_host:1; + u32 rsv1:2; + u32 bo_td_en:1; + u32 dis_pdr_upd:1; + u32 bo_sgpd_en:1; + u32 bo_data_en:1; + u32 bo_sa_en:1; + u32 bo_pd_en:1; + u32 rsv2:4; + u32 dynamic_sa_en:1; + u32 pdr_mode:2; + u32 pe_mode:1; + u32 rsv3:5; + u32 reset_sg:1; + u32 reset_pdr:1; + u32 reset_pe:1; + } bf; + u32 w; +} __attribute__((packed)); + +#define CRYPTO4XX_PDR_BASE_OFFSET 0x48 +#define CRYPTO4XX_RDR_BASE_OFFSET 0x4c +#define CRYPTO4XX_RING_SIZE_OFFSET 0x50 +union ce_ring_size { + struct { + u32 ring_offset:16; + u32 rsv:6; + u32 ring_size:10; + } bf; + u32 w; +} __attribute__((packed)); + +#define CRYPTO4XX_RING_CONTROL_OFFSET 0x54 +union ce_ring_contol { + struct { + u32 continuous:1; + u32 rsv:5; + u32 ring_retry_divisor:10; + u32 rsv1:4; + u32 ring_poll_divisor:10; + } bf; + u32 w; +} __attribute__((packed)); + +#define CRYPTO4XX_IO_THRESHOLD_OFFSET 0x60 +union ce_io_threshold { + struct { + u32 rsv:6; + u32 output_threshold:10; + u32 rsv1:6; + u32 input_threshold:10; + } bf; + u32 w; +} __attribute__((packed)); + +#define CRYPTO4XX_GATHER_RING_BASE_OFFSET 0x64 +#define CRYPTO4XX_SCATTER_RING_BASE_OFFSET 0x68 + +union ce_part_ring_size { + struct { + u32 sdr_size:16; + u32 gdr_size:16; + } bf; + u32 w; +} __attribute__((packed)); + +#define MAX_BURST_SIZE_32 0 +#define MAX_BURST_SIZE_64 1 +#define MAX_BURST_SIZE_128 2 +#define MAX_BURST_SIZE_256 3 + +/* gather descriptor control length */ +struct gd_ctl_len { + u32 len:16; + u32 rsv:14; + u32 done:1; + u32 ready:1; +} __attribute__((packed)); + +struct ce_gd { + u32 ptr; + struct gd_ctl_len ctl_len; +} __attribute__((packed)); + +struct sd_ctl { + u32 ctl:30; + u32 done:1; + u32 rdy:1; +} __attribute__((packed)); + +struct ce_sd { + u32 ptr; + struct sd_ctl ctl; +} __attribute__((packed)); + +#define PD_PAD_CTL_32 0x10 +#define PD_PAD_CTL_64 0x20 +#define PD_PAD_CTL_128 0x40 +#define PD_PAD_CTL_256 0x80 +union ce_pd_ctl { + struct { + u32 pd_pad_ctl:8; + u32 status:8; + u32 next_hdr:8; + u32 rsv:2; + u32 cached_sa:1; + u32 hash_final:1; + u32 init_arc4:1; + u32 rsv1:1; + u32 pe_done:1; + u32 host_ready:1; + } bf; + u32 w; +} __attribute__((packed)); + +union ce_pd_ctl_len { + struct { + u32 bypass:8; + u32 pe_done:1; + u32 host_ready:1; + u32 rsv:2; + u32 pkt_len:20; + } bf; + u32 w; +} __attribute__((packed)); + +struct ce_pd { + union ce_pd_ctl pd_ctl; + u32 src; + u32 dest; + u32 sa; /* get from ctx->sa_dma_addr */ + u32 sa_len; /* only if dynamic sa is used */ + union ce_pd_ctl_len pd_ctl_len; + +} __attribute__((packed)); +#endif diff --git a/drivers/crypto/amcc/crypto4xx_sa.c b/drivers/crypto/amcc/crypto4xx_sa.c new file mode 100644 index 00000000000..466fd94cd4a --- /dev/null +++ b/drivers/crypto/amcc/crypto4xx_sa.c @@ -0,0 +1,108 @@ +/** + * AMCC SoC PPC4xx Crypto Driver + * + * Copyright (c) 2008 Applied Micro Circuits Corporation. + * All rights reserved. James Hsiao + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * @file crypto4xx_sa.c + * + * This file implements the security context + * assoicate format. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "crypto4xx_reg_def.h" +#include "crypto4xx_sa.h" +#include "crypto4xx_core.h" + +u32 get_dynamic_sa_offset_iv_field(struct crypto4xx_ctx *ctx) +{ + u32 offset; + union dynamic_sa_contents cts; + + if (ctx->direction == DIR_INBOUND) + cts.w = ((struct dynamic_sa_ctl *)(ctx->sa_in))->sa_contents; + else + cts.w = ((struct dynamic_sa_ctl *)(ctx->sa_out))->sa_contents; + offset = cts.bf.key_size + + cts.bf.inner_size + + cts.bf.outer_size + + cts.bf.spi + + cts.bf.seq_num0 + + cts.bf.seq_num1 + + cts.bf.seq_num_mask0 + + cts.bf.seq_num_mask1 + + cts.bf.seq_num_mask2 + + cts.bf.seq_num_mask3; + + return sizeof(struct dynamic_sa_ctl) + offset * 4; +} + +u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx *ctx) +{ + u32 offset; + union dynamic_sa_contents cts; + + if (ctx->direction == DIR_INBOUND) + cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents; + else + cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents; + offset = cts.bf.key_size + + cts.bf.inner_size + + cts.bf.outer_size + + cts.bf.spi + + cts.bf.seq_num0 + + cts.bf.seq_num1 + + cts.bf.seq_num_mask0 + + cts.bf.seq_num_mask1 + + cts.bf.seq_num_mask2 + + cts.bf.seq_num_mask3 + + cts.bf.iv0 + + cts.bf.iv1 + + cts.bf.iv2 + + cts.bf.iv3; + + return sizeof(struct dynamic_sa_ctl) + offset * 4; +} + +u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx) +{ + union dynamic_sa_contents cts; + + if (ctx->direction == DIR_INBOUND) + cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents; + else + cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents; + return (cts.bf.iv0 + cts.bf.iv1 + cts.bf.iv2 + cts.bf.iv3) * 4; +} + +u32 get_dynamic_sa_offset_key_field(struct crypto4xx_ctx *ctx) +{ + union dynamic_sa_contents cts; + + if (ctx->direction == DIR_INBOUND) + cts.w = ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents; + else + cts.w = ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents; + + return sizeof(struct dynamic_sa_ctl); +} diff --git a/drivers/crypto/amcc/crypto4xx_sa.h b/drivers/crypto/amcc/crypto4xx_sa.h new file mode 100644 index 00000000000..4b83ed7e557 --- /dev/null +++ b/drivers/crypto/amcc/crypto4xx_sa.h @@ -0,0 +1,243 @@ +/** + * AMCC SoC PPC4xx Crypto Driver + * + * Copyright (c) 2008 Applied Micro Circuits Corporation. + * All rights reserved. James Hsiao + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This file defines the security context + * assoicate format. + */ + +#ifndef __CRYPTO4XX_SA_H__ +#define __CRYPTO4XX_SA_H__ + +#define AES_IV_SIZE 16 + +/** + * Contents of Dynamic Security Association (SA) with all possible fields + */ +union dynamic_sa_contents { + struct { + u32 arc4_state_ptr:1; + u32 arc4_ij_ptr:1; + u32 state_ptr:1; + u32 iv3:1; + u32 iv2:1; + u32 iv1:1; + u32 iv0:1; + u32 seq_num_mask3:1; + u32 seq_num_mask2:1; + u32 seq_num_mask1:1; + u32 seq_num_mask0:1; + u32 seq_num1:1; + u32 seq_num0:1; + u32 spi:1; + u32 outer_size:5; + u32 inner_size:5; + u32 key_size:4; + u32 cmd_size:4; + } bf; + u32 w; +} __attribute__((packed)); + +#define DIR_OUTBOUND 0 +#define DIR_INBOUND 1 +#define SA_OP_GROUP_BASIC 0 +#define SA_OPCODE_ENCRYPT 0 +#define SA_OPCODE_DECRYPT 0 +#define SA_OPCODE_HASH 3 +#define SA_CIPHER_ALG_DES 0 +#define SA_CIPHER_ALG_3DES 1 +#define SA_CIPHER_ALG_ARC4 2 +#define SA_CIPHER_ALG_AES 3 +#define SA_CIPHER_ALG_KASUMI 4 +#define SA_CIPHER_ALG_NULL 15 + +#define SA_HASH_ALG_MD5 0 +#define SA_HASH_ALG_SHA1 1 +#define SA_HASH_ALG_NULL 15 +#define SA_HASH_ALG_SHA1_DIGEST_SIZE 20 + +#define SA_LOAD_HASH_FROM_SA 0 +#define SA_LOAD_HASH_FROM_STATE 2 +#define SA_NOT_LOAD_HASH 3 +#define SA_LOAD_IV_FROM_SA 0 +#define SA_LOAD_IV_FROM_INPUT 1 +#define SA_LOAD_IV_FROM_STATE 2 +#define SA_LOAD_IV_GEN_IV 3 + +#define SA_PAD_TYPE_CONSTANT 2 +#define SA_PAD_TYPE_ZERO 3 +#define SA_PAD_TYPE_TLS 5 +#define SA_PAD_TYPE_DTLS 5 +#define SA_NOT_SAVE_HASH 0 +#define SA_SAVE_HASH 1 +#define SA_NOT_SAVE_IV 0 +#define SA_SAVE_IV 1 +#define SA_HEADER_PROC 1 +#define SA_NO_HEADER_PROC 0 + +union sa_command_0 { + struct { + u32 scatter:1; + u32 gather:1; + u32 save_hash_state:1; + u32 save_iv:1; + u32 load_hash_state:2; + u32 load_iv:2; + u32 digest_len:4; + u32 hdr_proc:1; + u32 extend_pad:1; + u32 stream_cipher_pad:1; + u32 rsv:1; + u32 hash_alg:4; + u32 cipher_alg:4; + u32 pad_type:2; + u32 op_group:2; + u32 dir:1; + u32 opcode:3; + } bf; + u32 w; +} __attribute__((packed)); + +#define CRYPTO_MODE_ECB 0 +#define CRYPTO_MODE_CBC 1 + +#define CRYPTO_FEEDBACK_MODE_NO_FB 0 +#define CRYPTO_FEEDBACK_MODE_64BIT_OFB 0 +#define CRYPTO_FEEDBACK_MODE_8BIT_CFB 1 +#define CRYPTO_FEEDBACK_MODE_1BIT_CFB 2 +#define CRYPTO_FEEDBACK_MODE_128BIT_CFB 3 + +#define SA_AES_KEY_LEN_128 2 +#define SA_AES_KEY_LEN_192 3 +#define SA_AES_KEY_LEN_256 4 + +#define SA_REV2 1 +/** + * The follow defines bits sa_command_1 + * In Basic hash mode this bit define simple hash or hmac. + * In IPsec mode, this bit define muting control. + */ +#define SA_HASH_MODE_HASH 0 +#define SA_HASH_MODE_HMAC 1 +#define SA_MC_ENABLE 0 +#define SA_MC_DISABLE 1 +#define SA_NOT_COPY_HDR 0 +#define SA_COPY_HDR 1 +#define SA_NOT_COPY_PAD 0 +#define SA_COPY_PAD 1 +#define SA_NOT_COPY_PAYLOAD 0 +#define SA_COPY_PAYLOAD 1 +#define SA_EXTENDED_SN_OFF 0 +#define SA_EXTENDED_SN_ON 1 +#define SA_SEQ_MASK_OFF 0 +#define SA_SEQ_MASK_ON 1 + +union sa_command_1 { + struct { + u32 crypto_mode31:1; + u32 save_arc4_state:1; + u32 arc4_stateful:1; + u32 key_len:5; + u32 hash_crypto_offset:8; + u32 sa_rev:2; + u32 byte_offset:1; + u32 hmac_muting:1; + u32 feedback_mode:2; + u32 crypto_mode9_8:2; + u32 extended_seq_num:1; + u32 seq_num_mask:1; + u32 mutable_bit_proc:1; + u32 ip_version:1; + u32 copy_pad:1; + u32 copy_payload:1; + u32 copy_hdr:1; + u32 rsv1:1; + } bf; + u32 w; +} __attribute__((packed)); + +struct dynamic_sa_ctl { + u32 sa_contents; + union sa_command_0 sa_command_0; + union sa_command_1 sa_command_1; +} __attribute__((packed)); + +/** + * State Record for Security Association (SA) + */ +struct sa_state_record { + u32 save_iv[4]; + u32 save_hash_byte_cnt[2]; + u32 save_digest[16]; +} __attribute__((packed)); + +/** + * Security Association (SA) for AES128 + * + */ +struct dynamic_sa_aes128 { + struct dynamic_sa_ctl ctrl; + u32 key[4]; + u32 iv[4]; /* for CBC, OFC, and CFB mode */ + u32 state_ptr; + u32 reserved; +} __attribute__((packed)); + +#define SA_AES128_LEN (sizeof(struct dynamic_sa_aes128)/4) +#define SA_AES128_CONTENTS 0x3e000042 + +/* + * Security Association (SA) for AES192 + */ +struct dynamic_sa_aes192 { + struct dynamic_sa_ctl ctrl; + u32 key[6]; + u32 iv[4]; /* for CBC, OFC, and CFB mode */ + u32 state_ptr; + u32 reserved; +} __attribute__((packed)); + +#define SA_AES192_LEN (sizeof(struct dynamic_sa_aes192)/4) +#define SA_AES192_CONTENTS 0x3e000062 + +/** + * Security Association (SA) for AES256 + */ +struct dynamic_sa_aes256 { + struct dynamic_sa_ctl ctrl; + u32 key[8]; + u32 iv[4]; /* for CBC, OFC, and CFB mode */ + u32 state_ptr; + u32 reserved; +} __attribute__((packed)); + +#define SA_AES256_LEN (sizeof(struct dynamic_sa_aes256)/4) +#define SA_AES256_CONTENTS 0x3e000082 +#define SA_AES_CONTENTS 0x3e000002 + +/** + * Security Association (SA) for HASH160: HMAC-SHA1 + */ +struct dynamic_sa_hash160 { + struct dynamic_sa_ctl ctrl; + u32 inner_digest[5]; + u32 outer_digest[5]; + u32 state_ptr; + u32 reserved; +} __attribute__((packed)); +#define SA_HASH160_LEN (sizeof(struct dynamic_sa_hash160)/4) +#define SA_HASH160_CONTENTS 0x2000a502 + +#endif -- cgit v1.2.3 From 9c3c133b1ed6e6d01bfabb6de29bf3d0f0886354 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Sun, 22 Feb 2009 12:03:56 +0800 Subject: hwrng: timeriomem - New driver Some hardware platforms, the TS-7800[1] is one for example, can supply the kernel with an entropy source, albeit a slow one for TS-7800 users, by just reading a particular IO address. This source must not be read above a certain rate otherwise the quality suffers. The driver is then hooked into by calling platform_device_(register|add|del) passing a structure similar to: ------ static struct timeriomem_rng_data ts78xx_ts_rng_data = { .address = (u32 *__iomem) TS_RNG, .period = 1000000, /* one second */ }; static struct platform_device ts78xx_ts_rng_device = { .name = "timeriomem_rng", .id = -1, .dev = { .platform_data = &ts78xx_ts_rng_data, }, .num_resources = 0, }; ------ [1] http://www.embeddedarm.com/products/board-detail.php?product=TS-7800 Signed-off-by: Alexander Clouter Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 14 +++ drivers/char/hw_random/Makefile | 1 + drivers/char/hw_random/timeriomem-rng.c | 151 ++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+) create mode 100644 drivers/char/hw_random/timeriomem-rng.c (limited to 'drivers') diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index 8822eca58ff..e86dd425a70 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -20,6 +20,20 @@ config HW_RANDOM If unsure, say Y. +config HW_RANDOM_TIMERIOMEM + tristate "Timer IOMEM HW Random Number Generator support" + depends on HW_RANDOM + ---help--- + This driver provides kernel-side support for a generic Random + Number Generator used by reading a 'dumb' iomem address that + is to be read no faster than, for example, once a second; + the default FPGA bitstream on the TS-7800 has such functionality. + + To compile this driver as a module, choose M here: the + module will be called timeriomem-rng. + + If unsure, say Y. + config HW_RANDOM_INTEL tristate "Intel HW Random Number Generator support" depends on HW_RANDOM && (X86 || IA64) && PCI diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index b6effb7522c..e81d21a5f28 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile @@ -4,6 +4,7 @@ obj-$(CONFIG_HW_RANDOM) += rng-core.o rng-core-y := core.o +obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c new file mode 100644 index 00000000000..10ad41be589 --- /dev/null +++ b/drivers/char/hw_random/timeriomem-rng.c @@ -0,0 +1,151 @@ +/* + * drivers/char/hw_random/timeriomem-rng.c + * + * Copyright (C) 2009 Alexander Clouter + * + * Derived from drivers/char/hw_random/omap-rng.c + * Copyright 2005 (c) MontaVista Software, Inc. + * Author: Deepak Saxena + * + * 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. + * + * Overview: + * This driver is useful for platforms that have an IO range that provides + * periodic random data from a single IO memory address. All the platform + * has to do is provide the address and 'wait time' that new data becomes + * available. + * + * TODO: add support for reading sizes other than 32bits and masking + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct timeriomem_rng_data *timeriomem_rng_data; + +static void timeriomem_rng_trigger(unsigned long); +static DEFINE_TIMER(timeriomem_rng_timer, timeriomem_rng_trigger, 0, 0); + +/* + * have data return 1, however return 0 if we have nothing + */ +static int timeriomem_rng_data_present(struct hwrng *rng, int wait) +{ + if (rng->priv == 0) + return 1; + + if (!wait || timeriomem_rng_data->present) + return timeriomem_rng_data->present; + + wait_for_completion(&timeriomem_rng_data->completion); + + return 1; +} + +static int timeriomem_rng_data_read(struct hwrng *rng, u32 *data) +{ + unsigned long cur; + s32 delay; + + *data = readl(timeriomem_rng_data->address); + + if (rng->priv != 0) { + cur = jiffies; + + delay = cur - timeriomem_rng_timer.expires; + delay = rng->priv - (delay % rng->priv); + + timeriomem_rng_timer.expires = cur + delay; + timeriomem_rng_data->present = 0; + + init_completion(&timeriomem_rng_data->completion); + add_timer(&timeriomem_rng_timer); + } + + return 4; +} + +static void timeriomem_rng_trigger(unsigned long dummy) +{ + timeriomem_rng_data->present = 1; + complete(&timeriomem_rng_data->completion); +} + +static struct hwrng timeriomem_rng_ops = { + .name = "timeriomem", + .data_present = timeriomem_rng_data_present, + .data_read = timeriomem_rng_data_read, + .priv = 0, +}; + +static int __init timeriomem_rng_probe(struct platform_device *pdev) +{ + int ret; + + timeriomem_rng_data = pdev->dev.platform_data; + + if (timeriomem_rng_data->period != 0 + && usecs_to_jiffies(timeriomem_rng_data->period) > 0) { + timeriomem_rng_timer.expires = jiffies; + + timeriomem_rng_ops.priv = usecs_to_jiffies( + timeriomem_rng_data->period); + } + timeriomem_rng_data->present = 1; + + ret = hwrng_register(&timeriomem_rng_ops); + if (ret) { + dev_err(&pdev->dev, "problem registering\n"); + return ret; + } + + dev_info(&pdev->dev, "32bits from 0x%p @ %dus\n", + timeriomem_rng_data->address, + timeriomem_rng_data->period); + + return 0; +} + +static int __devexit timeriomem_rng_remove(struct platform_device *pdev) +{ + del_timer_sync(&timeriomem_rng_timer); + hwrng_unregister(&timeriomem_rng_ops); + + return 0; +} + +static struct platform_driver timeriomem_rng_driver = { + .driver = { + .name = "timeriomem_rng", + .owner = THIS_MODULE, + }, + .probe = timeriomem_rng_probe, + .remove = __devexit_p(timeriomem_rng_remove), +}; + +static int __init timeriomem_rng_init(void) +{ + return platform_driver_register(&timeriomem_rng_driver); +} + +static void __exit timeriomem_rng_exit(void) +{ + platform_driver_unregister(&timeriomem_rng_driver); +} + +module_init(timeriomem_rng_init); +module_exit(timeriomem_rng_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Alexander Clouter "); +MODULE_DESCRIPTION("Timer IOMEM H/W RNG driver"); -- cgit v1.2.3 From 0af98d37e85e6958eb84987b1f60da3b54008317 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 8 Feb 2009 16:44:42 +0100 Subject: [WATCHDOG] rc32434_wdt: fix watchdog driver The existing driver code wasn't working. Neither the timeout was set correctly, nor system reset was being triggered, as the driver seemed to keep the WDT alive himself. There was also some unnecessary code. Signed-off-by: Phil Sutter Signed-off-by: Wim Van Sebroeck Cc: stable --- drivers/watchdog/rc32434_wdt.c | 158 +++++++++++++++++------------------------ 1 file changed, 64 insertions(+), 94 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index 57027f4653c..f1f98cd757c 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -34,104 +34,89 @@ #include #include -#define MAX_TIMEOUT 20 -#define RC32434_WDT_INTERVAL (15 * HZ) - -#define VERSION "0.2" +#define VERSION "0.3" static struct { - struct completion stop; - int running; - struct timer_list timer; - int queue; - int default_ticks; unsigned long inuse; } rc32434_wdt_device; static struct integ __iomem *wdt_reg; -static int ticks = 100 * HZ; static int expect_close; -static int timeout; + +/* Board internal clock speed in Hz, + * the watchdog timer ticks at. */ +extern unsigned int idt_cpu_freq; + +/* translate wtcompare value to seconds and vice versa */ +#define WTCOMP2SEC(x) (x / idt_cpu_freq) +#define SEC2WTCOMP(x) (x * idt_cpu_freq) + +/* Use a default timeout of 20s. This should be + * safe for CPU clock speeds up to 400MHz, as + * ((2 ^ 32) - 1) / (400MHz / 2) = 21s. */ +#define WATCHDOG_TIMEOUT 20 + +static int timeout = WATCHDOG_TIMEOUT; static int nowayout = WATCHDOG_NOWAYOUT; module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); +/* apply or and nand masks to data read from addr and write back */ +#define SET_BITS(addr, or, nand) \ + writel((readl(&addr) | or) & ~nand, &addr) static void rc32434_wdt_start(void) { - u32 val; - - if (!rc32434_wdt_device.inuse) { - writel(0, &wdt_reg->wtcount); + u32 or, nand; - val = RC32434_ERR_WRE; - writel(readl(&wdt_reg->errcs) | val, &wdt_reg->errcs); + /* zero the counter before enabling */ + writel(0, &wdt_reg->wtcount); - val = RC32434_WTC_EN; - writel(readl(&wdt_reg->wtc) | val, &wdt_reg->wtc); - } - rc32434_wdt_device.running++; -} + /* don't generate a non-maskable interrupt, + * do a warm reset instead */ + nand = 1 << RC32434_ERR_WNE; + or = 1 << RC32434_ERR_WRE; -static void rc32434_wdt_stop(void) -{ - u32 val; + /* reset the ERRCS timeout bit in case it's set */ + nand |= 1 << RC32434_ERR_WTO; - if (rc32434_wdt_device.running) { + SET_BITS(wdt_reg->errcs, or, nand); - val = ~RC32434_WTC_EN; - writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc); + /* reset WTC timeout bit and enable WDT */ + nand = 1 << RC32434_WTC_TO; + or = 1 << RC32434_WTC_EN; - val = ~RC32434_ERR_WRE; - writel(readl(&wdt_reg->errcs) & val, &wdt_reg->errcs); + SET_BITS(wdt_reg->wtc, or, nand); +} - rc32434_wdt_device.running = 0; - } +static void rc32434_wdt_stop(void) +{ + /* Disable WDT */ + SET_BITS(wdt_reg->wtc, 0, 1 << RC32434_WTC_EN); } -static void rc32434_wdt_set(int new_timeout) +static int rc32434_wdt_set(int new_timeout) { - u32 cmp = new_timeout * HZ; - u32 state, val; + int max_to = WTCOMP2SEC((u32)-1); + if (new_timeout < 0 || new_timeout > max_to) { + printk(KERN_ERR KBUILD_MODNAME + ": timeout value must be between 0 and %d", + max_to); + return -EINVAL; + } timeout = new_timeout; - /* - * store and disable WTC - */ - state = (u32)(readl(&wdt_reg->wtc) & RC32434_WTC_EN); - val = ~RC32434_WTC_EN; - writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc); - - writel(0, &wdt_reg->wtcount); - writel(cmp, &wdt_reg->wtcompare); - - /* - * restore WTC - */ - - writel(readl(&wdt_reg->wtc) | state, &wdt_reg); -} + writel(SEC2WTCOMP(timeout), &wdt_reg->wtcompare); -static void rc32434_wdt_reset(void) -{ - ticks = rc32434_wdt_device.default_ticks; + return 0; } -static void rc32434_wdt_update(unsigned long unused) +static void rc32434_wdt_ping(void) { - if (rc32434_wdt_device.running) - ticks--; - writel(0, &wdt_reg->wtcount); - - if (rc32434_wdt_device.queue && ticks) - mod_timer(&rc32434_wdt_device.timer, - jiffies + RC32434_WDT_INTERVAL); - else - complete(&rc32434_wdt_device.stop); } static int rc32434_wdt_open(struct inode *inode, struct file *file) @@ -142,19 +127,23 @@ static int rc32434_wdt_open(struct inode *inode, struct file *file) if (nowayout) __module_get(THIS_MODULE); + rc32434_wdt_start(); + rc32434_wdt_ping(); + return nonseekable_open(inode, file); } static int rc32434_wdt_release(struct inode *inode, struct file *file) { - if (expect_close && nowayout == 0) { + if (expect_close == 42) { rc32434_wdt_stop(); printk(KERN_INFO KBUILD_MODNAME ": disabling watchdog timer\n"); module_put(THIS_MODULE); - } else + } else { printk(KERN_CRIT KBUILD_MODNAME ": device closed unexpectedly. WDT will not stop !\n"); - + rc32434_wdt_ping(); + } clear_bit(0, &rc32434_wdt_device.inuse); return 0; } @@ -174,10 +163,10 @@ static ssize_t rc32434_wdt_write(struct file *file, const char *data, if (get_user(c, data + i)) return -EFAULT; if (c == 'V') - expect_close = 1; + expect_close = 42; } } - rc32434_wdt_update(0); + rc32434_wdt_ping(); return len; } return 0; @@ -197,11 +186,11 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, }; switch (cmd) { case WDIOC_KEEPALIVE: - rc32434_wdt_reset(); + rc32434_wdt_ping(); break; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: - value = readl(&wdt_reg->wtcount); + value = 0; if (copy_to_user(argp, &value, sizeof(int))) return -EFAULT; break; @@ -218,6 +207,7 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, break; case WDIOS_DISABLECARD: rc32434_wdt_stop(); + break; default: return -EINVAL; } @@ -225,11 +215,9 @@ static long rc32434_wdt_ioctl(struct file *file, unsigned int cmd, case WDIOC_SETTIMEOUT: if (copy_from_user(&new_timeout, argp, sizeof(int))) return -EFAULT; - if (new_timeout < 1) + if (rc32434_wdt_set(new_timeout)) return -EINVAL; - if (new_timeout > MAX_TIMEOUT) - return -EINVAL; - rc32434_wdt_set(new_timeout); + /* Fall through */ case WDIOC_GETTIMEOUT: return copy_to_user(argp, &timeout, sizeof(int)); default: @@ -262,7 +250,7 @@ static int rc32434_wdt_probe(struct platform_device *pdev) int ret; struct resource *r; - r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb500_wdt_res"); + r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "rb532_wdt_res"); if (!r) { printk(KERN_ERR KBUILD_MODNAME "failed to retrieve resources\n"); @@ -277,24 +265,12 @@ static int rc32434_wdt_probe(struct platform_device *pdev) } ret = misc_register(&rc32434_wdt_miscdev); - if (ret < 0) { printk(KERN_ERR KBUILD_MODNAME "failed to register watchdog device\n"); goto unmap; } - init_completion(&rc32434_wdt_device.stop); - rc32434_wdt_device.queue = 0; - - clear_bit(0, &rc32434_wdt_device.inuse); - - setup_timer(&rc32434_wdt_device.timer, rc32434_wdt_update, 0L); - - rc32434_wdt_device.default_ticks = ticks; - - rc32434_wdt_start(); - printk(banner, timeout); return 0; @@ -306,14 +282,8 @@ unmap: static int rc32434_wdt_remove(struct platform_device *pdev) { - if (rc32434_wdt_device.queue) { - rc32434_wdt_device.queue = 0; - wait_for_completion(&rc32434_wdt_device.stop); - } misc_deregister(&rc32434_wdt_miscdev); - iounmap(wdt_reg); - return 0; } -- cgit v1.2.3 From d9a8798c4bab5ccd40e45e011f668099cfb3eb83 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Sun, 8 Feb 2009 16:44:42 +0100 Subject: [WATCHDOG] rc32434_wdt: fix sections Fix init and exit sections. Signed-off-by: Phil Sutter Signed-off-by: Wim Van Sebroeck Cc: stable --- drivers/watchdog/rc32434_wdt.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c index f1f98cd757c..f3553fa40b1 100644 --- a/drivers/watchdog/rc32434_wdt.c +++ b/drivers/watchdog/rc32434_wdt.c @@ -34,7 +34,7 @@ #include #include -#define VERSION "0.3" +#define VERSION "0.4" static struct { unsigned long inuse; @@ -242,10 +242,10 @@ static struct miscdevice rc32434_wdt_miscdev = { .fops = &rc32434_wdt_fops, }; -static char banner[] = KERN_INFO KBUILD_MODNAME +static char banner[] __devinitdata = KERN_INFO KBUILD_MODNAME ": Watchdog Timer version " VERSION ", timer margin: %d sec\n"; -static int rc32434_wdt_probe(struct platform_device *pdev) +static int __devinit rc32434_wdt_probe(struct platform_device *pdev) { int ret; struct resource *r; @@ -280,7 +280,7 @@ unmap: return ret; } -static int rc32434_wdt_remove(struct platform_device *pdev) +static int __devexit rc32434_wdt_remove(struct platform_device *pdev) { misc_deregister(&rc32434_wdt_miscdev); iounmap(wdt_reg); @@ -289,8 +289,8 @@ static int rc32434_wdt_remove(struct platform_device *pdev) static struct platform_driver rc32434_wdt = { .probe = rc32434_wdt_probe, - .remove = rc32434_wdt_remove, - .driver = { + .remove = __devexit_p(rc32434_wdt_remove), + .driver = { .name = "rc32434_wdt", } }; -- cgit v1.2.3 From 29464f281389fd7e9adf969de7bbeb20b8596f82 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 18 Jan 2009 01:37:11 -0500 Subject: [CPUFREQ] checkpatch cleanups for cpufreq core Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 52 +++++++++++++++++++++++------------------------ 1 file changed, 26 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b55cb67435b..1867dac35af 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -104,7 +104,8 @@ EXPORT_SYMBOL_GPL(unlock_policy_rwsem_write); /* internal prototypes */ -static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); +static int __cpufreq_governor(struct cpufreq_policy *policy, + unsigned int event); static unsigned int __cpufreq_get(unsigned int cpu); static void handle_update(struct work_struct *work); @@ -128,7 +129,7 @@ static int __init init_cpufreq_transition_notifier_list(void) pure_initcall(init_cpufreq_transition_notifier_list); static LIST_HEAD(cpufreq_governor_list); -static DEFINE_MUTEX (cpufreq_governor_mutex); +static DEFINE_MUTEX(cpufreq_governor_mutex); struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) { @@ -371,7 +372,7 @@ static struct cpufreq_governor *__find_governor(const char *str_governor) struct cpufreq_governor *t; list_for_each_entry(t, &cpufreq_governor_list, governor_list) - if (!strnicmp(str_governor,t->name,CPUFREQ_NAME_LEN)) + if (!strnicmp(str_governor, t->name, CPUFREQ_NAME_LEN)) return t; return NULL; @@ -429,15 +430,11 @@ static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, mutex_unlock(&cpufreq_governor_mutex); } - out: +out: return err; } -/* drivers/base/cpu.c */ -extern struct sysdev_class cpu_sysdev_class; - - /** * cpufreq_per_cpu_attr_read() / show_##file_name() - * print out cpufreq information @@ -450,7 +447,7 @@ extern struct sysdev_class cpu_sysdev_class; static ssize_t show_##file_name \ (struct cpufreq_policy *policy, char *buf) \ { \ - return sprintf (buf, "%u\n", policy->object); \ + return sprintf(buf, "%u\n", policy->object); \ } show_one(cpuinfo_min_freq, cpuinfo.min_freq); @@ -476,7 +473,7 @@ static ssize_t store_##file_name \ if (ret) \ return -EINVAL; \ \ - ret = sscanf (buf, "%u", &new_policy.object); \ + ret = sscanf(buf, "%u", &new_policy.object); \ if (ret != 1) \ return -EINVAL; \ \ @@ -486,8 +483,8 @@ static ssize_t store_##file_name \ return ret ? ret : count; \ } -store_one(scaling_min_freq,min); -store_one(scaling_max_freq,max); +store_one(scaling_min_freq, min); +store_one(scaling_max_freq, max); /** * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware @@ -507,12 +504,13 @@ static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy, */ static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf) { - if(policy->policy == CPUFREQ_POLICY_POWERSAVE) + if (policy->policy == CPUFREQ_POLICY_POWERSAVE) return sprintf(buf, "powersave\n"); else if (policy->policy == CPUFREQ_POLICY_PERFORMANCE) return sprintf(buf, "performance\n"); else if (policy->governor) - return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", policy->governor->name); + return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", + policy->governor->name); return -EINVAL; } @@ -531,7 +529,7 @@ static ssize_t store_scaling_governor(struct cpufreq_policy *policy, if (ret) return ret; - ret = sscanf (buf, "%15s", str_governor); + ret = sscanf(buf, "%15s", str_governor); if (ret != 1) return -EINVAL; @@ -575,7 +573,8 @@ static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy, } list_for_each_entry(t, &cpufreq_governor_list, governor_list) { - if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) - (CPUFREQ_NAME_LEN + 2))) + if (i >= (ssize_t) ((PAGE_SIZE / sizeof(char)) + - (CPUFREQ_NAME_LEN + 2))) goto out; i += scnprintf(&buf[i], CPUFREQ_NAME_LEN, "%s ", t->name); } @@ -594,7 +593,7 @@ static ssize_t show_cpus(const struct cpumask *mask, char *buf) i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), " "); i += scnprintf(&buf[i], (PAGE_SIZE - i - 2), "%u", cpu); if (i >= (PAGE_SIZE - 5)) - break; + break; } i += sprintf(&buf[i], "\n"); return i; @@ -684,10 +683,10 @@ static struct attribute *default_attrs[] = { NULL }; -#define to_policy(k) container_of(k,struct cpufreq_policy,kobj) -#define to_attr(a) container_of(a,struct freq_attr,attr) +#define to_policy(k) container_of(k, struct cpufreq_policy, kobj) +#define to_attr(a) container_of(a, struct freq_attr, attr) -static ssize_t show(struct kobject *kobj, struct attribute *attr ,char *buf) +static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) { struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); @@ -858,10 +857,10 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) if (cpu == j) continue; - /* check for existing affected CPUs. They may not be aware - * of it due to CPU Hotplug. + /* Check for existing affected CPUs. + * They may not be aware of it due to CPU Hotplug. */ - managed_policy = cpufreq_cpu_get(j); // FIXME: Where is this released? What about error paths? + managed_policy = cpufreq_cpu_get(j); /* FIXME: Where is this released? What about error paths? */ if (unlikely(managed_policy)) { /* Set proper policy_cpu */ @@ -1142,8 +1141,8 @@ static void handle_update(struct work_struct *work) * @old_freq: CPU frequency the kernel thinks the CPU runs at * @new_freq: CPU frequency the CPU actually runs at * - * We adjust to current frequency first, and need to clean up later. So either call - * to cpufreq_update_policy() or schedule handle_update()). + * We adjust to current frequency first, and need to clean up later. + * So either call to cpufreq_update_policy() or schedule handle_update()). */ static void cpufreq_out_of_sync(unsigned int cpu, unsigned int old_freq, unsigned int new_freq) @@ -1625,7 +1624,8 @@ EXPORT_SYMBOL_GPL(cpufreq_unregister_governor); /** * cpufreq_get_policy - get the current cpufreq_policy - * @policy: struct cpufreq_policy into which the current cpufreq_policy is written + * @policy: struct cpufreq_policy into which the current cpufreq_policy + * is written * * Reads the current cpufreq policy. */ -- cgit v1.2.3 From 9acef4875695a7717734f2578666a64822ea6495 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 18 Jan 2009 01:39:51 -0500 Subject: [CPUFREQ] checkpatch cleanups for conservative governor Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 0320962c4ec..c6b3c6a02fc 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -82,7 +82,7 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */ * cpu_hotplug lock should be taken before that. Note that cpu_hotplug lock * is recursive for the same process. -Venki */ -static DEFINE_MUTEX (dbs_mutex); +static DEFINE_MUTEX(dbs_mutex); static DECLARE_DELAYED_WORK(dbs_work, do_dbs_timer); struct dbs_tuners { @@ -140,12 +140,12 @@ static struct notifier_block dbs_cpufreq_notifier_block = { /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) { - return sprintf (buf, "%u\n", MAX_SAMPLING_RATE); + return sprintf(buf, "%u\n", MAX_SAMPLING_RATE); } static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) { - return sprintf (buf, "%u\n", MIN_SAMPLING_RATE); + return sprintf(buf, "%u\n", MIN_SAMPLING_RATE); } #define define_one_ro(_name) \ @@ -174,7 +174,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, { unsigned int input; int ret; - ret = sscanf (buf, "%u", &input); + ret = sscanf(buf, "%u", &input); if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) return -EINVAL; @@ -190,10 +190,11 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, { unsigned int input; int ret; - ret = sscanf (buf, "%u", &input); + ret = sscanf(buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > MAX_SAMPLING_RATE || input < MIN_SAMPLING_RATE) { + if (ret != 1 || input > MAX_SAMPLING_RATE || + input < MIN_SAMPLING_RATE) { mutex_unlock(&dbs_mutex); return -EINVAL; } @@ -209,10 +210,11 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, { unsigned int input; int ret; - ret = sscanf (buf, "%u", &input); + ret = sscanf(buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > 100 || input <= dbs_tuners_ins.down_threshold) { + if (ret != 1 || input > 100 || + input <= dbs_tuners_ins.down_threshold) { mutex_unlock(&dbs_mutex); return -EINVAL; } @@ -228,7 +230,7 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused, { unsigned int input; int ret; - ret = sscanf (buf, "%u", &input); + ret = sscanf(buf, "%u", &input); mutex_lock(&dbs_mutex); if (ret != 1 || input > 100 || input >= dbs_tuners_ins.up_threshold) { @@ -310,7 +312,7 @@ define_one_rw(down_threshold); define_one_rw(ignore_nice_load); define_one_rw(freq_step); -static struct attribute * dbs_attributes[] = { +static struct attribute *dbs_attributes[] = { &sampling_rate_max.attr, &sampling_rate_min.attr, &sampling_rate.attr, @@ -600,11 +602,11 @@ static void __exit cpufreq_gov_dbs_exit(void) } -MODULE_AUTHOR ("Alexander Clouter "); -MODULE_DESCRIPTION ("'cpufreq_conservative' - A dynamic cpufreq governor for " +MODULE_AUTHOR("Alexander Clouter "); +MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " "Low Latency Frequency Transition capable processors " "optimised for use in a battery environment"); -MODULE_LICENSE ("GPL"); +MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE fs_initcall(cpufreq_gov_dbs_init); -- cgit v1.2.3 From 0a829c5afde8e9e9c33a3a5c231b04dcf253337d Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 18 Jan 2009 01:49:04 -0500 Subject: [CPUFREQ] checkpatch cleanups for cpufreq_stats Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_stats.c | 74 +++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index c0ff97d375d..5a62d678dd1 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -2,7 +2,7 @@ * drivers/cpufreq/cpufreq_stats.c * * Copyright (C) 2003-2004 Venkatesh Pallipadi . - * (C) 2004 Zou Nan hai . + * (C) 2004 Zou Nan hai . * * 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 @@ -23,7 +23,7 @@ static spinlock_t cpufreq_stats_lock; -#define CPUFREQ_STATDEVICE_ATTR(_name,_mode,_show) \ +#define CPUFREQ_STATDEVICE_ATTR(_name, _mode, _show) \ static struct freq_attr _attr_##_name = {\ .attr = {.name = __stringify(_name), .mode = _mode, }, \ .show = _show,\ @@ -50,8 +50,7 @@ struct cpufreq_stats_attribute { ssize_t(*show) (struct cpufreq_stats *, char *); }; -static int -cpufreq_stats_update (unsigned int cpu) +static int cpufreq_stats_update(unsigned int cpu) { struct cpufreq_stats *stat; unsigned long long cur_time; @@ -68,8 +67,7 @@ cpufreq_stats_update (unsigned int cpu) return 0; } -static ssize_t -show_total_trans(struct cpufreq_policy *policy, char *buf) +static ssize_t show_total_trans(struct cpufreq_policy *policy, char *buf) { struct cpufreq_stats *stat = per_cpu(cpufreq_stats_table, policy->cpu); if (!stat) @@ -78,8 +76,7 @@ show_total_trans(struct cpufreq_policy *policy, char *buf) per_cpu(cpufreq_stats_table, stat->cpu)->total_trans); } -static ssize_t -show_time_in_state(struct cpufreq_policy *policy, char *buf) +static ssize_t show_time_in_state(struct cpufreq_policy *policy, char *buf) { ssize_t len = 0; int i; @@ -89,14 +86,14 @@ show_time_in_state(struct cpufreq_policy *policy, char *buf) cpufreq_stats_update(stat->cpu); for (i = 0; i < stat->state_num; i++) { len += sprintf(buf + len, "%u %llu\n", stat->freq_table[i], - (unsigned long long)cputime64_to_clock_t(stat->time_in_state[i])); + (unsigned long long) + cputime64_to_clock_t(stat->time_in_state[i])); } return len; } #ifdef CONFIG_CPU_FREQ_STAT_DETAILS -static ssize_t -show_trans_table(struct cpufreq_policy *policy, char *buf) +static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) { ssize_t len = 0; int i, j; @@ -139,11 +136,11 @@ show_trans_table(struct cpufreq_policy *policy, char *buf) return PAGE_SIZE; return len; } -CPUFREQ_STATDEVICE_ATTR(trans_table,0444,show_trans_table); +CPUFREQ_STATDEVICE_ATTR(trans_table, 0444, show_trans_table); #endif -CPUFREQ_STATDEVICE_ATTR(total_trans,0444,show_total_trans); -CPUFREQ_STATDEVICE_ATTR(time_in_state,0444,show_time_in_state); +CPUFREQ_STATDEVICE_ATTR(total_trans, 0444, show_total_trans); +CPUFREQ_STATDEVICE_ATTR(time_in_state, 0444, show_time_in_state); static struct attribute *default_attrs[] = { &_attr_total_trans.attr, @@ -158,8 +155,7 @@ static struct attribute_group stats_attr_group = { .name = "stats" }; -static int -freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) +static int freq_table_get_index(struct cpufreq_stats *stat, unsigned int freq) { int index; for (index = 0; index < stat->max_state; index++) @@ -183,8 +179,7 @@ static void cpufreq_stats_free_table(unsigned int cpu) cpufreq_cpu_put(policy); } -static int -cpufreq_stats_create_table (struct cpufreq_policy *policy, +static int cpufreq_stats_create_table(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table) { unsigned int i, j, count = 0, ret = 0; @@ -194,7 +189,8 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, unsigned int cpu = policy->cpu; if (per_cpu(cpufreq_stats_table, cpu)) return -EBUSY; - if ((stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL)) == NULL) + stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL); + if ((stat) == NULL) return -ENOMEM; data = cpufreq_cpu_get(cpu); @@ -203,13 +199,14 @@ cpufreq_stats_create_table (struct cpufreq_policy *policy, goto error_get_fail; } - if ((ret = sysfs_create_group(&data->kobj, &stats_attr_group))) + ret = sysfs_create_group(&data->kobj, &stats_attr_group); + if (ret) goto error_out; stat->cpu = cpu; per_cpu(cpufreq_stats_table, cpu) = stat; - for (i=0; table[i].frequency != CPUFREQ_TABLE_END; i++) { + for (i = 0; table[i].frequency != CPUFREQ_TABLE_END; i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; @@ -255,9 +252,8 @@ error_get_fail: return ret; } -static int -cpufreq_stat_notifier_policy (struct notifier_block *nb, unsigned long val, - void *data) +static int cpufreq_stat_notifier_policy(struct notifier_block *nb, + unsigned long val, void *data) { int ret; struct cpufreq_policy *policy = data; @@ -268,14 +264,14 @@ cpufreq_stat_notifier_policy (struct notifier_block *nb, unsigned long val, table = cpufreq_frequency_get_table(cpu); if (!table) return 0; - if ((ret = cpufreq_stats_create_table(policy, table))) + ret = cpufreq_stats_create_table(policy, table); + if (ret) return ret; return 0; } -static int -cpufreq_stat_notifier_trans (struct notifier_block *nb, unsigned long val, - void *data) +static int cpufreq_stat_notifier_trans(struct notifier_block *nb, + unsigned long val, void *data) { struct cpufreq_freqs *freq = data; struct cpufreq_stats *stat; @@ -340,19 +336,20 @@ static struct notifier_block notifier_trans_block = { .notifier_call = cpufreq_stat_notifier_trans }; -static int -__init cpufreq_stats_init(void) +static int __init cpufreq_stats_init(void) { int ret; unsigned int cpu; spin_lock_init(&cpufreq_stats_lock); - if ((ret = cpufreq_register_notifier(¬ifier_policy_block, - CPUFREQ_POLICY_NOTIFIER))) + ret = cpufreq_register_notifier(¬ifier_policy_block, + CPUFREQ_POLICY_NOTIFIER); + if (ret) return ret; - if ((ret = cpufreq_register_notifier(¬ifier_trans_block, - CPUFREQ_TRANSITION_NOTIFIER))) { + ret = cpufreq_register_notifier(¬ifier_trans_block, + CPUFREQ_TRANSITION_NOTIFIER); + if (ret) { cpufreq_unregister_notifier(¬ifier_policy_block, CPUFREQ_POLICY_NOTIFIER); return ret; @@ -364,8 +361,7 @@ __init cpufreq_stats_init(void) } return 0; } -static void -__exit cpufreq_stats_exit(void) +static void __exit cpufreq_stats_exit(void) { unsigned int cpu; @@ -379,10 +375,10 @@ __exit cpufreq_stats_exit(void) } } -MODULE_AUTHOR ("Zou Nan hai "); -MODULE_DESCRIPTION ("'cpufreq_stats' - A driver to export cpufreq stats " +MODULE_AUTHOR("Zou Nan hai "); +MODULE_DESCRIPTION("'cpufreq_stats' - A driver to export cpufreq stats " "through sysfs filesystem"); -MODULE_LICENSE ("GPL"); +MODULE_LICENSE("GPL"); module_init(cpufreq_stats_init); module_exit(cpufreq_stats_exit); -- cgit v1.2.3 From 1bceb8d13907d681b7eac9ae0ae14f2eecae9801 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 18 Jan 2009 01:51:46 -0500 Subject: [CPUFREQ] checkpatch cleanups for userspace governor Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_userspace.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c index 1442bbada05..66d2d1d6c80 100644 --- a/drivers/cpufreq/cpufreq_userspace.c +++ b/drivers/cpufreq/cpufreq_userspace.c @@ -24,9 +24,6 @@ #include #include -#include - - /** * A few values needed by the userspace governor */ @@ -37,7 +34,7 @@ static DEFINE_PER_CPU(unsigned int, cpu_set_freq); /* CPU freq desired by userspace */ static DEFINE_PER_CPU(unsigned int, cpu_is_managed); -static DEFINE_MUTEX (userspace_mutex); +static DEFINE_MUTEX(userspace_mutex); static int cpus_using_userspace_governor; #define dprintk(msg...) \ @@ -46,9 +43,9 @@ static int cpus_using_userspace_governor; /* keep track of frequency transitions */ static int userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val, - void *data) + void *data) { - struct cpufreq_freqs *freq = data; + struct cpufreq_freqs *freq = data; if (!per_cpu(cpu_is_managed, freq->cpu)) return 0; @@ -57,11 +54,11 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val, freq->cpu, freq->new); per_cpu(cpu_cur_freq, freq->cpu) = freq->new; - return 0; + return 0; } static struct notifier_block userspace_cpufreq_notifier_block = { - .notifier_call = userspace_cpufreq_notifier + .notifier_call = userspace_cpufreq_notifier }; @@ -93,8 +90,11 @@ static int cpufreq_set(struct cpufreq_policy *policy, unsigned int freq) * We're safe from concurrent calls to ->target() here * as we hold the userspace_mutex lock. If we were calling * cpufreq_driver_target, a deadlock situation might occur: - * A: cpufreq_set (lock userspace_mutex) -> cpufreq_driver_target(lock policy->lock) - * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_mutex) + * A: cpufreq_set (lock userspace_mutex) -> + * cpufreq_driver_target(lock policy->lock) + * B: cpufreq_set_policy(lock policy->lock) -> + * __cpufreq_governor -> + * cpufreq_governor_userspace (lock userspace_mutex) */ ret = __cpufreq_driver_target(policy, freq, CPUFREQ_RELATION_L); @@ -210,9 +210,10 @@ static void __exit cpufreq_gov_userspace_exit(void) } -MODULE_AUTHOR ("Dominik Brodowski , Russell King "); -MODULE_DESCRIPTION ("CPUfreq policy governor 'userspace'"); -MODULE_LICENSE ("GPL"); +MODULE_AUTHOR("Dominik Brodowski , " + "Russell King "); +MODULE_DESCRIPTION("CPUfreq policy governor 'userspace'"); +MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE fs_initcall(cpufreq_gov_userspace_init); -- cgit v1.2.3 From 97acec55de8b168548665f267c9dd45ed863b179 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 18 Jan 2009 01:56:41 -0500 Subject: [CPUFREQ] checkpatch cleanups for freq_table Signed-off-by: Dave Jones --- drivers/cpufreq/freq_table.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index 9071d80fbba..a9bd3a05a68 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -28,7 +28,7 @@ int cpufreq_frequency_table_cpuinfo(struct cpufreq_policy *policy, unsigned int max_freq = 0; unsigned int i; - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) { dprintk("table entry %u is invalid, skipping\n", i); @@ -70,7 +70,7 @@ int cpufreq_frequency_table_verify(struct cpufreq_policy *policy, cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq, policy->cpuinfo.max_freq); - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; @@ -125,13 +125,13 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, if (!cpu_online(policy->cpu)) return -EINVAL; - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { unsigned int freq = table[i].frequency; if (freq == CPUFREQ_ENTRY_INVALID) continue; if ((freq < policy->min) || (freq > policy->max)) continue; - switch(relation) { + switch (relation) { case CPUFREQ_RELATION_H: if (freq <= target_freq) { if (freq >= optimal.frequency) { @@ -178,7 +178,7 @@ static DEFINE_PER_CPU(struct cpufreq_frequency_table *, show_table); /** * show_available_freqs - show available frequencies for the specified CPU */ -static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf) +static ssize_t show_available_freqs(struct cpufreq_policy *policy, char *buf) { unsigned int i = 0; unsigned int cpu = policy->cpu; @@ -190,7 +190,7 @@ static ssize_t show_available_freqs (struct cpufreq_policy *policy, char *buf) table = per_cpu(show_table, cpu); - for (i=0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { + for (i = 0; (table[i].frequency != CPUFREQ_TABLE_END); i++) { if (table[i].frequency == CPUFREQ_ENTRY_INVALID) continue; count += sprintf(&buf[count], "%d ", table[i].frequency); @@ -234,6 +234,6 @@ struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu) } EXPORT_SYMBOL_GPL(cpufreq_frequency_get_table); -MODULE_AUTHOR ("Dominik Brodowski "); -MODULE_DESCRIPTION ("CPUfreq frequency table helpers"); -MODULE_LICENSE ("GPL"); +MODULE_AUTHOR("Dominik Brodowski "); +MODULE_DESCRIPTION("CPUfreq frequency table helpers"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 2b03f891ad3804dd3fa4dadfd33e5dcb200389c5 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Sun, 18 Jan 2009 01:43:44 -0500 Subject: [CPUFREQ] checkpatch cleanups for ondemand governor. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_ondemand.c | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 6f45b1658a6..1fa4420eb33 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -65,14 +65,14 @@ struct cpu_dbs_info_s { cputime64_t prev_cpu_wall; cputime64_t prev_cpu_nice; struct cpufreq_policy *cur_policy; - struct delayed_work work; + struct delayed_work work; struct cpufreq_frequency_table *freq_table; unsigned int freq_lo; unsigned int freq_lo_jiffies; unsigned int freq_hi_jiffies; int cpu; unsigned int enable:1, - sample_type:1; + sample_type:1; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); @@ -203,12 +203,12 @@ static void ondemand_powersave_bias_init(void) /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) { - return sprintf (buf, "%u\n", MAX_SAMPLING_RATE); + return sprintf(buf, "%u\n", MAX_SAMPLING_RATE); } static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) { - return sprintf (buf, "%u\n", MIN_SAMPLING_RATE); + return sprintf(buf, "%u\n", MIN_SAMPLING_RATE); } #define define_one_ro(_name) \ @@ -279,14 +279,14 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, unsigned int j; ret = sscanf(buf, "%u", &input); - if ( ret != 1 ) + if (ret != 1) return -EINVAL; - if ( input > 1 ) + if (input > 1) input = 1; mutex_lock(&dbs_mutex); - if ( input == dbs_tuners_ins.ignore_nice ) { /* nothing to do */ + if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */ mutex_unlock(&dbs_mutex); return count; } @@ -337,7 +337,7 @@ define_one_rw(up_threshold); define_one_rw(ignore_nice_load); define_one_rw(powersave_bias); -static struct attribute * dbs_attributes[] = { +static struct attribute *dbs_attributes[] = { &sampling_rate_max.attr, &sampling_rate_min.attr, &sampling_rate.attr, @@ -512,8 +512,7 @@ static void do_dbs_timer(struct work_struct *work) } } else { __cpufreq_driver_target(dbs_info->cur_policy, - dbs_info->freq_lo, - CPUFREQ_RELATION_H); + dbs_info->freq_lo, CPUFREQ_RELATION_H); } queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay); unlock_policy_rwsem_write(cpu); @@ -530,7 +529,7 @@ static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) dbs_info->sample_type = DBS_NORMAL_SAMPLE; INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); queue_delayed_work_on(dbs_info->cpu, kondemand_wq, &dbs_info->work, - delay); + delay); } static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) @@ -617,12 +616,10 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, mutex_lock(&dbs_mutex); if (policy->max < this_dbs_info->cur_policy->cur) __cpufreq_driver_target(this_dbs_info->cur_policy, - policy->max, - CPUFREQ_RELATION_H); + policy->max, CPUFREQ_RELATION_H); else if (policy->min > this_dbs_info->cur_policy->cur) __cpufreq_driver_target(this_dbs_info->cur_policy, - policy->min, - CPUFREQ_RELATION_L); + policy->min, CPUFREQ_RELATION_L); mutex_unlock(&dbs_mutex); break; } @@ -677,7 +674,7 @@ static void __exit cpufreq_gov_dbs_exit(void) MODULE_AUTHOR("Venkatesh Pallipadi "); MODULE_AUTHOR("Alexey Starikovskiy "); MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for " - "Low Latency Frequency Transition capable processors"); + "Low Latency Frequency Transition capable processors"); MODULE_LICENSE("GPL"); #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND -- cgit v1.2.3 From ed12978453a3845c947695e7ad32bb3ede444813 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Wed, 4 Feb 2009 01:17:41 +0100 Subject: [CPUFREQ] Introduce /sys/devices/system/cpu/cpu*/cpufreq/cpuinfo_transition_latency It's not only useful for the ondemand and conservative governors, but also for userspace daemons to know about the HW transition latency of the CPU. It is especially useful for userspace to know about this value when the ondemand or conservative governors are run. The sampling rate control value depends on it and for userspace being able to set sane tuning values there it has to know about the transition latency. Signed-off-by: Thomas Renninger Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 1867dac35af..6fe466efb0b 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -452,6 +452,7 @@ static ssize_t show_##file_name \ show_one(cpuinfo_min_freq, cpuinfo.min_freq); show_one(cpuinfo_max_freq, cpuinfo.max_freq); +show_one(cpuinfo_transition_latency, cpuinfo.transition_latency); show_one(scaling_min_freq, min); show_one(scaling_max_freq, max); show_one(scaling_cur_freq, cur); @@ -659,6 +660,7 @@ __ATTR(_name, 0644, show_##_name, store_##_name) define_one_ro0400(cpuinfo_cur_freq); define_one_ro(cpuinfo_min_freq); define_one_ro(cpuinfo_max_freq); +define_one_ro(cpuinfo_transition_latency); define_one_ro(scaling_available_governors); define_one_ro(scaling_driver); define_one_ro(scaling_cur_freq); @@ -672,6 +674,7 @@ define_one_rw(scaling_setspeed); static struct attribute *default_attrs[] = { &cpuinfo_min_freq.attr, &cpuinfo_max_freq.attr, + &cpuinfo_transition_latency.attr, &scaling_min_freq.attr, &scaling_max_freq.attr, &affected_cpus.attr, -- cgit v1.2.3 From 9411b4ef7fcb534fe1582fe02738254e398dd931 Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Wed, 4 Feb 2009 11:54:04 +0100 Subject: [CPUFREQ] ondemand/conservative: deprecate sampling_rate{min,max} The same info can be obtained via the transition_latency sysfs file Signed-off-by: Thomas Renninger Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 15 +++++++++++++++ drivers/cpufreq/cpufreq_ondemand.c | 17 +++++++++++++++++ 2 files changed, 32 insertions(+) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index c6b3c6a02fc..0912d7ca8cd 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -140,11 +140,26 @@ static struct notifier_block dbs_cpufreq_notifier_block = { /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) { + static int print_once; + + if (!print_once) { + printk(KERN_INFO "CPUFREQ: conservative sampling_rate_max " + "sysfs file is deprecated - used by: %s\n", + current->comm); + print_once = 1; + } return sprintf(buf, "%u\n", MAX_SAMPLING_RATE); } static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) { + static int print_once; + + if (!print_once) { + printk(KERN_INFO "CPUFREQ: conservative sampling_rate_max " + "sysfs file is deprecated - used by: %s\n", current->comm); + print_once = 1; + } return sprintf(buf, "%u\n", MIN_SAMPLING_RATE); } diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 1fa4420eb33..32ddeaa4224 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -21,6 +21,7 @@ #include #include #include +#include /* * dbs is used in this file as a shortform for demandbased switching @@ -203,11 +204,27 @@ static void ondemand_powersave_bias_init(void) /************************** sysfs interface ************************/ static ssize_t show_sampling_rate_max(struct cpufreq_policy *policy, char *buf) { + static int print_once; + + if (!print_once) { + printk(KERN_INFO "CPUFREQ: ondemand sampling_rate_max " + "sysfs file is deprecated - used by: %s\n", + current->comm); + print_once = 1; + } return sprintf(buf, "%u\n", MAX_SAMPLING_RATE); } static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) { + static int print_once; + + if (!print_once) { + printk(KERN_INFO "CPUFREQ: ondemand sampling_rate_min " + "sysfs file is deprecated - used by: %s\n", + current->comm); + print_once = 1; + } return sprintf(buf, "%u\n", MIN_SAMPLING_RATE); } -- cgit v1.2.3 From 112124ab0a9f507a0d7fdbb1e1ed2b9a24f8c4ea Mon Sep 17 00:00:00 2001 From: Thomas Renninger Date: Wed, 4 Feb 2009 11:55:12 +0100 Subject: [CPUFREQ] ondemand/conservative: sanitize sampling_rate restrictions Limit sampling rate to transition_latency * 100 or kernel limits. If sampling_rate is tried to be set too low, set the lowest allowed value. Signed-off-by: Thomas Renninger Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 28 ++++++++++++++++++---------- drivers/cpufreq/cpufreq_ondemand.c | 28 ++++++++++++++++++---------- 2 files changed, 36 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 0912d7ca8cd..8d541c69aec 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -54,8 +54,20 @@ static unsigned int def_sampling_rate; (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) #define MIN_SAMPLING_RATE \ (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) +/* Above MIN_SAMPLING_RATE will vanish with its sysfs file soon + * Define the minimal settable sampling rate to the greater of: + * - "HW transition latency" * 100 (same as default sampling / 10) + * - MIN_STAT_SAMPLING_RATE + * To avoid that userspace shoots itself. +*/ +static unsigned int minimum_sampling_rate(void) +{ + return max(def_sampling_rate / 10, MIN_STAT_SAMPLING_RATE); +} + +/* This will also vanish soon with removing sampling_rate_max */ #define MAX_SAMPLING_RATE (500 * def_sampling_rate) -#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) +#define LATENCY_MULTIPLIER (1000) #define DEF_SAMPLING_DOWN_FACTOR (1) #define MAX_SAMPLING_DOWN_FACTOR (10) #define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) @@ -208,13 +220,11 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, ret = sscanf(buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > MAX_SAMPLING_RATE || - input < MIN_SAMPLING_RATE) { + if (ret != 1) { mutex_unlock(&dbs_mutex); return -EINVAL; } - - dbs_tuners_ins.sampling_rate = input; + dbs_tuners_ins.sampling_rate = max(input, minimum_sampling_rate()); mutex_unlock(&dbs_mutex); return count; @@ -540,11 +550,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (latency == 0) latency = 1; - def_sampling_rate = 10 * latency * - DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; - - if (def_sampling_rate < MIN_STAT_SAMPLING_RATE) - def_sampling_rate = MIN_STAT_SAMPLING_RATE; + def_sampling_rate = + max(10 * latency * LATENCY_MULTIPLIER, + MIN_STAT_SAMPLING_RATE); dbs_tuners_ins.sampling_rate = def_sampling_rate; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 32ddeaa4224..338f428a15b 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -52,8 +52,20 @@ static unsigned int def_sampling_rate; (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) #define MIN_SAMPLING_RATE \ (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) +/* Above MIN_SAMPLING_RATE will vanish with its sysfs file soon + * Define the minimal settable sampling rate to the greater of: + * - "HW transition latency" * 100 (same as default sampling / 10) + * - MIN_STAT_SAMPLING_RATE + * To avoid that userspace shoots itself. +*/ +static unsigned int minimum_sampling_rate(void) +{ + return max(def_sampling_rate / 10, MIN_STAT_SAMPLING_RATE); +} + +/* This will also vanish soon with removing sampling_rate_max */ #define MAX_SAMPLING_RATE (500 * def_sampling_rate) -#define DEF_SAMPLING_RATE_LATENCY_MULTIPLIER (1000) +#define LATENCY_MULTIPLIER (1000) #define TRANSITION_LATENCY_LIMIT (10 * 1000 * 1000) static void do_dbs_timer(struct work_struct *work); @@ -255,13 +267,11 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, ret = sscanf(buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > MAX_SAMPLING_RATE - || input < MIN_SAMPLING_RATE) { + if (ret != 1) { mutex_unlock(&dbs_mutex); return -EINVAL; } - - dbs_tuners_ins.sampling_rate = input; + dbs_tuners_ins.sampling_rate = max(input, minimum_sampling_rate()); mutex_unlock(&dbs_mutex); return count; @@ -607,11 +617,9 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, if (latency == 0) latency = 1; - def_sampling_rate = latency * - DEF_SAMPLING_RATE_LATENCY_MULTIPLIER; - - if (def_sampling_rate < MIN_STAT_SAMPLING_RATE) - def_sampling_rate = MIN_STAT_SAMPLING_RATE; + def_sampling_rate = + max(latency * LATENCY_MULTIPLIER, + MIN_STAT_SAMPLING_RATE); dbs_tuners_ins.sampling_rate = def_sampling_rate; } -- cgit v1.2.3 From 11a80a9c7668c40c40a03ae15bd2c6b215058b2e Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 13 Feb 2009 19:01:01 +0000 Subject: [CPUFREQ] conservative: amend author's email address Amend author's email address. Signed-off-by: Alexander Clouter Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 8d541c69aec..a18cfbf021b 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -4,7 +4,7 @@ * Copyright (C) 2001 Russell King * (C) 2003 Venkatesh Pallipadi . * Jun Nakajima - * (C) 2004 Alexander Clouter + * (C) 2009 Alexander Clouter * * 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 @@ -625,7 +625,7 @@ static void __exit cpufreq_gov_dbs_exit(void) } -MODULE_AUTHOR("Alexander Clouter "); +MODULE_AUTHOR("Alexander Clouter "); MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for " "Low Latency Frequency Transition capable processors " "optimised for use in a battery environment"); -- cgit v1.2.3 From f407a08bb7eff5ddbe0d9173d8717794a910771f Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 13 Feb 2009 19:01:51 +0000 Subject: [CPUFREQ] conservative: fix dbs_cpufreq_notifier so freq is not locked When someone added the dbs_cpufreq_notifier section to the governor the code ended up causing the frequency to only fall. This is because requested_freq is tinkered with and that should only modified if it has an invlaid value due to changes in the available frequency ranges This should fix #10055. Signed-off-by: Alexander Clouter Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index a18cfbf021b..a16a5b8c1dc 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -137,10 +137,21 @@ dbs_cpufreq_notifier(struct notifier_block *nb, unsigned long val, struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info, freq->cpu); + struct cpufreq_policy *policy; + if (!this_dbs_info->enable) return 0; - this_dbs_info->requested_freq = freq->new; + policy = this_dbs_info->cur_policy; + + /* + * we only care if our internally tracked freq moves outside + * the 'valid' ranges of freqency available to us otherwise + * we do not change it + */ + if (this_dbs_info->requested_freq > policy->max + || this_dbs_info->requested_freq < policy->min) + this_dbs_info->requested_freq = freq->new; return 0; } -- cgit v1.2.3 From 8e677ce83bf41ba9c74e5b6d9ee60b07d4e5ed93 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 13 Feb 2009 19:02:34 +0000 Subject: [CPUFREQ] conservative: fixup governor to function more like ondemand logic As conservative is based off ondemand the codebases occasionally need to be resync'd. This patch, although ugly, does this. Signed-off-by: Alexander Clouter Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 328 +++++++++++++++++++-------------- 1 file changed, 188 insertions(+), 140 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index a16a5b8c1dc..c9bd0c55ad1 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -13,22 +13,17 @@ #include #include -#include #include -#include -#include #include -#include -#include -#include -#include #include -#include -#include #include #include -#include #include +#include +#include +#include +#include + /* * dbs is used in this file as a shortform for demandbased switching * It helps to keep variable names smaller, simpler @@ -43,14 +38,14 @@ * latency of the processor. The governor will work on any processor with * transition latency <= 10mS, using appropriate sampling * rate. - * For CPUs with transition latency > 10mS (mostly drivers - * with CPUFREQ_ETERNAL), this governor will not work. + * For CPUs with transition latency > 10mS (mostly drivers with CPUFREQ_ETERNAL) + * this governor will not work. * All times here are in uS. */ static unsigned int def_sampling_rate; #define MIN_SAMPLING_RATE_RATIO (2) /* for correct statistics, we need at least 10 ticks between each measure */ -#define MIN_STAT_SAMPLING_RATE \ +#define MIN_STAT_SAMPLING_RATE \ (MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10)) #define MIN_SAMPLING_RATE \ (def_sampling_rate / MIN_SAMPLING_RATE_RATIO) @@ -75,12 +70,15 @@ static unsigned int minimum_sampling_rate(void) static void do_dbs_timer(struct work_struct *work); struct cpu_dbs_info_s { + cputime64_t prev_cpu_idle; + cputime64_t prev_cpu_wall; + cputime64_t prev_cpu_nice; struct cpufreq_policy *cur_policy; - unsigned int prev_cpu_idle_up; - unsigned int prev_cpu_idle_down; - unsigned int enable; + struct delayed_work work; unsigned int down_skip; unsigned int requested_freq; + int cpu; + unsigned int enable:1; }; static DEFINE_PER_CPU(struct cpu_dbs_info_s, cpu_dbs_info); @@ -95,18 +93,17 @@ static unsigned int dbs_enable; /* number of CPUs using this policy */ * is recursive for the same process. -Venki */ static DEFINE_MUTEX(dbs_mutex); -static DECLARE_DELAYED_WORK(dbs_work, do_dbs_timer); -struct dbs_tuners { +static struct workqueue_struct *kconservative_wq; + +static struct dbs_tuners { unsigned int sampling_rate; unsigned int sampling_down_factor; unsigned int up_threshold; unsigned int down_threshold; unsigned int ignore_nice; unsigned int freq_step; -}; - -static struct dbs_tuners dbs_tuners_ins = { +} dbs_tuners_ins = { .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, .down_threshold = DEF_FREQUENCY_DOWN_THRESHOLD, .sampling_down_factor = DEF_SAMPLING_DOWN_FACTOR, @@ -114,18 +111,37 @@ static struct dbs_tuners dbs_tuners_ins = { .freq_step = 5, }; -static inline unsigned int get_cpu_idle_time(unsigned int cpu) +static inline cputime64_t get_cpu_idle_time_jiffy(unsigned int cpu, + cputime64_t *wall) { - unsigned int add_nice = 0, ret; + cputime64_t idle_time; + cputime64_t cur_wall_time; + cputime64_t busy_time; + + cur_wall_time = jiffies64_to_cputime64(get_jiffies_64()); + busy_time = cputime64_add(kstat_cpu(cpu).cpustat.user, + kstat_cpu(cpu).cpustat.system); - if (dbs_tuners_ins.ignore_nice) - add_nice = kstat_cpu(cpu).cpustat.nice; + busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.irq); + busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.softirq); + busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.steal); + busy_time = cputime64_add(busy_time, kstat_cpu(cpu).cpustat.nice); - ret = kstat_cpu(cpu).cpustat.idle + - kstat_cpu(cpu).cpustat.iowait + - add_nice; + idle_time = cputime64_sub(cur_wall_time, busy_time); + if (wall) + *wall = cur_wall_time; - return ret; + return idle_time; +} + +static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) +{ + u64 idle_time = get_cpu_idle_time_us(cpu, wall); + + if (idle_time == -1ULL) + return get_cpu_idle_time_jiffy(cpu, wall); + + return idle_time; } /* keep track of frequency transitions */ @@ -186,8 +202,8 @@ static ssize_t show_sampling_rate_min(struct cpufreq_policy *policy, char *buf) return sprintf(buf, "%u\n", MIN_SAMPLING_RATE); } -#define define_one_ro(_name) \ -static struct freq_attr _name = \ +#define define_one_ro(_name) \ +static struct freq_attr _name = \ __ATTR(_name, 0444, show_##_name, NULL) define_one_ro(sampling_rate_max); @@ -213,6 +229,7 @@ static ssize_t store_sampling_down_factor(struct cpufreq_policy *unused, unsigned int input; int ret; ret = sscanf(buf, "%u", &input); + if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1) return -EINVAL; @@ -230,11 +247,10 @@ static ssize_t store_sampling_rate(struct cpufreq_policy *unused, int ret; ret = sscanf(buf, "%u", &input); - mutex_lock(&dbs_mutex); - if (ret != 1) { - mutex_unlock(&dbs_mutex); + if (ret != 1) return -EINVAL; - } + + mutex_lock(&dbs_mutex); dbs_tuners_ins.sampling_rate = max(input, minimum_sampling_rate()); mutex_unlock(&dbs_mutex); @@ -250,7 +266,7 @@ static ssize_t store_up_threshold(struct cpufreq_policy *unused, mutex_lock(&dbs_mutex); if (ret != 1 || input > 100 || - input <= dbs_tuners_ins.down_threshold) { + input <= dbs_tuners_ins.down_threshold) { mutex_unlock(&dbs_mutex); return -EINVAL; } @@ -269,7 +285,9 @@ static ssize_t store_down_threshold(struct cpufreq_policy *unused, ret = sscanf(buf, "%u", &input); mutex_lock(&dbs_mutex); - if (ret != 1 || input > 100 || input >= dbs_tuners_ins.up_threshold) { + /* cannot be lower than 11 otherwise freq will not fall */ + if (ret != 1 || input < 11 || input > 100 || + input >= dbs_tuners_ins.up_threshold) { mutex_unlock(&dbs_mutex); return -EINVAL; } @@ -302,12 +320,14 @@ static ssize_t store_ignore_nice_load(struct cpufreq_policy *policy, } dbs_tuners_ins.ignore_nice = input; - /* we need to re-evaluate prev_cpu_idle_up and prev_cpu_idle_down */ + /* we need to re-evaluate prev_cpu_idle */ for_each_online_cpu(j) { - struct cpu_dbs_info_s *j_dbs_info; - j_dbs_info = &per_cpu(cpu_dbs_info, j); - j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(j); - j_dbs_info->prev_cpu_idle_down = j_dbs_info->prev_cpu_idle_up; + struct cpu_dbs_info_s *dbs_info; + dbs_info = &per_cpu(cpu_dbs_info, j); + dbs_info->prev_cpu_idle = get_cpu_idle_time(j, + &dbs_info->prev_cpu_wall); + if (dbs_tuners_ins.ignore_nice) + dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice; } mutex_unlock(&dbs_mutex); @@ -319,7 +339,6 @@ static ssize_t store_freq_step(struct cpufreq_policy *policy, { unsigned int input; int ret; - ret = sscanf(buf, "%u", &input); if (ret != 1) @@ -367,55 +386,78 @@ static struct attribute_group dbs_attr_group = { /************************** sysfs end ************************/ -static void dbs_check_cpu(int cpu) +static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) { - unsigned int idle_ticks, up_idle_ticks, down_idle_ticks; - unsigned int tmp_idle_ticks, total_idle_ticks; + unsigned int load = 0; unsigned int freq_target; - unsigned int freq_down_sampling_rate; - struct cpu_dbs_info_s *this_dbs_info = &per_cpu(cpu_dbs_info, cpu); - struct cpufreq_policy *policy; - if (!this_dbs_info->enable) - return; + struct cpufreq_policy *policy; + unsigned int j; policy = this_dbs_info->cur_policy; /* - * The default safe range is 20% to 80% - * Every sampling_rate, we check - * - If current idle time is less than 20%, then we try to - * increase frequency - * Every sampling_rate*sampling_down_factor, we check - * - If current idle time is more than 80%, then we try to - * decrease frequency + * Every sampling_rate, we check, if current idle time is less + * than 20% (default), then we try to increase frequency + * Every sampling_rate*sampling_down_factor, we check, if current + * idle time is more than 80%, then we try to decrease frequency * * Any frequency increase takes it to the maximum frequency. * Frequency reduction happens at minimum steps of - * 5% (default) of max_frequency + * 5% (default) of maximum frequency */ - /* Check for frequency increase */ - idle_ticks = UINT_MAX; + /* Get Absolute Load */ + for_each_cpu(j, policy->cpus) { + struct cpu_dbs_info_s *j_dbs_info; + cputime64_t cur_wall_time, cur_idle_time; + unsigned int idle_time, wall_time; - /* Check for frequency increase */ - total_idle_ticks = get_cpu_idle_time(cpu); - tmp_idle_ticks = total_idle_ticks - - this_dbs_info->prev_cpu_idle_up; - this_dbs_info->prev_cpu_idle_up = total_idle_ticks; + j_dbs_info = &per_cpu(cpu_dbs_info, j); + + cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); + + wall_time = (unsigned int) cputime64_sub(cur_wall_time, + j_dbs_info->prev_cpu_wall); + j_dbs_info->prev_cpu_wall = cur_wall_time; - if (tmp_idle_ticks < idle_ticks) - idle_ticks = tmp_idle_ticks; + idle_time = (unsigned int) cputime64_sub(cur_idle_time, + j_dbs_info->prev_cpu_idle); + j_dbs_info->prev_cpu_idle = cur_idle_time; - /* Scale idle ticks by 100 and compare with up and down ticks */ - idle_ticks *= 100; - up_idle_ticks = (100 - dbs_tuners_ins.up_threshold) * - usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + if (dbs_tuners_ins.ignore_nice) { + cputime64_t cur_nice; + unsigned long cur_nice_jiffies; + + cur_nice = cputime64_sub(kstat_cpu(j).cpustat.nice, + j_dbs_info->prev_cpu_nice); + /* + * Assumption: nice time between sampling periods will + * be less than 2^32 jiffies for 32 bit sys + */ + cur_nice_jiffies = (unsigned long) + cputime64_to_jiffies64(cur_nice); + + j_dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice; + idle_time += jiffies_to_usecs(cur_nice_jiffies); + } + + if (unlikely(!wall_time || wall_time < idle_time)) + continue; + + load = 100 * (wall_time - idle_time) / wall_time; + } + + /* + * break out if we 'cannot' reduce the speed as the user might + * want freq_step to be zero + */ + if (dbs_tuners_ins.freq_step == 0) + return; - if (idle_ticks < up_idle_ticks) { + /* Check for frequency increase */ + if (load > dbs_tuners_ins.up_threshold) { this_dbs_info->down_skip = 0; - this_dbs_info->prev_cpu_idle_down = - this_dbs_info->prev_cpu_idle_up; /* if we are already at full speed then break out early */ if (this_dbs_info->requested_freq == policy->max) @@ -436,49 +478,24 @@ static void dbs_check_cpu(int cpu) return; } - /* Check for frequency decrease */ - this_dbs_info->down_skip++; - if (this_dbs_info->down_skip < dbs_tuners_ins.sampling_down_factor) - return; - - /* Check for frequency decrease */ - total_idle_ticks = this_dbs_info->prev_cpu_idle_up; - tmp_idle_ticks = total_idle_ticks - - this_dbs_info->prev_cpu_idle_down; - this_dbs_info->prev_cpu_idle_down = total_idle_ticks; - - if (tmp_idle_ticks < idle_ticks) - idle_ticks = tmp_idle_ticks; - - /* Scale idle ticks by 100 and compare with up and down ticks */ - idle_ticks *= 100; - this_dbs_info->down_skip = 0; - - freq_down_sampling_rate = dbs_tuners_ins.sampling_rate * - dbs_tuners_ins.sampling_down_factor; - down_idle_ticks = (100 - dbs_tuners_ins.down_threshold) * - usecs_to_jiffies(freq_down_sampling_rate); - - if (idle_ticks > down_idle_ticks) { - /* - * if we are already at the lowest speed then break out early - * or if we 'cannot' reduce the speed as the user might want - * freq_target to be zero - */ - if (this_dbs_info->requested_freq == policy->min - || dbs_tuners_ins.freq_step == 0) - return; - + /* + * The optimal frequency is the frequency that is the lowest that + * can support the current CPU usage without triggering the up + * policy. To be safe, we focus 10 points under the threshold. + */ + if (load < (dbs_tuners_ins.down_threshold - 10)) { freq_target = (dbs_tuners_ins.freq_step * policy->max) / 100; - /* max freq cannot be less than 100. But who knows.... */ - if (unlikely(freq_target == 0)) - freq_target = 5; - this_dbs_info->requested_freq -= freq_target; if (this_dbs_info->requested_freq < policy->min) this_dbs_info->requested_freq = policy->min; + /* + * if we cannot reduce the frequency anymore, break out early + */ + if (policy->cur == policy->min) + return; + __cpufreq_driver_target(policy, this_dbs_info->requested_freq, CPUFREQ_RELATION_H); return; @@ -487,27 +504,45 @@ static void dbs_check_cpu(int cpu) static void do_dbs_timer(struct work_struct *work) { - int i; - mutex_lock(&dbs_mutex); - for_each_online_cpu(i) - dbs_check_cpu(i); - schedule_delayed_work(&dbs_work, - usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); - mutex_unlock(&dbs_mutex); + struct cpu_dbs_info_s *dbs_info = + container_of(work, struct cpu_dbs_info_s, work.work); + unsigned int cpu = dbs_info->cpu; + + /* We want all CPUs to do sampling nearly on same jiffy */ + int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + + delay -= jiffies % delay; + + if (lock_policy_rwsem_write(cpu) < 0) + return; + + if (!dbs_info->enable) { + unlock_policy_rwsem_write(cpu); + return; + } + + dbs_check_cpu(dbs_info); + + queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay); + unlock_policy_rwsem_write(cpu); } -static inline void dbs_timer_init(void) +static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info) { - init_timer_deferrable(&dbs_work.timer); - schedule_delayed_work(&dbs_work, - usecs_to_jiffies(dbs_tuners_ins.sampling_rate)); - return; + /* We want all CPUs to do sampling nearly on same jiffy */ + int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate); + delay -= jiffies % delay; + + dbs_info->enable = 1; + INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer); + queue_delayed_work_on(dbs_info->cpu, kconservative_wq, &dbs_info->work, + delay); } -static inline void dbs_timer_exit(void) +static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) { - cancel_delayed_work(&dbs_work); - return; + dbs_info->enable = 0; + cancel_delayed_work(&dbs_info->work); } static int cpufreq_governor_dbs(struct cpufreq_policy *policy, @@ -541,11 +576,13 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, j_dbs_info = &per_cpu(cpu_dbs_info, j); j_dbs_info->cur_policy = policy; - j_dbs_info->prev_cpu_idle_up = get_cpu_idle_time(cpu); - j_dbs_info->prev_cpu_idle_down - = j_dbs_info->prev_cpu_idle_up; + j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j, + &j_dbs_info->prev_cpu_wall); + if (dbs_tuners_ins.ignore_nice) { + j_dbs_info->prev_cpu_nice = + kstat_cpu(j).cpustat.nice; + } } - this_dbs_info->enable = 1; this_dbs_info->down_skip = 0; this_dbs_info->requested_freq = policy->cur; @@ -567,30 +604,30 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, dbs_tuners_ins.sampling_rate = def_sampling_rate; - dbs_timer_init(); cpufreq_register_notifier( &dbs_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); } + dbs_timer_init(this_dbs_info); mutex_unlock(&dbs_mutex); + break; case CPUFREQ_GOV_STOP: mutex_lock(&dbs_mutex); - this_dbs_info->enable = 0; + dbs_timer_exit(this_dbs_info); sysfs_remove_group(&policy->kobj, &dbs_attr_group); dbs_enable--; + /* * Stop the timerschedule work, when this governor * is used for first time */ - if (dbs_enable == 0) { - dbs_timer_exit(); + if (dbs_enable == 0) cpufreq_unregister_notifier( &dbs_cpufreq_notifier_block, CPUFREQ_TRANSITION_NOTIFIER); - } mutex_unlock(&dbs_mutex); @@ -607,6 +644,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, this_dbs_info->cur_policy, policy->min, CPUFREQ_RELATION_L); mutex_unlock(&dbs_mutex); + break; } return 0; @@ -624,15 +662,25 @@ struct cpufreq_governor cpufreq_gov_conservative = { static int __init cpufreq_gov_dbs_init(void) { - return cpufreq_register_governor(&cpufreq_gov_conservative); + int err; + + kconservative_wq = create_workqueue("kconservative"); + if (!kconservative_wq) { + printk(KERN_ERR "Creation of kconservative failed\n"); + return -EFAULT; + } + + err = cpufreq_register_governor(&cpufreq_gov_conservative); + if (err) + destroy_workqueue(kconservative_wq); + + return err; } static void __exit cpufreq_gov_dbs_exit(void) { - /* Make sure that the scheduled work is indeed not running */ - flush_scheduled_work(); - cpufreq_unregister_governor(&cpufreq_gov_conservative); + destroy_workqueue(kconservative_wq); } -- cgit v1.2.3 From a75603a084f1dd9a9558c8af95fc2acfc54f1021 Mon Sep 17 00:00:00 2001 From: Alexander Clouter Date: Fri, 13 Feb 2009 19:03:26 +0000 Subject: [CPUFREQ] conservative: remove 10x from def_sampling_rate AMD users get particular hit by this issue (bug 8081) as it caps at typically 90 seconds as the minimum period for a frequency change. Harsh eh? Years ago I borked this buy puting the 10x in the wrong place...I fix that by removing it altogether. Signed-off-by: Alexander Clouter Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq_conservative.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index c9bd0c55ad1..2ecd95e4ab1 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -599,7 +599,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, latency = 1; def_sampling_rate = - max(10 * latency * LATENCY_MULTIPLIER, + max(latency * LATENCY_MULTIPLIER, MIN_STAT_SAMPLING_RATE); dbs_tuners_ins.sampling_rate = def_sampling_rate; -- cgit v1.2.3 From b233b28eac0cc37d07c2d007ea08c86c778c5af4 Mon Sep 17 00:00:00 2001 From: Adrian McMenamin Date: Fri, 27 Feb 2009 16:07:32 +0900 Subject: sh: maple: Support block reads and writes. This patch updates the maple bus to support asynchronous block reads and writes as well as generally improving the quality of the code and supporting concurrency (all needed to support the Dreamcast visual memory unit - a driver will also be posted for that). Changes in the bus driver necessitate some changes in the two maple bus input drivers that are currently in mainline. As well as supporting block reads and writes this code clean up removes some poor handling of locks, uses an atomic status variable to serialise access to devices and more robusly handles the general performance problems of the bus. Signed-off-by: Adrian McMenamin Signed-off-by: Paul Mundt --- drivers/input/joystick/maplecontrol.c | 4 +- drivers/input/keyboard/maple_keyb.c | 37 +-- drivers/sh/maple/maple.c | 463 +++++++++++++++++----------------- 3 files changed, 259 insertions(+), 245 deletions(-) (limited to 'drivers') diff --git a/drivers/input/joystick/maplecontrol.c b/drivers/input/joystick/maplecontrol.c index e50047bfe93..77cfde571bd 100644 --- a/drivers/input/joystick/maplecontrol.c +++ b/drivers/input/joystick/maplecontrol.c @@ -3,7 +3,7 @@ * Based on drivers/usb/iforce.c * * Copyright Yaegashi Takeshi, 2001 - * Adrian McMenamin, 2008 + * Adrian McMenamin, 2008 - 2009 */ #include @@ -29,7 +29,7 @@ static void dc_pad_callback(struct mapleq *mq) struct maple_device *mapledev = mq->dev; struct dc_pad *pad = maple_get_drvdata(mapledev); struct input_dev *dev = pad->dev; - unsigned char *res = mq->recvbuf; + unsigned char *res = mq->recvbuf->buf; buttons = ~le16_to_cpup((__le16 *)(res + 8)); diff --git a/drivers/input/keyboard/maple_keyb.c b/drivers/input/keyboard/maple_keyb.c index 22f17a593be..5aa2361aef9 100644 --- a/drivers/input/keyboard/maple_keyb.c +++ b/drivers/input/keyboard/maple_keyb.c @@ -1,8 +1,8 @@ /* * SEGA Dreamcast keyboard driver * Based on drivers/usb/usbkbd.c - * Copyright YAEGASHI Takeshi, 2001 - * Porting to 2.6 Copyright Adrian McMenamin, 2007, 2008 + * Copyright (c) YAEGASHI Takeshi, 2001 + * Porting to 2.6 Copyright (c) Adrian McMenamin, 2007 - 2009 * * 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 @@ -33,7 +33,7 @@ static DEFINE_MUTEX(maple_keyb_mutex); #define NR_SCANCODES 256 -MODULE_AUTHOR("YAEGASHI Takeshi, Adrian McMenamin"); +MODULE_AUTHOR("Adrian McMenamin dev, "Unknown key (scancode %#x) released.", code); } @@ -127,7 +127,7 @@ static void dc_scan_kbd(struct dc_kbd *kbd) input_event(dev, EV_MSC, MSC_SCAN, code); input_report_key(dev, keycode, 1); } else - printk(KERN_DEBUG "maple_keyb: " + dev_dbg(&dev->dev, "Unknown key (scancode %#x) pressed.", code); } @@ -140,7 +140,7 @@ static void dc_kbd_callback(struct mapleq *mq) { struct maple_device *mapledev = mq->dev; struct dc_kbd *kbd = maple_get_drvdata(mapledev); - unsigned long *buf = mq->recvbuf; + unsigned long *buf = (unsigned long *)(mq->recvbuf->buf); /* * We should always get the lock because the only @@ -159,22 +159,27 @@ static void dc_kbd_callback(struct mapleq *mq) static int probe_maple_kbd(struct device *dev) { - struct maple_device *mdev = to_maple_dev(dev); - struct maple_driver *mdrv = to_maple_driver(dev->driver); + struct maple_device *mdev; + struct maple_driver *mdrv; int i, error; struct dc_kbd *kbd; struct input_dev *idev; - if (!(mdev->function & MAPLE_FUNC_KEYBOARD)) - return -EINVAL; + mdev = to_maple_dev(dev); + mdrv = to_maple_driver(dev->driver); kbd = kzalloc(sizeof(struct dc_kbd), GFP_KERNEL); - idev = input_allocate_device(); - if (!kbd || !idev) { + if (!kbd) { error = -ENOMEM; goto fail; } + idev = input_allocate_device(); + if (!idev) { + error = -ENOMEM; + goto fail_idev_alloc; + } + kbd->dev = idev; memcpy(kbd->keycode, dc_kbd_keycode, sizeof(kbd->keycode)); @@ -195,7 +200,7 @@ static int probe_maple_kbd(struct device *dev) error = input_register_device(idev); if (error) - goto fail; + goto fail_register; /* Maple polling is locked to VBLANK - which may be just 50/s */ maple_getcond_callback(mdev, dc_kbd_callback, HZ/50, @@ -207,10 +212,12 @@ static int probe_maple_kbd(struct device *dev) return error; -fail: +fail_register: + maple_set_drvdata(mdev, NULL); input_free_device(idev); +fail_idev_alloc: kfree(kbd); - maple_set_drvdata(mdev, NULL); +fail: return error; } diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index 63f0de29aa1..4054fe93d6e 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -1,16 +1,10 @@ /* * Core maple bus functionality * - * Copyright (C) 2007, 2008 Adrian McMenamin + * Copyright (C) 2007 - 2009 Adrian McMenamin * Copyright (C) 2001 - 2008 Paul Mundt - * - * Based on 2.4 code by: - * - * Copyright (C) 2000-2001 YAEGASHI Takeshi + * Copyright (C) 2000 - 2001 YAEGASHI Takeshi * Copyright (C) 2001 M. R. Brown - * Copyright (C) 2001 Paul Mundt - * - * and others. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive @@ -32,7 +26,7 @@ #include #include -MODULE_AUTHOR("Yaegashi Takeshi, Paul Mundt, M. R. Brown, Adrian McMenamin"); +MODULE_AUTHOR("Adrian McMenamin "); MODULE_DESCRIPTION("Maple bus driver for Dreamcast"); MODULE_LICENSE("GPL v2"); MODULE_SUPPORTED_DEVICE("{{SEGA, Dreamcast/Maple}}"); @@ -49,7 +43,7 @@ static LIST_HEAD(maple_sentq); /* mutex to protect queue of waiting packets */ static DEFINE_MUTEX(maple_wlist_lock); -static struct maple_driver maple_dummy_driver; +static struct maple_driver maple_unsupported_device; static struct device maple_bus; static int subdevice_map[MAPLE_PORTS]; static unsigned long *maple_sendbuf, *maple_sendptr, *maple_lastptr; @@ -62,8 +56,9 @@ struct maple_device_specify { int unit; }; -static bool checked[4]; -static struct maple_device *baseunits[4]; +static bool checked[MAPLE_PORTS]; +static bool empty[MAPLE_PORTS]; +static struct maple_device *baseunits[MAPLE_PORTS]; /** * maple_driver_register - register a maple driver @@ -97,12 +92,20 @@ void maple_driver_unregister(struct maple_driver *drv) EXPORT_SYMBOL_GPL(maple_driver_unregister); /* set hardware registers to enable next round of dma */ -static void maplebus_dma_reset(void) +static void maple_dma_reset(void) { ctrl_outl(MAPLE_MAGIC, MAPLE_RESET); /* set trig type to 0 for software trigger, 1 for hardware (VBLANK) */ ctrl_outl(1, MAPLE_TRIGTYPE); - ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(50000), MAPLE_SPEED); + /* + * Maple system register + * bits 31 - 16 timeout in units of 20nsec + * bit 12 hard trigger - set 0 to keep responding to VBLANK + * bits 9 - 8 set 00 for 2 Mbps, 01 for 1 Mbps + * bits 3 - 0 delay (in 1.3ms) between VBLANK and start of DMA + * max delay is 11 + */ + ctrl_outl(MAPLE_2MBPS | MAPLE_TIMEOUT(0xFFFF), MAPLE_SPEED); ctrl_outl(PHYSADDR(maple_sendbuf), MAPLE_DMAADDR); ctrl_outl(1, MAPLE_ENABLE); } @@ -134,21 +137,16 @@ static void maple_release_device(struct device *dev) { struct maple_device *mdev; struct mapleq *mq; - if (!dev) - return; + mdev = to_maple_dev(dev); mq = mdev->mq; - if (mq) { - if (mq->recvbufdcsp) - kmem_cache_free(maple_queue_cache, mq->recvbufdcsp); - kfree(mq); - mq = NULL; - } + kmem_cache_free(maple_queue_cache, mq->recvbuf); + kfree(mq); kfree(mdev); } /** - * maple_add_packet - add a single instruction to the queue + * maple_add_packet - add a single instruction to the maple bus queue * @mdev: maple device * @function: function on device being queried * @command: maple command to add @@ -158,68 +156,12 @@ static void maple_release_device(struct device *dev) int maple_add_packet(struct maple_device *mdev, u32 function, u32 command, size_t length, void *data) { - int locking, ret = 0; + int ret = 0; void *sendbuf = NULL; - mutex_lock(&maple_wlist_lock); - /* bounce if device already locked */ - locking = mutex_is_locked(&mdev->mq->mutex); - if (locking) { - ret = -EBUSY; - goto out; - } - - mutex_lock(&mdev->mq->mutex); - if (length) { - sendbuf = kmalloc(length * 4, GFP_KERNEL); + sendbuf = kzalloc(length * 4, GFP_KERNEL); if (!sendbuf) { - mutex_unlock(&mdev->mq->mutex); - ret = -ENOMEM; - goto out; - } - ((__be32 *)sendbuf)[0] = cpu_to_be32(function); - } - - mdev->mq->command = command; - mdev->mq->length = length; - if (length > 1) - memcpy(sendbuf + 4, data, (length - 1) * 4); - mdev->mq->sendbuf = sendbuf; - - list_add(&mdev->mq->list, &maple_waitq); -out: - mutex_unlock(&maple_wlist_lock); - return ret; -} -EXPORT_SYMBOL_GPL(maple_add_packet); - -/** - * maple_add_packet_sleeps - add a single instruction to the queue - * @mdev: maple device - * @function: function on device being queried - * @command: maple command to add - * @length: length of command string (in 32 bit words) - * @data: remainder of command string - * - * Same as maple_add_packet(), but waits for the lock to become free. - */ -int maple_add_packet_sleeps(struct maple_device *mdev, u32 function, - u32 command, size_t length, void *data) -{ - int locking, ret = 0; - void *sendbuf = NULL; - - locking = mutex_lock_interruptible(&mdev->mq->mutex); - if (locking) { - ret = -EIO; - goto out; - } - - if (length) { - sendbuf = kmalloc(length * 4, GFP_KERNEL); - if (!sendbuf) { - mutex_unlock(&mdev->mq->mutex); ret = -ENOMEM; goto out; } @@ -233,38 +175,35 @@ int maple_add_packet_sleeps(struct maple_device *mdev, u32 function, mdev->mq->sendbuf = sendbuf; mutex_lock(&maple_wlist_lock); - list_add(&mdev->mq->list, &maple_waitq); + list_add_tail(&mdev->mq->list, &maple_waitq); mutex_unlock(&maple_wlist_lock); out: return ret; } -EXPORT_SYMBOL_GPL(maple_add_packet_sleeps); +EXPORT_SYMBOL_GPL(maple_add_packet); static struct mapleq *maple_allocq(struct maple_device *mdev) { struct mapleq *mq; - mq = kmalloc(sizeof(*mq), GFP_KERNEL); + mq = kzalloc(sizeof(*mq), GFP_KERNEL); if (!mq) goto failed_nomem; + INIT_LIST_HEAD(&mq->list); mq->dev = mdev; - mq->recvbufdcsp = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); - mq->recvbuf = (void *) P2SEGADDR(mq->recvbufdcsp); + mq->recvbuf = kmem_cache_zalloc(maple_queue_cache, GFP_KERNEL); if (!mq->recvbuf) goto failed_p2; - /* - * most devices do not need the mutex - but - * anything that injects block reads or writes - * will rely on it - */ - mutex_init(&mq->mutex); + mq->recvbuf->buf = &((mq->recvbuf->bufx)[0]); return mq; failed_p2: kfree(mq); failed_nomem: + dev_err(&mdev->dev, "could not allocate memory for device (%d, %d)\n", + mdev->port, mdev->unit); return NULL; } @@ -272,12 +211,16 @@ static struct maple_device *maple_alloc_dev(int port, int unit) { struct maple_device *mdev; + /* zero this out to avoid kobj subsystem + * thinking it has already been registered */ + mdev = kzalloc(sizeof(*mdev), GFP_KERNEL); if (!mdev) return NULL; mdev->port = port; mdev->unit = unit; + mdev->mq = maple_allocq(mdev); if (!mdev->mq) { @@ -286,19 +229,14 @@ static struct maple_device *maple_alloc_dev(int port, int unit) } mdev->dev.bus = &maple_bus_type; mdev->dev.parent = &maple_bus; + init_waitqueue_head(&mdev->maple_wait); return mdev; } static void maple_free_dev(struct maple_device *mdev) { - if (!mdev) - return; - if (mdev->mq) { - if (mdev->mq->recvbufdcsp) - kmem_cache_free(maple_queue_cache, - mdev->mq->recvbufdcsp); - kfree(mdev->mq); - } + kmem_cache_free(maple_queue_cache, mdev->mq->recvbuf); + kfree(mdev->mq); kfree(mdev); } @@ -320,7 +258,7 @@ static void maple_build_block(struct mapleq *mq) maple_lastptr = maple_sendptr; *maple_sendptr++ = (port << 16) | len | 0x80000000; - *maple_sendptr++ = PHYSADDR(mq->recvbuf); + *maple_sendptr++ = PHYSADDR(mq->recvbuf->buf); *maple_sendptr++ = mq->command | (to << 8) | (from << 16) | (len << 24); while (len-- > 0) @@ -333,20 +271,28 @@ static void maple_send(void) int i, maple_packets = 0; struct mapleq *mq, *nmq; - if (!list_empty(&maple_sentq)) + if (!maple_dma_done()) return; + + /* disable DMA */ + ctrl_outl(0, MAPLE_ENABLE); + + if (!list_empty(&maple_sentq)) + goto finish; + mutex_lock(&maple_wlist_lock); - if (list_empty(&maple_waitq) || !maple_dma_done()) { + if (list_empty(&maple_waitq)) { mutex_unlock(&maple_wlist_lock); - return; + goto finish; } - mutex_unlock(&maple_wlist_lock); + maple_lastptr = maple_sendbuf; maple_sendptr = maple_sendbuf; - mutex_lock(&maple_wlist_lock); + list_for_each_entry_safe(mq, nmq, &maple_waitq, list) { maple_build_block(mq); - list_move(&mq->list, &maple_sentq); + list_del_init(&mq->list); + list_add_tail(&mq->list, &maple_sentq); if (maple_packets++ > MAPLE_MAXPACKETS) break; } @@ -356,10 +302,13 @@ static void maple_send(void) dma_cache_sync(0, maple_sendbuf + i * PAGE_SIZE, PAGE_SIZE, DMA_BIDIRECTIONAL); } + +finish: + maple_dma_reset(); } /* check if there is a driver registered likely to match this device */ -static int check_matching_maple_driver(struct device_driver *driver, +static int maple_check_matching_driver(struct device_driver *driver, void *devptr) { struct maple_driver *maple_drv; @@ -374,10 +323,7 @@ static int check_matching_maple_driver(struct device_driver *driver, static void maple_detach_driver(struct maple_device *mdev) { - if (!mdev) - return; device_unregister(&mdev->dev); - mdev = NULL; } /* process initial MAPLE_COMMAND_DEVINFO for each device or port */ @@ -385,9 +331,9 @@ static void maple_attach_driver(struct maple_device *mdev) { char *p, *recvbuf; unsigned long function; - int matched, retval; + int matched, error; - recvbuf = mdev->mq->recvbuf; + recvbuf = mdev->mq->recvbuf->buf; /* copy the data as individual elements in * case of memory optimisation */ memcpy(&mdev->devinfo.function, recvbuf + 4, 4); @@ -395,7 +341,6 @@ static void maple_attach_driver(struct maple_device *mdev) memcpy(&mdev->devinfo.area_code, recvbuf + 20, 1); memcpy(&mdev->devinfo.connector_direction, recvbuf + 21, 1); memcpy(&mdev->devinfo.product_name[0], recvbuf + 22, 30); - memcpy(&mdev->devinfo.product_licence[0], recvbuf + 52, 60); memcpy(&mdev->devinfo.standby_power, recvbuf + 112, 2); memcpy(&mdev->devinfo.max_power, recvbuf + 114, 2); memcpy(mdev->product_name, mdev->devinfo.product_name, 30); @@ -414,43 +359,41 @@ static void maple_attach_driver(struct maple_device *mdev) else break; - printk(KERN_INFO "Maple device detected: %s\n", - mdev->product_name); - printk(KERN_INFO "Maple device: %s\n", mdev->product_licence); - function = be32_to_cpu(mdev->devinfo.function); + dev_info(&mdev->dev, "detected %s: function 0x%lX: at (%d, %d)\n", + mdev->product_name, function, mdev->port, mdev->unit); + if (function > 0x200) { /* Do this silently - as not a real device */ function = 0; - mdev->driver = &maple_dummy_driver; + mdev->driver = &maple_unsupported_device; sprintf(mdev->dev.bus_id, "%d:0.port", mdev->port); + } else { - printk(KERN_INFO - "Maple bus at (%d, %d): Function 0x%lX\n", - mdev->port, mdev->unit, function); matched = bus_for_each_drv(&maple_bus_type, NULL, mdev, - check_matching_maple_driver); + maple_check_matching_driver); if (matched == 0) { /* Driver does not exist yet */ - printk(KERN_INFO - "No maple driver found.\n"); - mdev->driver = &maple_dummy_driver; + dev_info(&mdev->dev, "no driver found\n"); + mdev->driver = &maple_unsupported_device; } sprintf(mdev->dev.bus_id, "%d:0%d.%lX", mdev->port, mdev->unit, function); } + mdev->function = function; mdev->dev.release = &maple_release_device; - retval = device_register(&mdev->dev); - if (retval) { - printk(KERN_INFO - "Maple bus: Attempt to register device" - " (%x, %x) failed.\n", - mdev->port, mdev->unit); + + atomic_set(&mdev->busy, 0); + error = device_register(&mdev->dev); + if (error) { + dev_warn(&mdev->dev, "could not register device at" + " (%d, %d), with error 0x%X\n", mdev->unit, + mdev->port, error); maple_free_dev(mdev); mdev = NULL; return; @@ -462,7 +405,7 @@ static void maple_attach_driver(struct maple_device *mdev) * port and unit then return 1 - allows identification * of which devices need to be attached or detached */ -static int detach_maple_device(struct device *device, void *portptr) +static int check_maple_device(struct device *device, void *portptr) { struct maple_device_specify *ds; struct maple_device *mdev; @@ -477,21 +420,25 @@ static int detach_maple_device(struct device *device, void *portptr) static int setup_maple_commands(struct device *device, void *ignored) { int add; - struct maple_device *maple_dev = to_maple_dev(device); - - if ((maple_dev->interval > 0) - && time_after(jiffies, maple_dev->when)) { - /* bounce if we cannot lock */ - add = maple_add_packet(maple_dev, - be32_to_cpu(maple_dev->devinfo.function), + struct maple_device *mdev = to_maple_dev(device); + if (mdev->interval > 0 && atomic_read(&mdev->busy) == 0 && + time_after(jiffies, mdev->when)) { + /* bounce if we cannot add */ + add = maple_add_packet(mdev, + be32_to_cpu(mdev->devinfo.function), MAPLE_COMMAND_GETCOND, 1, NULL); if (!add) - maple_dev->when = jiffies + maple_dev->interval; + mdev->when = jiffies + mdev->interval; } else { if (time_after(jiffies, maple_pnp_time)) - /* This will also bounce */ - maple_add_packet(maple_dev, 0, - MAPLE_COMMAND_DEVINFO, 0, NULL); + /* Ensure we don't have block reads and devinfo + * calls interfering with one another - so flag the + * device as busy */ + if (atomic_read(&mdev->busy) == 0) { + atomic_set(&mdev->busy, 1); + maple_add_packet(mdev, 0, + MAPLE_COMMAND_DEVINFO, 0, NULL); + } } return 0; } @@ -499,29 +446,50 @@ static int setup_maple_commands(struct device *device, void *ignored) /* VBLANK bottom half - implemented via workqueue */ static void maple_vblank_handler(struct work_struct *work) { - if (!list_empty(&maple_sentq) || !maple_dma_done()) + int x, locking; + struct maple_device *mdev; + + if (!maple_dma_done()) return; ctrl_outl(0, MAPLE_ENABLE); + if (!list_empty(&maple_sentq)) + goto finish; + + /* + * Set up essential commands - to fetch data and + * check devices are still present + */ bus_for_each_dev(&maple_bus_type, NULL, NULL, - setup_maple_commands); + setup_maple_commands); + + if (time_after(jiffies, maple_pnp_time)) { + /* + * Scan the empty ports - bus is flakey and may have + * mis-reported emptyness + */ + for (x = 0; x < MAPLE_PORTS; x++) { + if (checked[x] && empty[x]) { + mdev = baseunits[x]; + if (!mdev) + break; + atomic_set(&mdev->busy, 1); + locking = maple_add_packet(mdev, 0, + MAPLE_COMMAND_DEVINFO, 0, NULL); + if (!locking) + break; + } + } - if (time_after(jiffies, maple_pnp_time)) maple_pnp_time = jiffies + MAPLE_PNP_INTERVAL; - - mutex_lock(&maple_wlist_lock); - if (!list_empty(&maple_waitq) && list_empty(&maple_sentq)) { - mutex_unlock(&maple_wlist_lock); - maple_send(); - } else { - mutex_unlock(&maple_wlist_lock); } - maplebus_dma_reset(); +finish: + maple_send(); } -/* handle devices added via hotplugs - placing them on queue for DEVINFO*/ +/* handle devices added via hotplugs - placing them on queue for DEVINFO */ static void maple_map_subunits(struct maple_device *mdev, int submask) { int retval, k, devcheck; @@ -533,7 +501,7 @@ static void maple_map_subunits(struct maple_device *mdev, int submask) ds.unit = k + 1; retval = bus_for_each_dev(&maple_bus_type, NULL, &ds, - detach_maple_device); + check_maple_device); if (retval) { submask = submask >> 1; continue; @@ -543,6 +511,7 @@ static void maple_map_subunits(struct maple_device *mdev, int submask) mdev_add = maple_alloc_dev(mdev->port, k + 1); if (!mdev_add) return; + atomic_set(&mdev_add->busy, 1); maple_add_packet(mdev_add, 0, MAPLE_COMMAND_DEVINFO, 0, NULL); /* mark that we are checking sub devices */ @@ -564,27 +533,45 @@ static void maple_clean_submap(struct maple_device *mdev) } /* handle empty port or hotplug removal */ -static void maple_response_none(struct maple_device *mdev, - struct mapleq *mq) -{ - if (mdev->unit != 0) { - list_del(&mq->list); - maple_clean_submap(mdev); - printk(KERN_INFO - "Maple bus device detaching at (%d, %d)\n", - mdev->port, mdev->unit); +static void maple_response_none(struct maple_device *mdev) +{ + maple_clean_submap(mdev); + + if (likely(mdev->unit != 0)) { + /* + * Block devices play up + * and give the impression they have + * been removed even when still in place or + * trip the mtd layer when they have + * really gone - this code traps that eventuality + * and ensures we aren't overloaded with useless + * error messages + */ + if (mdev->can_unload) { + if (!mdev->can_unload(mdev)) { + atomic_set(&mdev->busy, 2); + wake_up(&mdev->maple_wait); + return; + } + } + + dev_info(&mdev->dev, "detaching device at (%d, %d)\n", + mdev->port, mdev->unit); maple_detach_driver(mdev); return; - } - if (!started || !fullscan) { - if (checked[mdev->port] == false) { - checked[mdev->port] = true; - printk(KERN_INFO "No maple devices attached" - " to port %d\n", mdev->port); + } else { + if (!started || !fullscan) { + if (checked[mdev->port] == false) { + checked[mdev->port] = true; + empty[mdev->port] = true; + dev_info(&mdev->dev, "no devices" + " to port %d\n", mdev->port); + } + return; } - return; } - maple_clean_submap(mdev); + /* Some hardware devices generate false detach messages on unit 0 */ + atomic_set(&mdev->busy, 0); } /* preprocess hotplugs or scans */ @@ -599,8 +586,11 @@ static void maple_response_devinfo(struct maple_device *mdev, } else { if (mdev->unit != 0) maple_attach_driver(mdev); + if (mdev->unit == 0) { + empty[mdev->port] = false; + maple_attach_driver(mdev); + } } - return; } if (mdev->unit == 0) { submask = recvbuf[2] & 0x1F; @@ -611,6 +601,17 @@ static void maple_response_devinfo(struct maple_device *mdev, } } +static void maple_response_fileerr(struct maple_device *mdev, void *recvbuf) +{ + if (mdev->fileerr_handler) { + mdev->fileerr_handler(mdev, recvbuf); + return; + } else + dev_warn(&mdev->dev, "device at (%d, %d) reports" + "file error 0x%X\n", mdev->port, mdev->unit, + ((int *)recvbuf)[1]); +} + static void maple_port_rescan(void) { int i; @@ -621,12 +622,6 @@ static void maple_port_rescan(void) if (checked[i] == false) { fullscan = 0; mdev = baseunits[i]; - /* - * test lock in case scan has failed - * but device is still locked - */ - if (mutex_is_locked(&mdev->mq->mutex)) - mutex_unlock(&mdev->mq->mutex); maple_add_packet(mdev, 0, MAPLE_COMMAND_DEVINFO, 0, NULL); } @@ -637,7 +632,7 @@ static void maple_port_rescan(void) static void maple_dma_handler(struct work_struct *work) { struct mapleq *mq, *nmq; - struct maple_device *dev; + struct maple_device *mdev; char *recvbuf; enum maple_code code; @@ -646,43 +641,56 @@ static void maple_dma_handler(struct work_struct *work) ctrl_outl(0, MAPLE_ENABLE); if (!list_empty(&maple_sentq)) { list_for_each_entry_safe(mq, nmq, &maple_sentq, list) { - recvbuf = mq->recvbuf; + mdev = mq->dev; + recvbuf = mq->recvbuf->buf; + dma_cache_sync(&mdev->dev, recvbuf, 0x400, + DMA_FROM_DEVICE); code = recvbuf[0]; - dev = mq->dev; kfree(mq->sendbuf); - mutex_unlock(&mq->mutex); list_del_init(&mq->list); - switch (code) { case MAPLE_RESPONSE_NONE: - maple_response_none(dev, mq); + maple_response_none(mdev); break; case MAPLE_RESPONSE_DEVINFO: - maple_response_devinfo(dev, recvbuf); + maple_response_devinfo(mdev, recvbuf); + atomic_set(&mdev->busy, 0); break; case MAPLE_RESPONSE_DATATRF: - if (dev->callback) - dev->callback(mq); + if (mdev->callback) + mdev->callback(mq); + atomic_set(&mdev->busy, 0); + wake_up(&mdev->maple_wait); break; case MAPLE_RESPONSE_FILEERR: + maple_response_fileerr(mdev, recvbuf); + atomic_set(&mdev->busy, 0); + wake_up(&mdev->maple_wait); + break; + case MAPLE_RESPONSE_AGAIN: case MAPLE_RESPONSE_BADCMD: case MAPLE_RESPONSE_BADFUNC: - printk(KERN_DEBUG - "Maple non-fatal error 0x%X\n", - code); + dev_warn(&mdev->dev, "non-fatal error" + " 0x%X at (%d, %d)\n", code, + mdev->port, mdev->unit); + atomic_set(&mdev->busy, 0); break; case MAPLE_RESPONSE_ALLINFO: - printk(KERN_DEBUG - "Maple - extended device information" - " not supported\n"); + dev_notice(&mdev->dev, "extended" + " device information request for (%d, %d)" + " but call is not supported\n", mdev->port, + mdev->unit); + atomic_set(&mdev->busy, 0); break; case MAPLE_RESPONSE_OK: + atomic_set(&mdev->busy, 0); + wake_up(&mdev->maple_wait); break; default: @@ -699,20 +707,19 @@ static void maple_dma_handler(struct work_struct *work) if (!fullscan) maple_port_rescan(); /* mark that we have been through the first scan */ - if (started == 0) - started = 1; + started = 1; } - maplebus_dma_reset(); + maple_send(); } -static irqreturn_t maplebus_dma_interrupt(int irq, void *dev_id) +static irqreturn_t maple_dma_interrupt(int irq, void *dev_id) { /* Load everything into the bottom half */ schedule_work(&maple_dma_process); return IRQ_HANDLED; } -static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id) +static irqreturn_t maple_vblank_interrupt(int irq, void *dev_id) { schedule_work(&maple_vblank_process); return IRQ_HANDLED; @@ -720,14 +727,14 @@ static irqreturn_t maplebus_vblank_interrupt(int irq, void *dev_id) static int maple_set_dma_interrupt_handler(void) { - return request_irq(HW_EVENT_MAPLE_DMA, maplebus_dma_interrupt, - IRQF_SHARED, "maple bus DMA", &maple_dummy_driver); + return request_irq(HW_EVENT_MAPLE_DMA, maple_dma_interrupt, + IRQF_SHARED, "maple bus DMA", &maple_unsupported_device); } static int maple_set_vblank_interrupt_handler(void) { - return request_irq(HW_EVENT_VSYNC, maplebus_vblank_interrupt, - IRQF_SHARED, "maple bus VBLANK", &maple_dummy_driver); + return request_irq(HW_EVENT_VSYNC, maple_vblank_interrupt, + IRQF_SHARED, "maple bus VBLANK", &maple_unsupported_device); } static int maple_get_dma_buffer(void) @@ -740,7 +747,7 @@ static int maple_get_dma_buffer(void) return 0; } -static int match_maple_bus_driver(struct device *devptr, +static int maple_match_bus_driver(struct device *devptr, struct device_driver *drvptr) { struct maple_driver *maple_drv = to_maple_driver(drvptr); @@ -765,16 +772,18 @@ static void maple_bus_release(struct device *dev) { } -static struct maple_driver maple_dummy_driver = { +static struct maple_driver maple_unsupported_device = { .drv = { - .name = "maple_dummy_driver", + .name = "maple_unsupported_device", .bus = &maple_bus_type, }, }; - +/** + * maple_bus_type - core maple bus structure + */ struct bus_type maple_bus_type = { .name = "maple", - .match = match_maple_bus_driver, + .match = maple_match_bus_driver, .uevent = maple_bus_uevent, }; EXPORT_SYMBOL_GPL(maple_bus_type); @@ -788,7 +797,8 @@ static int __init maple_bus_init(void) { int retval, i; struct maple_device *mdev[MAPLE_PORTS]; - ctrl_outl(0, MAPLE_STATE); + + ctrl_outl(0, MAPLE_ENABLE); retval = device_register(&maple_bus); if (retval) @@ -798,36 +808,33 @@ static int __init maple_bus_init(void) if (retval) goto cleanup_device; - retval = driver_register(&maple_dummy_driver.drv); + retval = driver_register(&maple_unsupported_device.drv); if (retval) goto cleanup_bus; /* allocate memory for maple bus dma */ retval = maple_get_dma_buffer(); if (retval) { - printk(KERN_INFO - "Maple bus: Failed to allocate Maple DMA buffers\n"); + dev_err(&maple_bus, "failed to allocate DMA buffers\n"); goto cleanup_basic; } /* set up DMA interrupt handler */ retval = maple_set_dma_interrupt_handler(); if (retval) { - printk(KERN_INFO - "Maple bus: Failed to grab maple DMA IRQ\n"); + dev_err(&maple_bus, "bus failed to grab maple " + "DMA IRQ\n"); goto cleanup_dma; } /* set up VBLANK interrupt handler */ retval = maple_set_vblank_interrupt_handler(); if (retval) { - printk(KERN_INFO "Maple bus: Failed to grab VBLANK IRQ\n"); + dev_err(&maple_bus, "bus failed to grab VBLANK IRQ\n"); goto cleanup_irq; } - maple_queue_cache = - kmem_cache_create("maple_queue_cache", 0x400, 0, - SLAB_HWCACHE_ALIGN, NULL); + maple_queue_cache = KMEM_CACHE(maple_buffer, SLAB_HWCACHE_ALIGN); if (!maple_queue_cache) goto cleanup_bothirqs; @@ -838,23 +845,23 @@ static int __init maple_bus_init(void) /* setup maple ports */ for (i = 0; i < MAPLE_PORTS; i++) { checked[i] = false; + empty[i] = false; mdev[i] = maple_alloc_dev(i, 0); - baseunits[i] = mdev[i]; if (!mdev[i]) { while (i-- > 0) maple_free_dev(mdev[i]); goto cleanup_cache; } + baseunits[i] = mdev[i]; + atomic_set(&mdev[i]->busy, 1); maple_add_packet(mdev[i], 0, MAPLE_COMMAND_DEVINFO, 0, NULL); subdevice_map[i] = 0; } - /* setup maplebus hardware */ - maplebus_dma_reset(); - /* initial detection */ + maple_pnp_time = jiffies + HZ; + /* prepare initial queue */ maple_send(); - maple_pnp_time = jiffies; - printk(KERN_INFO "Maple bus core now registered.\n"); + dev_info(&maple_bus, "bus core now registered\n"); return 0; @@ -871,7 +878,7 @@ cleanup_dma: free_pages((unsigned long) maple_sendbuf, MAPLE_DMA_PAGES); cleanup_basic: - driver_unregister(&maple_dummy_driver.drv); + driver_unregister(&maple_unsupported_device.drv); cleanup_bus: bus_unregister(&maple_bus_type); @@ -880,7 +887,7 @@ cleanup_device: device_unregister(&maple_bus); cleanup: - printk(KERN_INFO "Maple bus registration failed\n"); + printk(KERN_ERR "Maple bus registration failed\n"); return retval; } /* Push init to later to ensure hardware gets detected */ -- cgit v1.2.3 From 973e5d525d39be6f9f6c38d37aacf03efda02e60 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 24 Feb 2009 15:57:12 +0900 Subject: serial: sh-sci: console drainage Modify the serial console code to wait for the transmit FIFO, make sure all bits have been put on the wire before returning. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 557b54ab2f2..d3ccce0bfd4 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -139,7 +139,7 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c) } while (!(status & SCxSR_TDxE(port))); sci_in(port, SCxSR); /* Dummy read */ - sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); + sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); sci_out(port, SCxTDR, c); } #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */ @@ -1095,6 +1095,7 @@ static void serial_console_write(struct console *co, const char *s, unsigned count) { struct uart_port *port = &serial_console_port->port; + unsigned short bits; int i; for (i = 0; i < count; i++) { @@ -1103,6 +1104,11 @@ static void serial_console_write(struct console *co, const char *s, sci_poll_put_char(port, *s++); } + + /* wait until fifo is empty and last bit has been transmitted */ + bits = SCxSR_TDxE(port) | SCxSR_TEND(port); + while ((sci_in(port, SCxSR) & bits) != bits) + cpu_relax(); } static int __init serial_console_setup(struct console *co, char *options) -- cgit v1.2.3 From 5e084a1586a864d4e9b3f2edbb1bd3429909d652 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 24 Feb 2009 22:11:03 +0900 Subject: rtc: sh-rtc: Add Single IRQ Support Add support for single IRQ hardware to the sh-rtc driver. This is useful for processors with limited interrupt masking support such as sh7750 and sh7780. With this patch in place we can add logic to the intc code that merges all RTC vectors into a single linux interrupt with proper masking/unmasking support. Specify a single IRQ in the platform data to use this new shared IRQ feature. Separate Periodic/Carry/Alarm IRQs are still supported. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/rtc/rtc-sh.c | 190 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 117 insertions(+), 73 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 1c3fc6b428e..b37f44b0406 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -99,56 +99,51 @@ struct sh_rtc { unsigned short periodic_freq; }; -static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) +static int __sh_rtc_interrupt(struct sh_rtc *rtc) { - struct sh_rtc *rtc = dev_id; - unsigned int tmp; - - spin_lock(&rtc->lock); + unsigned int tmp, pending; tmp = readb(rtc->regbase + RCR1); + pending = tmp & RCR1_CF; tmp &= ~RCR1_CF; writeb(tmp, rtc->regbase + RCR1); /* Users have requested One x Second IRQ */ - if (rtc->periodic_freq & PF_OXS) + if (pending && rtc->periodic_freq & PF_OXS) rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF); - spin_unlock(&rtc->lock); - - return IRQ_HANDLED; + return pending; } -static irqreturn_t sh_rtc_alarm(int irq, void *dev_id) +static int __sh_rtc_alarm(struct sh_rtc *rtc) { - struct sh_rtc *rtc = dev_id; - unsigned int tmp; - - spin_lock(&rtc->lock); + unsigned int tmp, pending; tmp = readb(rtc->regbase + RCR1); + pending = tmp & RCR1_AF; tmp &= ~(RCR1_AF | RCR1_AIE); - writeb(tmp, rtc->regbase + RCR1); - - rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); + writeb(tmp, rtc->regbase + RCR1); - spin_unlock(&rtc->lock); + if (pending) + rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF); - return IRQ_HANDLED; + return pending; } -static irqreturn_t sh_rtc_periodic(int irq, void *dev_id) +static int __sh_rtc_periodic(struct sh_rtc *rtc) { - struct sh_rtc *rtc = dev_id; struct rtc_device *rtc_dev = rtc->rtc_dev; - unsigned int tmp; - - spin_lock(&rtc->lock); + struct rtc_task *irq_task; + unsigned int tmp, pending; tmp = readb(rtc->regbase + RCR2); + pending = tmp & RCR2_PEF; tmp &= ~RCR2_PEF; writeb(tmp, rtc->regbase + RCR2); + if (!pending) + return 0; + /* Half period enabled than one skipped and the next notified */ if ((rtc->periodic_freq & PF_HP) && (rtc->periodic_freq & PF_COUNT)) rtc->periodic_freq &= ~PF_COUNT; @@ -157,16 +152,65 @@ static irqreturn_t sh_rtc_periodic(int irq, void *dev_id) rtc->periodic_freq |= PF_COUNT; if (rtc->periodic_freq & PF_KOU) { spin_lock(&rtc_dev->irq_task_lock); - if (rtc_dev->irq_task) - rtc_dev->irq_task->func(rtc_dev->irq_task->private_data); + irq_task = rtc_dev->irq_task; + if (irq_task) + irq_task->func(irq_task->private_data); spin_unlock(&rtc_dev->irq_task_lock); } else rtc_update_irq(rtc->rtc_dev, 1, RTC_PF | RTC_IRQF); } + return pending; +} + +static irqreturn_t sh_rtc_interrupt(int irq, void *dev_id) +{ + struct sh_rtc *rtc = dev_id; + int ret; + + spin_lock(&rtc->lock); + ret = __sh_rtc_interrupt(rtc); + spin_unlock(&rtc->lock); + + return IRQ_RETVAL(ret); +} + +static irqreturn_t sh_rtc_alarm(int irq, void *dev_id) +{ + struct sh_rtc *rtc = dev_id; + int ret; + + spin_lock(&rtc->lock); + ret = __sh_rtc_alarm(rtc); + spin_unlock(&rtc->lock); + + return IRQ_RETVAL(ret); +} + +static irqreturn_t sh_rtc_periodic(int irq, void *dev_id) +{ + struct sh_rtc *rtc = dev_id; + int ret; + + spin_lock(&rtc->lock); + ret = __sh_rtc_periodic(rtc); spin_unlock(&rtc->lock); - return IRQ_HANDLED; + return IRQ_RETVAL(ret); +} + +static irqreturn_t sh_rtc_shared(int irq, void *dev_id) +{ + struct sh_rtc *rtc = dev_id; + int ret; + + spin_lock(&rtc->lock); + ret = __sh_rtc_interrupt(rtc); + ret |= __sh_rtc_alarm(rtc); + ret |= __sh_rtc_periodic(rtc); + spin_unlock(&rtc->lock); + + return IRQ_RETVAL(ret); } static inline void sh_rtc_setpie(struct device *dev, unsigned int enable) @@ -585,26 +629,12 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) ret = platform_get_irq(pdev, 0); if (unlikely(ret <= 0)) { ret = -ENOENT; - dev_err(&pdev->dev, "No IRQ for period\n"); + dev_err(&pdev->dev, "No IRQ resource\n"); goto err_badres; } rtc->periodic_irq = ret; - - ret = platform_get_irq(pdev, 1); - if (unlikely(ret <= 0)) { - ret = -ENOENT; - dev_err(&pdev->dev, "No IRQ for carry\n"); - goto err_badres; - } - rtc->carry_irq = ret; - - ret = platform_get_irq(pdev, 2); - if (unlikely(ret <= 0)) { - ret = -ENOENT; - dev_err(&pdev->dev, "No IRQ for alarm\n"); - goto err_badres; - } - rtc->alarm_irq = ret; + rtc->carry_irq = platform_get_irq(pdev, 1); + rtc->alarm_irq = platform_get_irq(pdev, 2); res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (unlikely(res == NULL)) { @@ -651,35 +681,47 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, rtc); - /* register periodic/carry/alarm irqs */ - ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, IRQF_DISABLED, - "sh-rtc period", rtc); - if (unlikely(ret)) { - dev_err(&pdev->dev, - "request period IRQ failed with %d, IRQ %d\n", ret, - rtc->periodic_irq); - goto err_unmap; - } + if (rtc->carry_irq <= 0) { + /* register shared periodic/carry/alarm irq */ + ret = request_irq(rtc->periodic_irq, sh_rtc_shared, + IRQF_DISABLED, "sh-rtc", rtc); + if (unlikely(ret)) { + dev_err(&pdev->dev, + "request IRQ failed with %d, IRQ %d\n", ret, + rtc->periodic_irq); + goto err_unmap; + } + } else { + /* register periodic/carry/alarm irqs */ + ret = request_irq(rtc->periodic_irq, sh_rtc_periodic, + IRQF_DISABLED, "sh-rtc period", rtc); + if (unlikely(ret)) { + dev_err(&pdev->dev, + "request period IRQ failed with %d, IRQ %d\n", + ret, rtc->periodic_irq); + goto err_unmap; + } - ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, IRQF_DISABLED, - "sh-rtc carry", rtc); - if (unlikely(ret)) { - dev_err(&pdev->dev, - "request carry IRQ failed with %d, IRQ %d\n", ret, - rtc->carry_irq); - free_irq(rtc->periodic_irq, rtc); - goto err_unmap; - } + ret = request_irq(rtc->carry_irq, sh_rtc_interrupt, + IRQF_DISABLED, "sh-rtc carry", rtc); + if (unlikely(ret)) { + dev_err(&pdev->dev, + "request carry IRQ failed with %d, IRQ %d\n", + ret, rtc->carry_irq); + free_irq(rtc->periodic_irq, rtc); + goto err_unmap; + } - ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, IRQF_DISABLED, - "sh-rtc alarm", rtc); - if (unlikely(ret)) { - dev_err(&pdev->dev, - "request alarm IRQ failed with %d, IRQ %d\n", ret, - rtc->alarm_irq); - free_irq(rtc->carry_irq, rtc); - free_irq(rtc->periodic_irq, rtc); - goto err_unmap; + ret = request_irq(rtc->alarm_irq, sh_rtc_alarm, + IRQF_DISABLED, "sh-rtc alarm", rtc); + if (unlikely(ret)) { + dev_err(&pdev->dev, + "request alarm IRQ failed with %d, IRQ %d\n", + ret, rtc->alarm_irq); + free_irq(rtc->carry_irq, rtc); + free_irq(rtc->periodic_irq, rtc); + goto err_unmap; + } } tmp = readb(rtc->regbase + RCR1); @@ -709,9 +751,11 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev) sh_rtc_setpie(&pdev->dev, 0); sh_rtc_setaie(&pdev->dev, 0); - free_irq(rtc->carry_irq, rtc); free_irq(rtc->periodic_irq, rtc); - free_irq(rtc->alarm_irq, rtc); + if (rtc->carry_irq > 0) { + free_irq(rtc->carry_irq, rtc); + free_irq(rtc->alarm_irq, rtc); + } release_resource(rtc->res); -- cgit v1.2.3 From bdaa6e8062d7f8085d8ed94ff88c99406ad53d79 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 24 Feb 2009 22:58:57 +0900 Subject: sh: multiple vectors per irq - base Instead of keeping the single vector -> single linux irq mapping we extend the intc code to support merging of vectors to a single linux irq. This helps processors such as sh7750, sh7780 and sh7785 which have more vectors than masking ability. With this patch in place we can modify the intc tables to use one irq per maskable irq source. Please note the following: - If multiple vectors share the same enum then only the first vector will be available as a linux irq. - Drivers may need to be rewritten to get pending irq source from the hardware block instead of irq number. This patch together with the sh7785 specific intc tables solves DMA controller irq issues related to buggy interrupt masking. Reported-by: Yoshihiro Shimoda Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/sh/intc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) (limited to 'drivers') diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 58d24c5a76c..d7b8959d9d9 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -568,6 +568,10 @@ static void __init intc_register_irq(struct intc_desc *desc, if (!data[0] && data[1]) primary = 1; + if (!data[0] && !data[1]) + pr_warning("intc: missing unique irq mask for 0x%04x\n", + irq2evt(irq)); + data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1); data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1); @@ -641,6 +645,17 @@ static unsigned int __init save_reg(struct intc_desc_int *d, return 0; } +static unsigned char *intc_evt2irq_table; + +unsigned int intc_evt2irq(unsigned int vector) +{ + unsigned int irq = evt2irq(vector); + + if (intc_evt2irq_table && intc_evt2irq_table[irq]) + irq = intc_evt2irq_table[irq]; + + return irq; +} void __init register_intc_controller(struct intc_desc *desc) { @@ -705,9 +720,41 @@ void __init register_intc_controller(struct intc_desc *desc) BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */ + /* keep the first vector only if same enum is used multiple times */ + for (i = 0; i < desc->nr_vectors; i++) { + struct intc_vect *vect = desc->vectors + i; + int first_irq = evt2irq(vect->vect); + + if (!vect->enum_id) + continue; + + for (k = i + 1; k < desc->nr_vectors; k++) { + struct intc_vect *vect2 = desc->vectors + k; + + if (vect->enum_id != vect2->enum_id) + continue; + + vect2->enum_id = 0; + + if (!intc_evt2irq_table) + intc_evt2irq_table = alloc_bootmem(NR_IRQS); + + if (!intc_evt2irq_table) { + pr_warning("intc: cannot allocate evt2irq!\n"); + continue; + } + + intc_evt2irq_table[evt2irq(vect2->vect)] = first_irq; + } + } + + /* register the vectors one by one */ for (i = 0; i < desc->nr_vectors; i++) { struct intc_vect *vect = desc->vectors + i; + if (!vect->enum_id) + continue; + intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect)); } } -- cgit v1.2.3 From 93fde774546c947ac8563da431f0a6d47452551d Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 3 Mar 2009 12:16:12 +0900 Subject: sh: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers Signed-off-by: Paul Mundt --- drivers/sh/maple/maple.c | 11 +++++------ drivers/sh/superhyway/superhyway.c | 4 ++-- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index 4054fe93d6e..c71bb4b4ce8 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -368,10 +368,8 @@ static void maple_attach_driver(struct maple_device *mdev) /* Do this silently - as not a real device */ function = 0; mdev->driver = &maple_unsupported_device; - sprintf(mdev->dev.bus_id, "%d:0.port", mdev->port); - + dev_set_name(&mdev->dev, "%d:0.port", mdev->port); } else { - matched = bus_for_each_drv(&maple_bus_type, NULL, mdev, maple_check_matching_driver); @@ -381,8 +379,9 @@ static void maple_attach_driver(struct maple_device *mdev) dev_info(&mdev->dev, "no driver found\n"); mdev->driver = &maple_unsupported_device; } - sprintf(mdev->dev.bus_id, "%d:0%d.%lX", mdev->port, - mdev->unit, function); + + dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port, + mdev->unit, function); } mdev->function = function; @@ -789,7 +788,7 @@ struct bus_type maple_bus_type = { EXPORT_SYMBOL_GPL(maple_bus_type); static struct device maple_bus = { - .bus_id = "maple", + .init_name = "maple", .release = maple_bus_release, }; diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 4d0282b821b..2d9e7f3d561 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -22,7 +22,7 @@ static int superhyway_devices; static struct device superhyway_bus_device = { - .bus_id = "superhyway", + .init_name = "superhyway", }; static void superhyway_device_release(struct device *dev) @@ -83,7 +83,7 @@ int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, dev->id.id = dev->vcr.mod_id; sprintf(dev->name, "SuperHyway device %04x", dev->id.id); - sprintf(dev->dev.bus_id, "%02x", superhyway_devices); + dev_set_name(&dev->dev, "%02x", superhyway_devices); superhyway_devices++; -- cgit v1.2.3 From 55ba99eb211a06709237cb322ecd8c8b6faf6159 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 3 Mar 2009 15:40:25 +0900 Subject: sh: Add support for SH7786 CPU subtype. This adds preliminary support for the SH7786 CPU subtype. While this is a dual-core CPU, only UP is supported for now. L2 cache support is likewise not yet implemented. More information on this particular CPU subtype is available at: http://www.renesas.com/fmwk.jsp?cnt=sh7786_root.jsp&fp=/products/mpumcu/superh_family/sh7780_series/sh7786_group/ Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- drivers/serial/sh-sci.c | 4 +++- drivers/serial/sh-sci.h | 13 +++++++++---- 2 files changed, 12 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index d3ccce0bfd4..dbf5357a77b 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c @@ -263,6 +263,7 @@ static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) #elif defined(CONFIG_CPU_SUBTYPE_SH7763) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ defined(CONFIG_CPU_SUBTYPE_SH7785) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786) || \ defined(CONFIG_CPU_SUBTYPE_SHX3) static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) { @@ -284,7 +285,8 @@ static inline void sci_init_pins(struct uart_port *port, unsigned int cflag) #if defined(CONFIG_CPU_SUBTYPE_SH7760) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ - defined(CONFIG_CPU_SUBTYPE_SH7785) + defined(CONFIG_CPU_SUBTYPE_SH7785) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786) static inline int scif_txroom(struct uart_port *port) { return SCIF_TXROOM_MAX - (sci_in(port, SCTFDR) & 0xff); diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index bb9fe122488..d0aa82d7fce 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h @@ -126,7 +126,8 @@ # define SCSPTR1 0xffe10024 /* 16 bit SCIF */ # define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCSCR_INIT(port) 0x3a /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ -#elif defined(CONFIG_CPU_SUBTYPE_SH7785) +#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786) # define SCSPTR0 0xffea0024 /* 16 bit SCIF */ # define SCSPTR1 0xffeb0024 /* 16 bit SCIF */ # define SCSPTR2 0xffec0024 /* 16 bit SCIF */ @@ -182,6 +183,7 @@ defined(CONFIG_CPU_SUBTYPE_SH7763) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ defined(CONFIG_CPU_SUBTYPE_SH7785) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786) || \ defined(CONFIG_CPU_SUBTYPE_SHX3) #define SCI_CTRL_FLAGS_REIE 0x08 /* 7750 SCIF */ #else @@ -413,7 +415,8 @@ SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8) SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16) #if defined(CONFIG_CPU_SUBTYPE_SH7760) || \ defined(CONFIG_CPU_SUBTYPE_SH7780) || \ - defined(CONFIG_CPU_SUBTYPE_SH7785) + defined(CONFIG_CPU_SUBTYPE_SH7785) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786) SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) @@ -644,7 +647,8 @@ static inline int sci_rxd_in(struct uart_port *port) return ctrl_inw(SCSPTR1) & 0x0001 ? 1 : 0; /* SCIF */ return 1; } -#elif defined(CONFIG_CPU_SUBTYPE_SH7785) +#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786) static inline int sci_rxd_in(struct uart_port *port) { if (port->mapbase == 0xffea0000) @@ -746,7 +750,8 @@ static inline int sci_rxd_in(struct uart_port *port) */ #if defined(CONFIG_CPU_SUBTYPE_SH7780) || \ - defined(CONFIG_CPU_SUBTYPE_SH7785) + defined(CONFIG_CPU_SUBTYPE_SH7785) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786) #define SCBRR_VALUE(bps, clk) ((clk+16*bps)/(16*bps)-1) #elif defined(CONFIG_CPU_SUBTYPE_SH7705) || \ defined(CONFIG_CPU_SUBTYPE_SH7720) || \ -- cgit v1.2.3 From 5fd3a17ed456637a224cf4ca82b9ad9d005bc8d4 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 4 Mar 2009 00:57:25 -0700 Subject: md: fix deadlock when stopping arrays Resolve a deadlock when stopping redundant arrays, i.e. ones that require a call to sysfs_remove_group when shutdown. The deadlock is summarized below: Thread1 Thread2 ------- ------- read sysfs attribute stop array take mddev lock sysfs_remove_group sysfs_get_active wait for mddev lock wait for active Sysrq-w: -------- mdmon S 00000017 2212 4163 1 f1982ea8 00000046 2dcf6b85 00000017 c0b23100 f2f83ed0 c0b23100 f2f8413c c0b23100 c0b23100 c0b1fb98 f2f8413c 00000000 f2f8413c c0b23100 f2291ecc 00000002 c0b23100 00000000 00000017 f2f83ed0 f1982eac 00000046 c044d9dd Call Trace: [] ? debug_mutex_add_waiter+0x1d/0x58 [] __mutex_lock_common+0x1d9/0x338 [] ? __mutex_lock_common+0x1d9/0x338 [] mutex_lock_interruptible_nested+0x33/0x3a [] ? mddev_lock+0x14/0x16 [] mddev_lock+0x14/0x16 [] md_attr_show+0x2a/0x49 [] sysfs_read_file+0x93/0xf9 mdadm D 00000017 2812 4177 1 f0401d78 00000046 430456f8 00000017 f0401d58 f0401d20 c0b23100 f2da2c4c c0b23100 c0b23100 c0b1fb98 f2da2c4c 0a10fc36 00000000 c0b23100 f0401d70 00000003 c0b23100 00000000 00000017 f2da29e0 00000001 00000002 00000000 Call Trace: [] schedule_timeout+0x1b/0x95 [] ? schedule_timeout+0x1b/0x95 [] ? wait_for_common+0x34/0xdc [] ? trace_hardirqs_on_caller+0x18/0x145 [] ? trace_hardirqs_on+0xb/0xd [] wait_for_common+0xa0/0xdc [] ? default_wake_function+0x0/0x12 [] wait_for_completion+0x17/0x19 [] sysfs_addrm_finish+0x19f/0x1d1 [] sysfs_hash_and_remove+0x42/0x55 [] sysfs_remove_group+0x57/0x86 [] do_md_stop+0x13a/0x499 This has been there for a while, but is easier to trigger now that mdmon is closely watching sysfs. Cc: Reported-by: Jacek Danecki Signed-off-by: Dan Williams --- drivers/md/md.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/md/md.c b/drivers/md/md.c index 03b4cd0a634..a307f87eb90 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -214,12 +214,7 @@ static inline mddev_t *mddev_get(mddev_t *mddev) return mddev; } -static void mddev_delayed_delete(struct work_struct *ws) -{ - mddev_t *mddev = container_of(ws, mddev_t, del_work); - kobject_del(&mddev->kobj); - kobject_put(&mddev->kobj); -} +static void mddev_delayed_delete(struct work_struct *ws); static void mddev_put(mddev_t *mddev) { @@ -3542,6 +3537,21 @@ static struct kobj_type md_ktype = { int mdp_major = 0; +static void mddev_delayed_delete(struct work_struct *ws) +{ + mddev_t *mddev = container_of(ws, mddev_t, del_work); + + if (mddev->private == &md_redundancy_group) { + sysfs_remove_group(&mddev->kobj, &md_redundancy_group); + if (mddev->sysfs_action) + sysfs_put(mddev->sysfs_action); + mddev->sysfs_action = NULL; + mddev->private = NULL; + } + kobject_del(&mddev->kobj); + kobject_put(&mddev->kobj); +} + static int md_alloc(dev_t dev, char *name) { static DEFINE_MUTEX(disks_mutex); @@ -4033,13 +4043,9 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open) mddev->queue->merge_bvec_fn = NULL; mddev->queue->unplug_fn = NULL; mddev->queue->backing_dev_info.congested_fn = NULL; - if (mddev->pers->sync_request) { - sysfs_remove_group(&mddev->kobj, &md_redundancy_group); - if (mddev->sysfs_action) - sysfs_put(mddev->sysfs_action); - mddev->sysfs_action = NULL; - } module_put(mddev->pers->owner); + if (mddev->pers->sync_request) + mddev->private = &md_redundancy_group; mddev->pers = NULL; /* tell userspace to handle 'inactive' */ sysfs_notify_dirent(mddev->sysfs_state); -- cgit v1.2.3 From c21986a76220919bb06e4c04a89a8a62aeac107e Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 4 Mar 2009 00:18:11 -0800 Subject: jsflash: stop defining MAJOR_NR Ever since early 2.5 kernels block drivers don't need to define MAJOR_NR anymore, so use the JSFD_MAJOR defined directly and kill it. Signed-off-by: Christoph Hellwig Signed-off-by: David S. Miller --- drivers/sbus/char/jsflash.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index a9a9893a5f9..e6d1fc8c54f 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c @@ -38,9 +38,6 @@ #include #include #include - -#define MAJOR_NR JSFD_MAJOR - #include #include #include -- cgit v1.2.3 From f4c13638185c91a269c63fcfb980d89180cf43a1 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 4 Mar 2009 00:19:28 -0800 Subject: sparc64: wait_event_interruptible_timeout may return -ERESTARTSYS wait_event_interruptible_timeout may return -ERESTARTSYS. Signed-off-by: Roel Kluin Signed-off-by: David S. Miller --- drivers/sbus/char/bbc_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index f08e169ba1b..7e30e5f6e03 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c @@ -129,7 +129,7 @@ static int wait_for_pin(struct bbc_i2c_bus *bp, u8 *status) bp->waiting = 1; add_wait_queue(&bp->wq, &wait); while (limit-- > 0) { - unsigned long val; + long val; val = wait_event_interruptible_timeout( bp->wq, -- cgit v1.2.3 From 49bc46360d68156ce82b2b1a12badb80078453a0 Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Thu, 26 Feb 2009 11:04:23 +0100 Subject: I/OAT: add verification for proper APICID_TAG_MAP setting by BIOS BIOS versions for systems with I/OAT ver.2 have been found which fail to program APICID_TAG_MAP for DCA. The ioatdma driver should recognize incorrectly set APICID_TAG_MAP and disable DCA in that case. Signed-off-by: Maciej Sosnowski Signed-off-by: Shannon Nelson Acked-by: Jeff Kirsher Signed-off-by: Dan Williams --- drivers/dma/ioat_dca.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c index 6cf622da028..78705ca7d36 100644 --- a/drivers/dma/ioat_dca.c +++ b/drivers/dma/ioat_dca.c @@ -49,6 +49,23 @@ #define DCA_TAG_MAP_MASK 0xDF +/* expected tag map bytes for I/OAT ver.2 */ +#define DCA2_TAG_MAP_BYTE0 0x80 +#define DCA2_TAG_MAP_BYTE1 0x0 +#define DCA2_TAG_MAP_BYTE2 0x81 +#define DCA2_TAG_MAP_BYTE3 0x82 +#define DCA2_TAG_MAP_BYTE4 0x82 + +/* verify if tag map matches expected values */ +static inline int dca2_tag_map_valid(u8 *tag_map) +{ + return ((tag_map[0] == DCA2_TAG_MAP_BYTE0) && + (tag_map[1] == DCA2_TAG_MAP_BYTE1) && + (tag_map[2] == DCA2_TAG_MAP_BYTE2) && + (tag_map[3] == DCA2_TAG_MAP_BYTE3) && + (tag_map[4] == DCA2_TAG_MAP_BYTE4)); +} + /* * "Legacy" DCA systems do not implement the DCA register set in the * I/OAT device. Software needs direct support for their tag mappings. @@ -452,6 +469,13 @@ struct dca_provider *ioat2_dca_init(struct pci_dev *pdev, void __iomem *iobase) ioatdca->tag_map[i] = 0; } + if (!dca2_tag_map_valid(ioatdca->tag_map)) { + dev_err(&pdev->dev, "APICID_TAG_MAP set incorrectly by BIOS, " + "disabling DCA\n"); + free_dca_provider(dca); + return NULL; + } + err = register_dca_provider(dca, &pdev->dev); if (err) { free_dca_provider(dca); -- cgit v1.2.3 From ea9c717d0148d4194f9bd04ecfa6b59b20fc0a08 Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Thu, 26 Feb 2009 11:04:38 +0100 Subject: I/OAT: do not set DCACTRL_CMPL_WRITE_ENABLE for I/OAT ver.3 Flag DCACTRL_CMPL_WRITE_ENABLE is valid only for I/OAT ver.2 so it should not be set for I/OAT ver.3. Signed-off-by: Maciej Sosnowski Signed-off-by: Shannon Nelson Acked-by: Jeff Kirsher Signed-off-by: Dan Williams --- drivers/dma/ioat_dma.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index b3759c4b653..879f4a06e3c 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -189,11 +189,13 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) ioat_chan->xfercap = xfercap; ioat_chan->desccount = 0; INIT_DELAYED_WORK(&ioat_chan->work, ioat_dma_chan_reset_part2); - if (ioat_chan->device->version != IOAT_VER_1_2) { - writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE - | IOAT_DMA_DCA_ANY_CPU, - ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); - } + if (ioat_chan->device->version == IOAT_VER_2_0) + writel(IOAT_DCACTRL_CMPL_WRITE_ENABLE | + IOAT_DMA_DCA_ANY_CPU, + ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); + else if (ioat_chan->device->version == IOAT_VER_3_0) + writel(IOAT_DMA_DCA_ANY_CPU, + ioat_chan->reg_base + IOAT_DCACTRL_OFFSET); spin_lock_init(&ioat_chan->cleanup_lock); spin_lock_init(&ioat_chan->desc_lock); INIT_LIST_HEAD(&ioat_chan->free_desc); -- cgit v1.2.3 From 8b794b141c633083408d0bfb2229b3406d0ebf99 Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Thu, 26 Feb 2009 11:04:54 +0100 Subject: I/OAT: fail initialization on zero channels detection On some systems with I/OAT ver.2 when DCA is disabled in BIOS situations have been observed that zero DMA channels are detected instead of four. To avoid kernel panic driver should fail gracefully with appropriate message. Signed-off-by: Maciej Sosnowski Signed-off-by: Shannon Nelson Acked-by: Jeff Kirsher Signed-off-by: Dan Williams --- drivers/dma/ioat_dma.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index 879f4a06e3c..9012da7908f 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -1659,6 +1659,13 @@ struct ioatdma_device *ioat_dma_probe(struct pci_dev *pdev, " %d channels, device version 0x%02x, driver version %s\n", device->common.chancnt, device->version, IOAT_DMA_VERSION); + if (!device->common.chancnt) { + dev_err(&device->pdev->dev, + "Intel(R) I/OAT DMA Engine problem found: " + "zero channels detected\n"); + goto err_setup_interrupts; + } + err = ioat_dma_setup_interrupts(device); if (err) goto err_setup_interrupts; -- cgit v1.2.3 From 2b8a6bf896ef47cc7d84c503079cc7b99789f9fa Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Thu, 26 Feb 2009 11:05:07 +0100 Subject: I/OAT: cancel watchdog before dma remove Channel watchdog should be canceled before the rest of dma remove stuff. Signed-off-by: Maciej Sosnowski Signed-off-by: Shannon Nelson Acked-by: Jeff Kirsher Signed-off-by: Dan Williams --- drivers/dma/ioat_dma.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index 9012da7908f..fc9b845ee89 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -1705,6 +1705,9 @@ void ioat_dma_remove(struct ioatdma_device *device) struct dma_chan *chan, *_chan; struct ioat_dma_chan *ioat_chan; + if (device->version != IOAT_VER_3_0) + cancel_delayed_work(&device->work); + ioat_dma_remove_interrupts(device); dma_async_device_unregister(&device->common); @@ -1716,10 +1719,6 @@ void ioat_dma_remove(struct ioatdma_device *device) pci_release_regions(device->pdev); pci_disable_device(device->pdev); - if (device->version != IOAT_VER_3_0) { - cancel_delayed_work(&device->work); - } - list_for_each_entry_safe(chan, _chan, &device->common.channels, device_node) { ioat_chan = to_ioat_chan(chan); -- cgit v1.2.3 From 5de22343b2303b278ab562e5d166ffe306566d30 Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Thu, 26 Feb 2009 11:05:17 +0100 Subject: I/OAT: set tcp_dma_copybreak to 256k for I/OAT ver.3 Upcoming server platforms from Intel based on the Nehalem performance have significantly improved CPU based copy performance. However, the DMA engine can still be effective at higher I/O sizes for TCP traffic and at this time copybreak should be set to 256k for TCP traffic only. Signed-off-by: Maciej Sosnowski Signed-off-by: Shannon Nelson Acked-by: Jeff Kirsher Signed-off-by: Dan Williams --- drivers/dma/ioatdma.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h index a3306d0e137..dcf8db513c3 100644 --- a/drivers/dma/ioatdma.h +++ b/drivers/dma/ioatdma.h @@ -135,12 +135,14 @@ static inline void ioat_set_tcp_copy_break(struct ioatdma_device *dev) #ifdef CONFIG_NET_DMA switch (dev->version) { case IOAT_VER_1_2: - case IOAT_VER_3_0: sysctl_tcp_dma_copybreak = 4096; break; case IOAT_VER_2_0: sysctl_tcp_dma_copybreak = 2048; break; + case IOAT_VER_3_0: + sysctl_tcp_dma_copybreak = 262144; + break; } #endif } -- cgit v1.2.3 From aa2d0b8b97efa1033609ca89b9faa5d3a1232959 Mon Sep 17 00:00:00 2001 From: Eric Sesterhenn Date: Thu, 26 Feb 2009 11:05:30 +0100 Subject: I/OAT: list usage cleanup Trivial cleanup, list_del(); list_add_tail() is equivalent to list_move_tail(). Semantic patch for coccinelle can be found at www.cccmz.de/~snakebyte/list_move_tail.spatch Signed-off-by: Eric Sesterhenn Signed-off-by: Maciej Sosnowski Signed-off-by: Shannon Nelson Acked-by: Jeff Kirsher Signed-off-by: Dan Williams --- drivers/dma/ioat_dma.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index fc9b845ee89..ae8c0ce3b86 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -1171,9 +1171,8 @@ static void ioat_dma_memcpy_cleanup(struct ioat_dma_chan *ioat_chan) * up if the client is done with the descriptor */ if (async_tx_test_ack(&desc->async_tx)) { - list_del(&desc->node); - list_add_tail(&desc->node, - &ioat_chan->free_desc); + list_move_tail(&desc->node, + &ioat_chan->free_desc); } else desc->async_tx.cookie = 0; } else { -- cgit v1.2.3 From 211a22ce08dbb27eb1a66df8a4bdae5e96092bc8 Mon Sep 17 00:00:00 2001 From: Maciej Sosnowski Date: Thu, 26 Feb 2009 11:05:43 +0100 Subject: I/OAT: update driver version and copyright dates Together with new fixes update driver version and extend copyright dates ranges. Signed-off-by: Maciej Sosnowski Signed-off-by: Shannon Nelson Acked-by: Jeff Kirsher Signed-off-by: Dan Williams --- drivers/dca/dca-core.c | 2 +- drivers/dma/ioat.c | 2 +- drivers/dma/ioat_dca.c | 2 +- drivers/dma/ioat_dma.c | 2 +- drivers/dma/ioatdma.h | 4 ++-- drivers/dma/ioatdma_hw.h | 2 +- drivers/dma/ioatdma_registers.h | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/dca/dca-core.c b/drivers/dca/dca-core.c index 33bd7534751..25b743abfb5 100644 --- a/drivers/dca/dca-core.c +++ b/drivers/dca/dca-core.c @@ -1,5 +1,5 @@ /* - * Copyright(c) 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. * * 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 diff --git a/drivers/dma/ioat.c b/drivers/dma/ioat.c index 4105d6575b6..ed83dd9df19 100644 --- a/drivers/dma/ioat.c +++ b/drivers/dma/ioat.c @@ -1,6 +1,6 @@ /* * Intel I/OAT DMA Linux driver - * Copyright(c) 2007 Intel Corporation. + * Copyright(c) 2007 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/dma/ioat_dca.c b/drivers/dma/ioat_dca.c index 78705ca7d36..c012a1e1504 100644 --- a/drivers/dma/ioat_dca.c +++ b/drivers/dma/ioat_dca.c @@ -1,6 +1,6 @@ /* * Intel I/OAT DMA Linux driver - * Copyright(c) 2007 Intel Corporation. + * Copyright(c) 2007 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index ae8c0ce3b86..068b6351452 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -1,6 +1,6 @@ /* * Intel I/OAT DMA Linux driver - * Copyright(c) 2004 - 2007 Intel Corporation. + * Copyright(c) 2004 - 2009 Intel Corporation. * * This program is free software; you can redistribute it and/or modify it * under the terms and conditions of the GNU General Public License, diff --git a/drivers/dma/ioatdma.h b/drivers/dma/ioatdma.h index dcf8db513c3..a52ff4bd460 100644 --- a/drivers/dma/ioatdma.h +++ b/drivers/dma/ioatdma.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved. * * 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 @@ -29,7 +29,7 @@ #include #include -#define IOAT_DMA_VERSION "3.30" +#define IOAT_DMA_VERSION "3.64" enum ioat_interrupt { none = 0, diff --git a/drivers/dma/ioatdma_hw.h b/drivers/dma/ioatdma_hw.h index f1ae2c776f7..afa57eef86c 100644 --- a/drivers/dma/ioatdma_hw.h +++ b/drivers/dma/ioatdma_hw.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved. * * 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 diff --git a/drivers/dma/ioatdma_registers.h b/drivers/dma/ioatdma_registers.h index 827cb503cac..49bc277424f 100644 --- a/drivers/dma/ioatdma_registers.h +++ b/drivers/dma/ioatdma_registers.h @@ -1,5 +1,5 @@ /* - * Copyright(c) 2004 - 2007 Intel Corporation. All rights reserved. + * Copyright(c) 2004 - 2009 Intel Corporation. All rights reserved. * * 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 -- cgit v1.2.3 From 0c33e1ca3d80647f2e72e44524fd21e79214da20 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 2 Mar 2009 13:31:35 -0700 Subject: I/OAT: fail self-test if callback test reaches timeout If we miss interrupts in the self test then fail registration of this channel as it is unsuitable for use as a public channel. Signed-off-by: Maciej Sosnowski Signed-off-by: Dan Williams --- drivers/dma/ioat_dma.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index 068b6351452..5905cd36bcd 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c @@ -1363,6 +1363,7 @@ static int ioat_dma_self_test(struct ioatdma_device *device) dma_cookie_t cookie; int err = 0; struct completion cmp; + unsigned long tmo; src = kzalloc(sizeof(u8) * IOAT_TEST_SIZE, GFP_KERNEL); if (!src) @@ -1414,9 +1415,10 @@ static int ioat_dma_self_test(struct ioatdma_device *device) } device->common.device_issue_pending(dma_chan); - wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)); + tmo = wait_for_completion_timeout(&cmp, msecs_to_jiffies(3000)); - if (device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) + if (tmo == 0 || + device->common.device_is_tx_complete(dma_chan, cookie, NULL, NULL) != DMA_SUCCESS) { dev_err(&device->pdev->dev, "Self-test copy timed out, disabling\n"); -- cgit v1.2.3 From 900325a6ce33995688b7a680a34e7698f16f4d72 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 2 Mar 2009 15:33:46 -0700 Subject: fsldma: fix off by one in dma_halt Prevent dev_err from firing even if we successfully detected 'dma-idle' before the full 1ms timeout has elapsed. Acked-by: Roel Kluin Signed-off-by: Dan Williams --- drivers/dma/fsldma.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 70126a60623..86d6da47f55 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -158,7 +158,8 @@ static void dma_start(struct fsl_dma_chan *fsl_chan) static void dma_halt(struct fsl_dma_chan *fsl_chan) { - int i = 0; + int i; + DMA_OUT(fsl_chan, &fsl_chan->reg_base->mr, DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) | FSL_DMA_MR_CA, 32); @@ -166,8 +167,11 @@ static void dma_halt(struct fsl_dma_chan *fsl_chan) DMA_IN(fsl_chan, &fsl_chan->reg_base->mr, 32) & ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA), 32); - while (!dma_is_idle(fsl_chan) && (i++ < 100)) + for (i = 0; i < 100; i++) { + if (dma_is_idle(fsl_chan)) + break; udelay(10); + } if (i >= 100 && !dma_is_idle(fsl_chan)) dev_err(fsl_chan->dev, "DMA halt timeout!\n"); } -- cgit v1.2.3 From a09b09ae51ace43d28cd9bc1c8bb97986f2b55a6 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 25 Feb 2009 13:56:21 +0100 Subject: iop-adma, mv_xor: fix mem leak on self-test setup failure iop_adma_zero_sum_self_test has the brackets in the wrong place for the setup failure deallocation path. This error was duplicated in mv_xor_xor_self_test. Signed-off-by: Roel Kluin Signed-off-by: Dan Williams --- drivers/dma/iop-adma.c | 16 ++++++++-------- drivers/dma/mv_xor.c | 16 ++++++++-------- 2 files changed, 16 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/iop-adma.c b/drivers/dma/iop-adma.c index ea5440dd10d..4131ab8e503 100644 --- a/drivers/dma/iop-adma.c +++ b/drivers/dma/iop-adma.c @@ -928,19 +928,19 @@ iop_adma_xor_zero_sum_self_test(struct iop_adma_device *device) for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) { xor_srcs[src_idx] = alloc_page(GFP_KERNEL); - if (!xor_srcs[src_idx]) - while (src_idx--) { + if (!xor_srcs[src_idx]) { + while (src_idx--) __free_page(xor_srcs[src_idx]); - return -ENOMEM; - } + return -ENOMEM; + } } dest = alloc_page(GFP_KERNEL); - if (!dest) - while (src_idx--) { + if (!dest) { + while (src_idx--) __free_page(xor_srcs[src_idx]); - return -ENOMEM; - } + return -ENOMEM; + } /* Fill in src buffers */ for (src_idx = 0; src_idx < IOP_ADMA_NUM_SRC_TEST; src_idx++) { diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index d35cbd1ff0b..2a4e3e30a04 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -1019,19 +1019,19 @@ mv_xor_xor_self_test(struct mv_xor_device *device) for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) { xor_srcs[src_idx] = alloc_page(GFP_KERNEL); - if (!xor_srcs[src_idx]) - while (src_idx--) { + if (!xor_srcs[src_idx]) { + while (src_idx--) __free_page(xor_srcs[src_idx]); - return -ENOMEM; - } + return -ENOMEM; + } } dest = alloc_page(GFP_KERNEL); - if (!dest) - while (src_idx--) { + if (!dest) { + while (src_idx--) __free_page(xor_srcs[src_idx]); - return -ENOMEM; - } + return -ENOMEM; + } /* Fill in src buffers */ for (src_idx = 0; src_idx < MV_XOR_NUM_SRC_TEST; src_idx++) { -- cgit v1.2.3 From c74ef1f867d18171c8617519ee5fe40b02903934 Mon Sep 17 00:00:00 2001 From: Luotao Fu Date: Thu, 26 Feb 2009 12:29:20 +0100 Subject: ipu_idmac: fix spinlock type fix a probably accidently dropped reference operator while calling spin_unlock_restore to an ipu lock. Signed-off-by: Luotao Fu Cc: Guennadi Liakhovetski Signed-off-by: Andrew Morton Signed-off-by: Dan Williams --- drivers/dma/ipu/ipu_idmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/ipu/ipu_idmac.c b/drivers/dma/ipu/ipu_idmac.c index 1f154d08e98..ae50a9d1a4e 100644 --- a/drivers/dma/ipu/ipu_idmac.c +++ b/drivers/dma/ipu/ipu_idmac.c @@ -729,7 +729,7 @@ static int ipu_init_channel_buffer(struct idmac_channel *ichan, ichan->status = IPU_CHANNEL_READY; - spin_unlock_irqrestore(ipu->lock, flags); + spin_unlock_irqrestore(&ipu->lock, flags); return 0; } -- cgit v1.2.3 From 7cbd4877e5b167b56a3d6033b926a9f925186e12 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Wed, 4 Mar 2009 16:06:03 -0700 Subject: dmatest: fix use after free in dmatest_exit dmatest_cleanup_chanel will free dtc, so grab ->chan before it goes away and use it to do the release. Reported-by: Thierry Reding Signed-off-by: Dan Williams --- drivers/dma/dmatest.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c index 732fa1ec36a..e190d8b3070 100644 --- a/drivers/dma/dmatest.c +++ b/drivers/dma/dmatest.c @@ -430,13 +430,15 @@ late_initcall(dmatest_init); static void __exit dmatest_exit(void) { struct dmatest_chan *dtc, *_dtc; + struct dma_chan *chan; list_for_each_entry_safe(dtc, _dtc, &dmatest_channels, node) { list_del(&dtc->node); + chan = dtc->chan; dmatest_cleanup_channel(dtc); pr_debug("dmatest: dropped channel %s\n", - dma_chan_name(dtc->chan)); - dma_release_channel(dtc->chan); + dma_chan_name(chan)); + dma_release_channel(chan); } } module_exit(dmatest_exit); -- cgit v1.2.3 From a1a15ac5f9aeee521c048a88fc1aec848e623de7 Mon Sep 17 00:00:00 2001 From: Kris Shannon Date: Mon, 2 Mar 2009 19:47:37 +1100 Subject: Fix kernel NULL pointer dereference in xen-blkfront When booting Xen Dom0 on a pre-release 3.2.1 hypervisor the system Oopses on a "Unable to handle kernel NULL pointer dereference" in xenwatch. From the backtrace it looks like backend_changed is calling bdget_disk with a NULL pointer. Checking for NULL and returning ENODEV instead allows the kernel to boot. --- drivers/block/xen-blkfront.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index b6c8ce25435..8f905089b72 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c @@ -977,6 +977,8 @@ static void backend_changed(struct xenbus_device *dev, break; case XenbusStateClosing: + if (info->gd == NULL) + xenbus_dev_fatal(dev, -ENODEV, "gd is NULL"); bd = bdget_disk(info->gd, 0); if (bd == NULL) xenbus_dev_fatal(dev, -ENODEV, "bdget failed"); -- cgit v1.2.3 From 5e18cfd04feca78cc08a6b8b71a60a610de81eaa Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 27 Feb 2009 08:10:26 +0100 Subject: cciss: remove 30 second initial timeout on controller reset Commit 5e4c91c84b194b26cf592779e451f4b5be777cba forgot to remove the initial sleep, get rid of it. Thanks to Randy Dunlap for spotting this error. Signed-off-by: Jens Axboe --- drivers/block/cciss.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index b5a06111463..4f9b6d79201 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c @@ -3606,11 +3606,9 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, if (cciss_hard_reset_controller(pdev) || cciss_reset_msi(pdev)) return -ENODEV; - /* Some devices (notably the HP Smart Array 5i Controller) - need a little pause here */ - schedule_timeout_uninterruptible(30*HZ); - - /* Now try to get the controller to respond to a no-op */ + /* Now try to get the controller to respond to a no-op. Some + devices (notably the HP Smart Array 5i Controller) need + up to 30 seconds to respond. */ for (i=0; i<30; i++) { if (cciss_noop(pdev) == 0) break; -- cgit v1.2.3 From a3941ec101a5ec54c1e929730afeb196441a171e Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Thu, 5 Mar 2009 08:03:53 +0100 Subject: loop: don't increment p->offset with (size_t) -EINVAL Upon a 'transfer error block' size is set to -EINVAL, but this becomes positive since size is unsigned: p->offset still gets incremented. Signed-off-by: Roel Kluin Signed-off-by: Jens Axboe --- drivers/block/loop.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/block/loop.c b/drivers/block/loop.c index edbaac6c057..bf034557767 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c @@ -392,8 +392,7 @@ lo_splice_actor(struct pipe_inode_info *pipe, struct pipe_buffer *buf, struct loop_device *lo = p->lo; struct page *page = buf->page; sector_t IV; - size_t size; - int ret; + int size, ret; ret = buf->ops->confirm(pipe, buf); if (unlikely(ret)) -- cgit v1.2.3 From 5825627c9463581fd9e70f8285685889ae5bb9bb Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 27 Feb 2009 17:35:43 +0900 Subject: libata: fix dma_unmap_sg misuse libata passes the returned value of dma_map_sg() to dma_unmap_sg(),which is the misuse of dma_unmap_sg(). DMA-mapping.txt says: To unmap a scatterlist, just call: pci_unmap_sg(pdev, sglist, nents, direction); Again, make sure DMA activity has already finished. PLEASE NOTE: The 'nents' argument to the pci_unmap_sg call must be the _same_ one you passed into the pci_map_sg call, it should _NOT_ be the 'count' value _returned_ from the pci_map_sg call. Signed-off-by: FUJITA Tomonori Acked-by: Bartlomiej Zolnierkiewicz Acked-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9fbf0595f3d..5e324cea301 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -4612,7 +4612,7 @@ void ata_sg_clean(struct ata_queued_cmd *qc) VPRINTK("unmapping %u sg elements\n", qc->n_elem); if (qc->n_elem) - dma_unmap_sg(ap->dev, sg, qc->n_elem, dir); + dma_unmap_sg(ap->dev, sg, qc->orig_n_elem, dir); qc->flags &= ~ATA_QCFLAG_DMAMAP; qc->sg = NULL; @@ -4727,7 +4727,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc) return -1; DPRINTK("%d sg elements mapped\n", n_elem); - + qc->orig_n_elem = qc->n_elem; qc->n_elem = n_elem; qc->flags |= ATA_QCFLAG_DMAMAP; -- cgit v1.2.3 From b53570814692db79c3525523b6e9ec9874416c04 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Mon, 2 Mar 2009 18:55:16 +0900 Subject: libata: don't use on-stack sense buffer sense_buffer is used as DMA target and shouldn't be allocated on stack. Use ap->sector_buf instead. This problem is spotted by Chuck Ebbert. Signed-off-by: Tejun Heo Reported-by: Chuck Ebbert Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ce2ef047533..009ccc7c986 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2901,7 +2901,7 @@ static int atapi_eh_clear_ua(struct ata_device *dev) int i; for (i = 0; i < ATA_EH_UA_TRIES; i++) { - u8 sense_buffer[SCSI_SENSE_BUFFERSIZE]; + u8 *sense_buffer = dev->link->ap->sector_buf; u8 sense_key = 0; unsigned int err_mask; -- cgit v1.2.3 From 7adbe46b9289794f8fe629cd78c876169741177f Mon Sep 17 00:00:00 2001 From: peerchen Date: Fri, 27 Feb 2009 16:58:41 +0800 Subject: ahci: Add the Device IDs for MCP89 and remove IDs of MCP7B to/from ahci.c Added the Device IDs for MCP89 AHCI controller. Removed the IDs of MCP7B because this chipset had been cancelled. Signed-off-by: Peer Chen Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a603bbf9b1b..66e012cd327 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -582,18 +582,18 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x0abd), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0abe), board_ahci }, /* MCP79 */ { PCI_VDEVICE(NVIDIA, 0x0abf), board_ahci }, /* MCP79 */ - { PCI_VDEVICE(NVIDIA, 0x0bc8), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bc9), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bca), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bcb), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bcc), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci }, /* MCP7B */ - { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */ + { PCI_VDEVICE(NVIDIA, 0x0d84), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d85), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d86), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d87), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d88), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d89), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8a), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8b), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8c), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8d), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8e), board_ahci }, /* MCP89 */ + { PCI_VDEVICE(NVIDIA, 0x0d8f), board_ahci }, /* MCP89 */ /* SiS */ { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ -- cgit v1.2.3 From 55f784c826af2506e417bcc484d7e0e4d27f1977 Mon Sep 17 00:00:00 2001 From: Brandon Ehle Date: Sun, 1 Mar 2009 00:02:49 -0800 Subject: sata_nv: fix module parameter description Update MODULE_PARM_DESC for ADMA to reflect the fact that the option is disabled by default. Signed-off-by: Brandon Ehle Signed-off-by: Jeff Garzik --- drivers/ata/sata_nv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 55a8eed3f3a..f65b53785a8 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -2523,7 +2523,7 @@ static void __exit nv_exit(void) module_init(nv_init); module_exit(nv_exit); module_param_named(adma, adma_enabled, bool, 0444); -MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: true)"); +MODULE_PARM_DESC(adma, "Enable use of ADMA (Default: false)"); module_param_named(swncq, swncq_enabled, bool, 0444); MODULE_PARM_DESC(swncq, "Enable use of SWNCQ (Default: true)"); -- cgit v1.2.3 From d6515e6ff4ad3db4bd5ef2dd4e1026a7aca2482e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 4 Mar 2009 15:59:30 +0900 Subject: libata: make sure port is thawed when skipping resets When SCR access is available and the link is offline, softreset is skipped as it only wastes time and some controllers don't respond very well. However, the skip path forgot to thaw the port, which not only blocks further event notification from the port but also causes repeated EH invocations on the same event on drivers which rely on ->thaw() to clear events if the IRQ is shared with another device or port. This problem has always been there but is uncovered by recent sata_nv nf2/3 change which dropped hardreset support while maintaining SCR access. nf2/3 doesn't clear hotplug event mask from the interrupt handler but relies on ->thaw() to clear them. When the hardreset was there, the reset action was never skipped and the port was always thawed but, with the hardreset gone, ->prereset() determines that there's no need for softreset and both ->softreset() and ->thaw() are skipped. This leads to stuck hotplug event in the IRQ status register triggering hotplug event whenever IRQ is delieverd on the same IRQ. As the controller shares the same IRQ for both ports, this happens on every IO if one port is occpupied and the other isn't. This patch fixes the problem by making sure that the port is thawed on reset-skip path. bko#11615 reports this problem. Signed-off-by: Tejun Heo Cc: Robert Hancock Reported-by: Dan Andresan Reported-by: Arne Woerner Reported-by: Stefan Lippers-Hollmann Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 009ccc7c986..ea890911d4f 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2423,11 +2423,14 @@ int ata_eh_reset(struct ata_link *link, int classify, } /* prereset() might have cleared ATA_EH_RESET. If so, - * bang classes and return. + * bang classes, thaw and return. */ if (reset && !(ehc->i.action & ATA_EH_RESET)) { ata_for_each_dev(dev, link, ALL) classes[dev->devno] = ATA_DEV_NONE; + if ((ap->pflags & ATA_PFLAG_FROZEN) && + ata_is_host_link(link)) + ata_eh_thaw_port(ap); rc = 0; goto out; } -- cgit v1.2.3 From 968e594afdbc40b4270f9d4032ae8350475749d6 Mon Sep 17 00:00:00 2001 From: Robert Hancock Date: Mon, 16 Feb 2009 20:15:08 -0600 Subject: libata: Don't trust current capacity values in identify words 57-58 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hanno Böck reported a problem where an old Conner CP30254 240MB hard drive was reported as 1.1TB in capacity by libata: http://lkml.org/lkml/2009/2/13/134 This was caused by libata trusting the drive's reported current capacity in sectors in identify words 57 and 58 if the drive does not support LBA and the current CHS translation values appear valid. Unfortunately it seems older ATA specs were vague about what this field should contain and a number of drives used values with wrong byte order or that were totally bogus. There's no unique information that it conveys and so we can just calculate the number of sectors from the reported current CHS values. While we're at it, clean up this function to use named constants for the identify word values. Signed-off-by: Robert Hancock Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 5e324cea301..060bcd601f5 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -1322,14 +1322,16 @@ static u64 ata_id_n_sectors(const u16 *id) { if (ata_id_has_lba(id)) { if (ata_id_has_lba48(id)) - return ata_id_u64(id, 100); + return ata_id_u64(id, ATA_ID_LBA_CAPACITY_2); else - return ata_id_u32(id, 60); + return ata_id_u32(id, ATA_ID_LBA_CAPACITY); } else { if (ata_id_current_chs_valid(id)) - return ata_id_u32(id, 57); + return id[ATA_ID_CUR_CYLS] * id[ATA_ID_CUR_HEADS] * + id[ATA_ID_CUR_SECTORS]; else - return id[1] * id[3] * id[6]; + return id[ATA_ID_CYLS] * id[ATA_ID_HEADS] * + id[ATA_ID_SECTORS]; } } -- cgit v1.2.3 From b02c387892fc6b3cc59c78ab2f79413d55f50190 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Thu, 12 Feb 2009 13:42:41 +0300 Subject: [WATCHDOG] ks8695_wdt.c: 'CLOCK_TICK_RATE' undeclared On arm-acs5k_tiny: drivers/watchdog/ks8695_wdt.c:68: error: 'CLOCK_TICK_RATE' undeclared (first use in this function) Signed-off-by: Alexey Dobriyan Signed-off-by: Wim Van Sebroeck Cc: stable --- drivers/watchdog/ks8695_wdt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c index 0b798fdaa37..74c92d38411 100644 --- a/drivers/watchdog/ks8695_wdt.c +++ b/drivers/watchdog/ks8695_wdt.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #define WDT_DEFAULT_TIME 5 /* seconds */ -- cgit v1.2.3 From 26952669f01646c3e7d0832c99b310b199fe2b20 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 3 Mar 2009 15:10:05 +0100 Subject: [WATCHDOG] gef_wdt.c: fsl_get_sys_freq() failure not noticed fsl_get_sys_freq() may return -1 when 'soc' isn't found, but in gef_wdt_probe() 'freq' is unsigned, so the test doesn't catch that. Signed-off-by: Roel Kluin Signed-off-by: Wim Van Sebroeck Signed-off-by: Andrew Morton --- drivers/watchdog/gef_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c index f0c2b7a1a17..734d9806a87 100644 --- a/drivers/watchdog/gef_wdt.c +++ b/drivers/watchdog/gef_wdt.c @@ -269,7 +269,7 @@ static int __devinit gef_wdt_probe(struct of_device *dev, bus_clk = 133; /* in MHz */ freq = fsl_get_sys_freq(); - if (freq > 0) + if (freq != -1) bus_clk = freq; /* Map devices registers into memory */ -- cgit v1.2.3 From e0c6dcd8d4257a129fc813ac68f20b77c6ae2a7a Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Thu, 5 Mar 2009 16:10:55 +0100 Subject: ide: expiry() returns int, negative expiry() return values won't be noticed bart: It seems like the bug could cause insanely long timeouts for: - ATA_DMA_ERR error in dma_timer_expiry() - commands without ->expiry in tc86c001_timer_expiry() (TC86C001 IDE controller only) Signed-off-by: Roel Kluin Cc: Sergei Shtylyov Cc: Andrew Morton [bart: port it to the current tree] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 9ee51adf567..9ff90cb1dbf 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -908,7 +908,7 @@ void ide_timer_expiry (unsigned long data) ide_drive_t *uninitialized_var(drive); ide_handler_t *handler; unsigned long flags; - unsigned long wait = -1; + int wait = -1; int plug_device = 0; spin_lock_irqsave(&hwif->lock, flags); -- cgit v1.2.3 From 71bfc7a7c73eaf1f99e309dba60822ba050e3ec5 Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Thu, 5 Mar 2009 16:10:56 +0100 Subject: ide: NULL noise: drivers/ide/ide-*.c Fix this sparse warnings: drivers/ide/ide-disk_proc.c:130:11: warning: Using plain integer as NULL pointer drivers/ide/ide-floppy_proc.c:32:11: warning: Using plain integer as NULL pointer drivers/ide/ide-proc.c:234:11: warning: Using plain integer as NULL pointer drivers/ide/ide-tape.c:2141:11: warning: Using plain integer as NULL pointer Signed-off-by: Hannes Eder Cc: trivial@kernel.org Cc: kernel-janitors@vger.kernel.org Cc: Al Viro Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-disk_proc.c | 2 +- drivers/ide/ide-floppy_proc.c | 2 +- drivers/ide/ide-proc.c | 2 +- drivers/ide/ide-tape.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-disk_proc.c b/drivers/ide/ide-disk_proc.c index 1146f4204c6..1f86dcbd2b1 100644 --- a/drivers/ide/ide-disk_proc.c +++ b/drivers/ide/ide-disk_proc.c @@ -125,5 +125,5 @@ const struct ide_proc_devset ide_disk_settings[] = { IDE_PROC_DEVSET(multcount, 0, 16), IDE_PROC_DEVSET(nowerr, 0, 1), IDE_PROC_DEVSET(wcache, 0, 1), - { 0 }, + { NULL }, }; diff --git a/drivers/ide/ide-floppy_proc.c b/drivers/ide/ide-floppy_proc.c index 3ec762cb60a..fcd4d8153df 100644 --- a/drivers/ide/ide-floppy_proc.c +++ b/drivers/ide/ide-floppy_proc.c @@ -29,5 +29,5 @@ const struct ide_proc_devset ide_floppy_settings[] = { IDE_PROC_DEVSET(bios_head, 0, 255), IDE_PROC_DEVSET(bios_sect, 0, 63), IDE_PROC_DEVSET(ticks, 0, 255), - { 0 }, + { NULL }, }; diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 1d8978b3314..a7b9287ee0d 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -231,7 +231,7 @@ static const struct ide_proc_devset ide_generic_settings[] = { IDE_PROC_DEVSET(pio_mode, 0, 255), IDE_PROC_DEVSET(unmaskirq, 0, 1), IDE_PROC_DEVSET(using_dma, 0, 1), - { 0 }, + { NULL }, }; static void proc_ide_settings_warn(void) diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index bb450a7608c..4e6181c7bbd 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2166,7 +2166,7 @@ static const struct ide_proc_devset idetape_settings[] = { __IDE_PROC_DEVSET(speed, 0, 0xffff, NULL, NULL), __IDE_PROC_DEVSET(tdsc, IDETAPE_DSC_RW_MIN, IDETAPE_DSC_RW_MAX, mulf_tdsc, divf_tdsc), - { 0 }, + { NULL }, }; #endif -- cgit v1.2.3 From a509538d4fb4f99cdf0a095213d57cc3b2347615 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Thu, 5 Mar 2009 16:10:56 +0100 Subject: ide-iops: fix odd-length ATAPI PIO transfers Commit 9567b349f7e7dd7e2483db99ee8e4a6fe0caca38 (ide: merge ->atapi_*put_bytes and ->ata_*put_data methods) introduced a regression WRT the odd-length ATAPI PIO transfers -- the final word didn't get written (causing command timeouts). Signed-off-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 753b92ebe0a..b1892bd95c6 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -315,6 +315,8 @@ void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf, u8 io_32bit = drive->io_32bit; u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + len++; + if (io_32bit) { unsigned long uninitialized_var(flags); -- cgit v1.2.3 From 849d7130001ab740a5a4778a561049841fdd77c9 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 5 Mar 2009 16:10:57 +0100 Subject: ide: allow to wrap interrupt handler Signed-off-by: Stanislaw Gruszka Cc: Andrew Victor [bart: minor checkpatch.pl / CodingStyle fixups] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 1 + drivers/ide/ide-probe.c | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 9ff90cb1dbf..a9a6c208288 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1162,6 +1162,7 @@ out_early: return irq_ret; } +EXPORT_SYMBOL_GPL(ide_intr); /** * ide_do_drive_cmd - issue IDE special command diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index ce0818a993f..ee8e3e7cad5 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -950,6 +950,7 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) static int init_irq (ide_hwif_t *hwif) { struct ide_io_ports *io_ports = &hwif->io_ports; + irq_handler_t irq_handler; int sa = 0; mutex_lock(&ide_cfg_mtx); @@ -959,6 +960,10 @@ static int init_irq (ide_hwif_t *hwif) hwif->timer.function = &ide_timer_expiry; hwif->timer.data = (unsigned long)hwif; + irq_handler = hwif->host->irq_handler; + if (irq_handler == NULL) + irq_handler = ide_intr; + #if defined(__mc68000__) sa = IRQF_SHARED; #endif /* __mc68000__ */ @@ -969,7 +974,7 @@ static int init_irq (ide_hwif_t *hwif) if (io_ports->ctl_addr) hwif->tp_ops->set_irq(hwif, 1); - if (request_irq(hwif->irq, &ide_intr, sa, hwif->name, hwif)) + if (request_irq(hwif->irq, irq_handler, sa, hwif->name, hwif)) goto out_up; if (!hwif->rqsize) { -- cgit v1.2.3 From 6e5f1e1115bb041993f9f247036996364b4c84d5 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Thu, 5 Mar 2009 16:10:58 +0100 Subject: ide: add at91_ide driver This is IDE host driver for AT91 (SAM9, CAP9, AT572D940HF) Static Memory Controller with Compact Flash True IDE Mode logic. Driver have to switch 8/16 bit bus width when accessing Task Tile or Data Register. Moreover some extra things need to be done when setting PIO mode. Only PIO mode is used, hardware have no DMA support. If interrupt line is connected through GPIO extra quirk is needed to cope with fake interrupts. Signed-off-by: Stanislaw Gruszka Cc: Andrew Victor Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 5 + drivers/ide/Makefile | 1 + drivers/ide/at91_ide.c | 467 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 473 insertions(+) create mode 100644 drivers/ide/at91_ide.c (limited to 'drivers') diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index e072903b12f..5ea3bfad172 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -721,6 +721,11 @@ config BLK_DEV_IDE_TX4939 depends on SOC_TX4939 select BLK_DEV_IDEDMA_SFF +config BLK_DEV_IDE_AT91 + tristate "Atmel AT91 (SAM9, CAP9, AT572D940HF) IDE support" + depends on ARM && ARCH_AT91 && !ARCH_AT91RM9200 && !ARCH_AT91X40 + select IDE_TIMINGS + config IDE_ARM tristate "ARM IDE support" depends on ARM && (ARCH_RPC || ARCH_SHARK) diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index d0e3d7d5b46..1c326d94aa6 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -116,3 +116,4 @@ obj-$(CONFIG_BLK_DEV_IDE_AU1XXX) += au1xxx-ide.o obj-$(CONFIG_BLK_DEV_IDE_TX4938) += tx4938ide.o obj-$(CONFIG_BLK_DEV_IDE_TX4939) += tx4939ide.o +obj-$(CONFIG_BLK_DEV_IDE_AT91) += at91_ide.o diff --git a/drivers/ide/at91_ide.c b/drivers/ide/at91_ide.c new file mode 100644 index 00000000000..1bb50f46388 --- /dev/null +++ b/drivers/ide/at91_ide.c @@ -0,0 +1,467 @@ +/* + * IDE host driver for AT91 (SAM9, CAP9, AT572D940HF) Static Memory Controller + * with Compact Flash True IDE logic + * + * Copyright (c) 2008, 2009 Kelvatek Ltd. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define DRV_NAME "at91_ide" + +#define perr(fmt, args...) pr_err(DRV_NAME ": " fmt, ##args) +#define pdbg(fmt, args...) pr_debug("%s " fmt, __func__, ##args) + +/* + * Access to IDE device is possible through EBI Static Memory Controller + * with Compact Flash logic. For details see EBI and SMC datasheet sections + * of any microcontroller from AT91SAM9 family. + * + * Within SMC chip select address space, lines A[23:21] distinguish Compact + * Flash modes (I/O, common memory, attribute memory, True IDE). IDE modes are: + * 0x00c0000 - True IDE + * 0x00e0000 - Alternate True IDE (Alt Status Register) + * + * On True IDE mode Task File and Data Register are mapped at the same address. + * To distinguish access between these two different bus data width is used: + * 8Bit for Task File, 16Bit for Data I/O. + * + * After initialization we do 8/16 bit flipping (changes in SMC MODE register) + * only inside IDE callback routines which are serialized by IDE layer, + * so no additional locking needed. + */ + +#define TASK_FILE 0x00c00000 +#define ALT_MODE 0x00e00000 +#define REGS_SIZE 8 + +#define enter_16bit(cs, mode) do { \ + mode = at91_sys_read(AT91_SMC_MODE(cs)); \ + at91_sys_write(AT91_SMC_MODE(cs), mode | AT91_SMC_DBW_16); \ +} while (0) + +#define leave_16bit(cs, mode) at91_sys_write(AT91_SMC_MODE(cs), mode); + +static void set_smc_timings(const u8 chipselect, const u16 cycle, + const u16 setup, const u16 pulse, + const u16 data_float, int use_iordy) +{ + unsigned long mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | + AT91_SMC_BAT_SELECT; + + /* disable or enable waiting for IORDY signal */ + if (use_iordy) + mode |= AT91_SMC_EXNWMODE_READY; + + /* add data float cycles if needed */ + if (data_float) + mode |= AT91_SMC_TDF_(data_float); + + at91_sys_write(AT91_SMC_MODE(chipselect), mode); + + /* setup timings in SMC */ + at91_sys_write(AT91_SMC_SETUP(chipselect), AT91_SMC_NWESETUP_(setup) | + AT91_SMC_NCS_WRSETUP_(0) | + AT91_SMC_NRDSETUP_(setup) | + AT91_SMC_NCS_RDSETUP_(0)); + at91_sys_write(AT91_SMC_PULSE(chipselect), AT91_SMC_NWEPULSE_(pulse) | + AT91_SMC_NCS_WRPULSE_(cycle) | + AT91_SMC_NRDPULSE_(pulse) | + AT91_SMC_NCS_RDPULSE_(cycle)); + at91_sys_write(AT91_SMC_CYCLE(chipselect), AT91_SMC_NWECYCLE_(cycle) | + AT91_SMC_NRDCYCLE_(cycle)); +} + +static unsigned int calc_mck_cycles(unsigned int ns, unsigned int mck_hz) +{ + u64 tmp = ns; + + tmp *= mck_hz; + tmp += 1000*1000*1000 - 1; /* round up */ + do_div(tmp, 1000*1000*1000); + return (unsigned int) tmp; +} + +static void apply_timings(const u8 chipselect, const u8 pio, + const struct ide_timing *timing, int use_iordy) +{ + unsigned int t0, t1, t2, t6z; + unsigned int cycle, setup, pulse, data_float; + unsigned int mck_hz; + struct clk *mck; + + /* see table 22 of Compact Flash standard 4.1 for the meaning, + * we do not stretch active (t2) time, so setup (t1) + hold time (th) + * assure at least minimal recovery (t2i) time */ + t0 = timing->cyc8b; + t1 = timing->setup; + t2 = timing->act8b; + t6z = (pio < 5) ? 30 : 20; + + pdbg("t0=%u t1=%u t2=%u t6z=%u\n", t0, t1, t2, t6z); + + mck = clk_get(NULL, "mck"); + BUG_ON(IS_ERR(mck)); + mck_hz = clk_get_rate(mck); + pdbg("mck_hz=%u\n", mck_hz); + + cycle = calc_mck_cycles(t0, mck_hz); + setup = calc_mck_cycles(t1, mck_hz); + pulse = calc_mck_cycles(t2, mck_hz); + data_float = calc_mck_cycles(t6z, mck_hz); + + pdbg("cycle=%u setup=%u pulse=%u data_float=%u\n", + cycle, setup, pulse, data_float); + + set_smc_timings(chipselect, cycle, setup, pulse, data_float, use_iordy); +} + +static void at91_ide_input_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + u8 chipselect = hwif->select_data; + unsigned long mode; + + pdbg("cs %u buf %p len %d\n", chipselect, buf, len); + + len++; + + enter_16bit(chipselect, mode); + __ide_mm_insw((void __iomem *) io_ports->data_addr, buf, len / 2); + leave_16bit(chipselect, mode); +} + +static void at91_ide_output_data(ide_drive_t *drive, struct request *rq, + void *buf, unsigned int len) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + u8 chipselect = hwif->select_data; + unsigned long mode; + + pdbg("cs %u buf %p len %d\n", chipselect, buf, len); + + enter_16bit(chipselect, mode); + __ide_mm_outsw((void __iomem *) io_ports->data_addr, buf, len / 2); + leave_16bit(chipselect, mode); +} + +static u8 ide_mm_inb(unsigned long port) +{ + return readb((void __iomem *) port); +} + +static void ide_mm_outb(u8 value, unsigned long port) +{ + writeb(value, (void __iomem *) port); +} + +static void at91_ide_tf_load(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) { + u16 data = (tf->hob_data << 8) | tf->data; + + at91_ide_output_data(drive, NULL, &data, 2); + } + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + ide_mm_outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + ide_mm_outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + ide_mm_outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + ide_mm_outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + ide_mm_outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + ide_mm_outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + ide_mm_outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + ide_mm_outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + ide_mm_outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + ide_mm_outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + ide_mm_outb((tf->device & HIHI) | drive->select, io_ports->device_addr); +} + +static void at91_ide_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data; + + at91_ide_input_data(drive, NULL, &data, 2); + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + ide_mm_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_FEATURE) + tf->feature = ide_mm_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = ide_mm_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = ide_mm_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = ide_mm_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = ide_mm_inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = ide_mm_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + ide_mm_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = ide_mm_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = ide_mm_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = ide_mm_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = ide_mm_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = ide_mm_inb(io_ports->lbah_addr); + } +} + +static void at91_ide_set_pio_mode(ide_drive_t *drive, const u8 pio) +{ + struct ide_timing *timing; + u8 chipselect = drive->hwif->select_data; + int use_iordy = 0; + + pdbg("chipselect %u pio %u\n", chipselect, pio); + + timing = ide_timing_find_mode(XFER_PIO_0 + pio); + BUG_ON(!timing); + + if ((pio > 2 || ata_id_has_iordy(drive->id)) && + !(ata_id_is_cfa(drive->id) && pio > 4)) + use_iordy = 1; + + apply_timings(chipselect, pio, timing, use_iordy); +} + +static const struct ide_tp_ops at91_ide_tp_ops = { + .exec_command = ide_exec_command, + .read_status = ide_read_status, + .read_altstatus = ide_read_altstatus, + .set_irq = ide_set_irq, + + .tf_load = at91_ide_tf_load, + .tf_read = at91_ide_tf_read, + + .input_data = at91_ide_input_data, + .output_data = at91_ide_output_data, +}; + +static const struct ide_port_ops at91_ide_port_ops = { + .set_pio_mode = at91_ide_set_pio_mode, +}; + +static const struct ide_port_info at91_ide_port_info __initdata = { + .port_ops = &at91_ide_port_ops, + .tp_ops = &at91_ide_tp_ops, + .host_flags = IDE_HFLAG_MMIO | IDE_HFLAG_NO_DMA | IDE_HFLAG_SINGLE | + IDE_HFLAG_NO_IO_32BIT | IDE_HFLAG_UNMASK_IRQS, + .pio_mask = ATA_PIO5, +}; + +/* + * If interrupt is delivered through GPIO, IRQ are triggered on falling + * and rising edge of signal. Whereas IDE device request interrupt on high + * level (rising edge in our case). This mean we have fake interrupts, so + * we need to check interrupt pin and exit instantly from ISR when line + * is on low level. + */ + +irqreturn_t at91_irq_handler(int irq, void *dev_id) +{ + int ntries = 8; + int pin_val1, pin_val2; + + /* additional deglitch, line can be noisy in badly designed PCB */ + do { + pin_val1 = at91_get_gpio_value(irq); + pin_val2 = at91_get_gpio_value(irq); + } while (pin_val1 != pin_val2 && --ntries > 0); + + if (pin_val1 == 0 || ntries <= 0) + return IRQ_HANDLED; + + return ide_intr(irq, dev_id); +} + +static int __init at91_ide_probe(struct platform_device *pdev) +{ + int ret; + hw_regs_t hw; + hw_regs_t *hws[] = { &hw, NULL, NULL, NULL }; + struct ide_host *host; + struct resource *res; + unsigned long tf_base = 0, ctl_base = 0; + struct at91_cf_data *board = pdev->dev.platform_data; + + if (!board) + return -ENODEV; + + if (board->det_pin && at91_get_gpio_value(board->det_pin) != 0) { + perr("no device detected\n"); + return -ENODEV; + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + perr("can't get memory resource\n"); + return -ENODEV; + } + + if (!devm_request_mem_region(&pdev->dev, res->start + TASK_FILE, + REGS_SIZE, "ide") || + !devm_request_mem_region(&pdev->dev, res->start + ALT_MODE, + REGS_SIZE, "alt")) { + perr("memory resources in use\n"); + return -EBUSY; + } + + pdbg("chipselect %u irq %u res %08lx\n", board->chipselect, + board->irq_pin, (unsigned long) res->start); + + tf_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + TASK_FILE, + REGS_SIZE); + ctl_base = (unsigned long) devm_ioremap(&pdev->dev, res->start + ALT_MODE, + REGS_SIZE); + if (!tf_base || !ctl_base) { + perr("can't map memory regions\n"); + return -EBUSY; + } + + memset(&hw, 0, sizeof(hw)); + + if (board->flags & AT91_IDE_SWAP_A0_A2) { + /* workaround for stupid hardware bug */ + hw.io_ports.data_addr = tf_base + 0; + hw.io_ports.error_addr = tf_base + 4; + hw.io_ports.nsect_addr = tf_base + 2; + hw.io_ports.lbal_addr = tf_base + 6; + hw.io_ports.lbam_addr = tf_base + 1; + hw.io_ports.lbah_addr = tf_base + 5; + hw.io_ports.device_addr = tf_base + 3; + hw.io_ports.command_addr = tf_base + 7; + hw.io_ports.ctl_addr = ctl_base + 3; + } else + ide_std_init_ports(&hw, tf_base, ctl_base + 6); + + hw.irq = board->irq_pin; + hw.chipset = ide_generic; + hw.dev = &pdev->dev; + + host = ide_host_alloc(&at91_ide_port_info, hws); + if (!host) { + perr("failed to allocate ide host\n"); + return -ENOMEM; + } + + /* setup Static Memory Controller - PIO 0 as default */ + apply_timings(board->chipselect, 0, ide_timing_find_mode(XFER_PIO_0), 0); + + /* with GPIO interrupt we have to do quirks in handler */ + if (board->irq_pin >= PIN_BASE) + host->irq_handler = at91_irq_handler; + + host->ports[0]->select_data = board->chipselect; + + ret = ide_host_register(host, &at91_ide_port_info, hws); + if (ret) { + perr("failed to register ide host\n"); + goto err_free_host; + } + platform_set_drvdata(pdev, host); + return 0; + +err_free_host: + ide_host_free(host); + return ret; +} + +static int __exit at91_ide_remove(struct platform_device *pdev) +{ + struct ide_host *host = platform_get_drvdata(pdev); + + ide_host_remove(host); + return 0; +} + +static struct platform_driver at91_ide_driver = { + .driver = { + .name = DRV_NAME, + .owner = THIS_MODULE, + }, + .remove = __exit_p(at91_ide_remove), +}; + +static int __init at91_ide_init(void) +{ + return platform_driver_probe(&at91_ide_driver, at91_ide_probe); +} + +static void __exit at91_ide_exit(void) +{ + platform_driver_unregister(&at91_ide_driver); +} + +module_init(at91_ide_init); +module_exit(at91_ide_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Stanislaw Gruszka "); + -- cgit v1.2.3 From 33dd6f92a1a7ad85c54d47fd9d73371a32c0bde4 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 20 Feb 2009 06:53:48 -0700 Subject: [SCSI] sd: Don't try to spin up drives that are connected to an inactive port We currently try to spin up drives connected to standby and unavailable ports. This will never succeed and wastes a lot of time. Fail quickly if the sense data reports the port is in standby or unavailable state. Reported-by: Narayanan Rengarajan Tested-by: Narayanan Rengarajan Signed-off-by: Matthew Wilcox Signed-off-by: James Bottomley --- drivers/scsi/sd.c | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 55310dbc10a..4970ae4a62d 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1167,23 +1167,19 @@ sd_spinup_disk(struct scsi_disk *sdkp) /* * The device does not want the automatic start to be issued. */ - if (sdkp->device->no_start_on_add) { + if (sdkp->device->no_start_on_add) break; - } - - /* - * If manual intervention is required, or this is an - * absent USB storage device, a spinup is meaningless. - */ - if (sense_valid && - sshdr.sense_key == NOT_READY && - sshdr.asc == 4 && sshdr.ascq == 3) { - break; /* manual intervention required */ - /* - * Issue command to spin up drive when not ready - */ - } else if (sense_valid && sshdr.sense_key == NOT_READY) { + if (sense_valid && sshdr.sense_key == NOT_READY) { + if (sshdr.asc == 4 && sshdr.ascq == 3) + break; /* manual intervention required */ + if (sshdr.asc == 4 && sshdr.ascq == 0xb) + break; /* standby */ + if (sshdr.asc == 4 && sshdr.ascq == 0xc) + break; /* unavailable */ + /* + * Issue command to spin up drive when not ready + */ if (!spintime) { sd_printk(KERN_NOTICE, sdkp, "Spinning up disk..."); cmd[0] = START_STOP; -- cgit v1.2.3 From c9a0c8a6845b5efb64841f40b8efb4c387051d46 Mon Sep 17 00:00:00 2001 From: Wim Van Sebroeck Date: Wed, 25 Feb 2009 13:33:01 +0100 Subject: [WATCHDOG] orion5x_wdt.c: 'ORION5X_TCLK' undeclared orion5x_wdt no longer compiled after the changes in commit ebe35aff883496c07248df82c8576c3b6e84bbbe ("Orion: prepare for runtime-determined timer tick rate"). The tick rate define (ORION5X_TCLK) was removed in favor of a runtime detection. The quick fix is to add the define in the watchdog driver. The fix is not correct for all supported orion5x platforms, but since the supported platforms right now are 133 Mhz and 166 Mhz, it won't be _that_ far off. ;-) A fix that uses the runtime-determined timer tick rate will be applied later. Signed-off-by: Wim Van Sebroeck Cc: Kristof Provost Acked-by: Lennert Buytenhek Cc: Nicolas Pitre Cc: Russell King Cc: Andrew Morton --- drivers/watchdog/orion5x_wdt.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c index 14a339f58b6..b64ae1a1783 100644 --- a/drivers/watchdog/orion5x_wdt.c +++ b/drivers/watchdog/orion5x_wdt.c @@ -29,6 +29,7 @@ #define WDT_EN 0x0010 #define WDT_VAL (TIMER_VIRT_BASE + 0x0024) +#define ORION5X_TCLK 166666667 #define WDT_MAX_DURATION (0xffffffff / ORION5X_TCLK) #define WDT_IN_USE 0 #define WDT_OK_TO_CLOSE 1 -- cgit v1.2.3 From d2c452306ab402d7a3572bc3bf8e575796529bf8 Mon Sep 17 00:00:00 2001 From: Gregory Lardiere Date: Sun, 22 Feb 2009 17:54:11 -0300 Subject: V4L/DVB (10789): m5602-s5k4aa: Split up the initial sensor probe in chunks. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The previous probe rotine tried to read 6 bytes in one chunk which currently isn't allowed. This is the rev. 10346 243399e67c41 readded with a high priority. Signed-off-by: Gregory Lardiere Signed-off-by: Erik Andrén Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/gspca/m5602/m5602_s5k4aa.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c index e564a61a72d..48892b5715d 100644 --- a/drivers/media/video/gspca/m5602/m5602_s5k4aa.c +++ b/drivers/media/video/gspca/m5602/m5602_s5k4aa.c @@ -102,7 +102,11 @@ int s5k4aa_probe(struct sd *sd) } /* Test some registers, but we don't know their exact meaning yet */ - if (m5602_read_sensor(sd, 0x00, prod_id, sizeof(prod_id))) + if (m5602_read_sensor(sd, 0x00, prod_id, 2)) + return -ENODEV; + if (m5602_read_sensor(sd, 0x02, prod_id+2, 2)) + return -ENODEV; + if (m5602_read_sensor(sd, 0x04, prod_id+4, 2)) return -ENODEV; if (memcmp(prod_id, expected_prod_id, sizeof(prod_id))) -- cgit v1.2.3 From 4c6c390eb8ba0c569279266a98c604508c695ef8 Mon Sep 17 00:00:00 2001 From: Vitaly Wool Date: Thu, 5 Mar 2009 13:03:32 -0300 Subject: V4L/DVB (10832): tvaudio: Avoid breakage with tda9874a The 'bytes' array is 64 bytes large but the easy standard programming (TDA9874A_ESP) has a number of 255, outside the shadow array size. This patch increases the size of the shadow array in order to accomodate this register. Signed-off-by: Vitaly Wool Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/tvaudio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/video/tvaudio.c b/drivers/media/video/tvaudio.c index 5aeccb301ce..076ed5bf48b 100644 --- a/drivers/media/video/tvaudio.c +++ b/drivers/media/video/tvaudio.c @@ -54,7 +54,7 @@ MODULE_LICENSE("GPL"); /* ---------------------------------------------------------------------- */ /* our structs */ -#define MAXREGS 64 +#define MAXREGS 256 struct CHIPSTATE; typedef int (*getvalue)(int); -- cgit v1.2.3 From e08e7b5f01de7ec246b996c65e9c26c7cea0c62d Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 5 Mar 2009 16:19:14 -0300 Subject: V4L/DVB (10834): zoran: auto-select bt866 for AverMedia 6 Eyes AFAIK, the bt866 is only seen on AverMedia 6 Eyes. However, no module selects it. Adds a proper select for this driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/media/video/zoran/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/media/video/zoran/Kconfig b/drivers/media/video/zoran/Kconfig index 4ea5fa71de8..8666e19f31a 100644 --- a/drivers/media/video/zoran/Kconfig +++ b/drivers/media/video/zoran/Kconfig @@ -68,6 +68,7 @@ config VIDEO_ZORAN_AVS6EYES tristate "AverMedia 6 Eyes support (EXPERIMENTAL)" depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL && VIDEO_V4L1 select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO + select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO help Support for the AverMedia 6 Eyes video surveillance card. -- cgit v1.2.3 From f033599aac86f4eb08a1b6b851568a2587e8c6ad Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 6 Mar 2009 17:56:58 +0900 Subject: sh: intc: Make missing unique IRQ mask warning more verbose. This includes the IRQ number in addition to the vector, as not all platforms wrap in with INTC_VECT(). Signed-off-by: Paul Mundt --- drivers/sh/intc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index d7b8959d9d9..2269fbcaa18 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c @@ -569,8 +569,8 @@ static void __init intc_register_irq(struct intc_desc *desc, primary = 1; if (!data[0] && !data[1]) - pr_warning("intc: missing unique irq mask for 0x%04x\n", - irq2evt(irq)); + pr_warning("intc: missing unique irq mask for " + "irq %d (vect 0x%04x)\n", irq, irq2evt(irq)); data[0] = data[0] ? data[0] : intc_mask_data(desc, d, enum_id, 1); data[1] = data[1] ? data[1] : intc_prio_data(desc, d, enum_id, 1); -- cgit v1.2.3 From e26b926a561ba24bfeb8a15bfc848f97052a50f4 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Fri, 6 Mar 2009 18:51:33 +0900 Subject: rtc: rtc-sh: Bump version up to reflect single IRQ support changes. Signed-off-by: Paul Mundt --- drivers/rtc/rtc-sh.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index b37f44b0406..aeff2511197 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -28,7 +28,7 @@ #include #define DRV_NAME "sh-rtc" -#define DRV_VERSION "0.2.0" +#define DRV_VERSION "0.2.1" #define RTC_REG(r) ((r) * rtc_reg_size) -- cgit v1.2.3 From 1f6ff364ceda516f88351a8ab640e656beed0b26 Mon Sep 17 00:00:00 2001 From: Abhijeet Joglekar Date: Fri, 27 Feb 2009 10:54:35 -0800 Subject: [SCSI] libfc: Pass lport in exch_mgr_reset fc_exch_mgr structure is private to fc_exch.c. To export exch_mgr_reset to transport, transport needs access to the exch manager. Change exch_mgr_reset to use lport param which is the shared structure between libFC and transport. Alternatively, fc_exch_mgr definition can be moved to libfc.h so that lport can be accessed from mp*. Signed-off-by: Abhijeet Joglekar Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 3 ++- drivers/scsi/libfc/fc_lport.c | 4 ++-- drivers/scsi/libfc/fc_rport.c | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 66db08a5f27..a09416fd843 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1480,10 +1480,11 @@ static void fc_exch_reset(struct fc_exch *ep) * If sid is non-zero, reset only exchanges we source from that FID. * If did is non-zero, reset only exchanges destined to that FID. */ -void fc_exch_mgr_reset(struct fc_exch_mgr *mp, u32 sid, u32 did) +void fc_exch_mgr_reset(struct fc_lport *lp, u32 sid, u32 did) { struct fc_exch *ep; struct fc_exch *next; + struct fc_exch_mgr *mp = lp->emp; spin_lock_bh(&mp->em_lock); restart: diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 0b9bdb1fb80..5db223ce3b2 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -663,7 +663,7 @@ int fc_lport_destroy(struct fc_lport *lport) { lport->tt.frame_send = fc_frame_drop; lport->tt.fcp_abort_io(lport); - lport->tt.exch_mgr_reset(lport->emp, 0, 0); + lport->tt.exch_mgr_reset(lport, 0, 0); return 0; } EXPORT_SYMBOL(fc_lport_destroy); @@ -973,7 +973,7 @@ static void fc_lport_enter_reset(struct fc_lport *lport) lport->tt.disc_stop(lport); - lport->tt.exch_mgr_reset(lport->emp, 0, 0); + lport->tt.exch_mgr_reset(lport, 0, 0); fc_host_fabric_name(lport->host) = 0; fc_host_port_id(lport->host) = 0; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index e780d8caf70..dec7bae0e56 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1285,7 +1285,7 @@ void fc_rport_terminate_io(struct fc_rport *rport) struct fc_rport_libfc_priv *rdata = rport->dd_data; struct fc_lport *lport = rdata->local_port; - lport->tt.exch_mgr_reset(lport->emp, 0, rport->port_id); - lport->tt.exch_mgr_reset(lport->emp, rport->port_id, 0); + lport->tt.exch_mgr_reset(lport, 0, rport->port_id); + lport->tt.exch_mgr_reset(lport, rport->port_id, 0); } EXPORT_SYMBOL(fc_rport_terminate_io); -- cgit v1.2.3 From 571f824c3cd7b7f5a40ba100f7e576b6b0fe826a Mon Sep 17 00:00:00 2001 From: Abhijeet Joglekar Date: Fri, 27 Feb 2009 10:54:41 -0800 Subject: [SCSI] libfc: when rport goes away (re-plogi), clean up exchanges to/from rport When a rport goes away, libFC does a plogi which will reset exchanges at the rport. Clean exchanges at our end, both in transport and libFC. If transport hooks into exch_mgr_reset, it will call back into fc_exch_mgr_reset() to clean up libFC exchanges. Signed-off-by: Abhijeet Joglekar Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_rport.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index dec7bae0e56..71757593415 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -214,6 +214,7 @@ static void fc_rport_state_enter(struct fc_rport *rport, static void fc_rport_work(struct work_struct *work) { + u32 port_id; struct fc_rport_libfc_priv *rdata = container_of(work, struct fc_rport_libfc_priv, event_work); enum fc_rport_event event; @@ -279,8 +280,12 @@ static void fc_rport_work(struct work_struct *work) rport_ops->event_callback(lport, rport, event); if (trans_state == FC_PORTSTATE_ROGUE) put_device(&rport->dev); - else + else { + port_id = rport->port_id; fc_remote_port_delete(rport); + lport->tt.exch_mgr_reset(lport, 0, port_id); + lport->tt.exch_mgr_reset(lport, port_id, 0); + } } else mutex_unlock(&rdata->rp_mutex); } -- cgit v1.2.3 From 78342da3682ec843e3e6301af5c723c88a46c408 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:54:46 -0800 Subject: [SCSI] libfc: handle RRQ exch timeout Cleanup exchange held due to RRQ when RRQ exch times out, in this case the ABTS is already done causing RRQ req therefore proceeding with cleanup in fc_exch_rrq_resp should be okay to restore exch resource. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index a09416fd843..e874e77b740 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1608,7 +1608,7 @@ static void fc_exch_rrq_resp(struct fc_seq *sp, struct fc_frame *fp, void *arg) if (IS_ERR(fp)) { int err = PTR_ERR(fp); - if (err == -FC_EX_CLOSED) + if (err == -FC_EX_CLOSED || err == -FC_EX_TIMEOUT) goto cleanup; FC_DBG("Cannot process RRQ, because of frame error %d\n", err); return; -- cgit v1.2.3 From a7e84f2b83f17f8f11da34ccef3ba5a862dc0182 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:54:51 -0800 Subject: [SCSI] libfc: fixed a soft lockup issue in fc_exch_recv_abts The fc_seq_start_next grabs ep->ex_lock but this lock was already held here, so instead called fc_seq_start_next_locked to avoid soft lockup. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index e874e77b740..dd269e5f953 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -1096,7 +1096,7 @@ static void fc_exch_recv_abts(struct fc_exch *ep, struct fc_frame *rx_fp) ap->ba_high_seq_cnt = fh->fh_seq_cnt; ap->ba_low_seq_cnt = htons(sp->cnt); } - sp = fc_seq_start_next(sp); + sp = fc_seq_start_next_locked(sp); spin_unlock_bh(&ep->ex_lock); fc_seq_send_last(sp, fp, FC_RCTL_BA_ACC, FC_TYPE_BLS); fc_frame_free(rx_fp); -- cgit v1.2.3 From bc0e17f691085315ae9303eb5b0883fe16dfe6b1 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:54:57 -0800 Subject: [SCSI] libfc, fcoe: fixed locking issues with lport->lp_mutex around lport->link_status The fcoe_xmit could call fc_pause in case the pending skb queue len is larger than FCOE_MAX_QUEUE_DEPTH, the fc_pause was trying to grab lport->lp_muex to change lport->link_status and that had these issues :- 1. The fcoe_xmit was getting called with bh disabled, thus causing "BUG: scheduling while atomic" when grabbing lport->lp_muex with bh disabled. 2. fc_linkup and fc_linkdown function calls lport_enter function with lport->lp_mutex held and these enter function in turn calls fcoe_xmit to send lport related FC frame, e.g. fc_linkup => fc_lport_enter_flogi to send flogi req. In this case grabbing the same lport->lp_mutex again in fc_puase from fcoe_xmit would cause deadlock. The lport->lp_mutex was used for setting FC_PAUSE in fcoe_xmit path but FC_PAUSE bit was not used anywhere beside just setting and clear this bit in lport->link_status, instead used a separate field qfull in fc_lport to eliminate need for lport->lp_mutex to track pending queue full condition and in turn avoid above described two locking issues. Also added check for lp->qfull in fc_fcp_lport_queue_ready to trigger SCSI_MLQUEUE_HOST_BUSY when lp->qfull is set to prevent more scsi-ml cmds while lp->qfull is set. This patch eliminated FC_LINK_UP and FC_PAUSE and instead used dedicated fields in fc_lport for this, this simplified all related conditional code. Also removed fc_pause and fc_unpause functions and instead used newly added lport->qfull directly in fcoe. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_sw.c | 6 +++--- drivers/scsi/fcoe/libfcoe.c | 41 +++++++++++++++++------------------------ drivers/scsi/libfc/fc_fcp.c | 4 ++-- drivers/scsi/libfc/fc_lport.c | 36 ++++++------------------------------ 4 files changed, 28 insertions(+), 59 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index dc4cd5e2576..cf83675a0fb 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -116,7 +116,8 @@ static int fcoe_sw_lport_config(struct fc_lport *lp) { int i = 0; - lp->link_status = 0; + lp->link_up = 0; + lp->qfull = 0; lp->max_retry_count = 3; lp->e_d_tov = 2 * 1000; /* FC-FS default */ lp->r_a_tov = 2 * 2 * 1000; @@ -181,9 +182,8 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) if (fc_set_mfs(lp, mfs)) return -EINVAL; - lp->link_status = ~FC_PAUSE & ~FC_LINK_UP; if (!fcoe_link_ok(lp)) - lp->link_status |= FC_LINK_UP; + lp->link_up = 1; /* offload features support */ if (fc->real_dev->features & NETIF_F_SG) diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index e419f486cdb..296071043f5 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -504,7 +504,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) if (rc) { fcoe_insert_wait_queue(lp, skb); if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - fc_pause(lp); + lp->qfull = 1; } return 0; @@ -718,7 +718,7 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) * fcoe_watchdog - fcoe timer callback * @vp: * - * This checks the pending queue length for fcoe and put fcoe to be paused state + * This checks the pending queue length for fcoe and set lport qfull * if the FCOE_MAX_QUEUE_DEPTH is reached. This is done for all fc_lport on the * fcoe_hostlist. * @@ -728,17 +728,17 @@ void fcoe_watchdog(ulong vp) { struct fc_lport *lp; struct fcoe_softc *fc; - int paused = 0; + int qfilled = 0; read_lock(&fcoe_hostlist_lock); list_for_each_entry(fc, &fcoe_hostlist, list) { lp = fc->lp; if (lp) { if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - paused = 1; + qfilled = 1; if (fcoe_check_wait_queue(lp) < FCOE_MAX_QUEUE_DEPTH) { - if (paused) - fc_unpause(lp); + if (qfilled) + lp->qfull = 0; } } } @@ -767,8 +767,7 @@ void fcoe_watchdog(ulong vp) **/ static int fcoe_check_wait_queue(struct fc_lport *lp) { - int rc, unpause = 0; - int paused = 0; + int rc; struct sk_buff *skb; struct fcoe_softc *fc; @@ -776,10 +775,10 @@ static int fcoe_check_wait_queue(struct fc_lport *lp) spin_lock_bh(&fc->fcoe_pending_queue.lock); /* - * is this interface paused? + * if interface pending queue full then set qfull in lport. */ if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - paused = 1; + lp->qfull = 1; if (fc->fcoe_pending_queue.qlen) { while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { spin_unlock_bh(&fc->fcoe_pending_queue.lock); @@ -791,11 +790,9 @@ static int fcoe_check_wait_queue(struct fc_lport *lp) spin_lock_bh(&fc->fcoe_pending_queue.lock); } if (fc->fcoe_pending_queue.qlen < FCOE_MAX_QUEUE_DEPTH) - unpause = 1; + lp->qfull = 0; } spin_unlock_bh(&fc->fcoe_pending_queue.lock); - if ((unpause) && (paused)) - fc_unpause(lp); return fc->fcoe_pending_queue.qlen; } @@ -873,7 +870,7 @@ static int fcoe_device_notification(struct notifier_block *notifier, struct net_device *real_dev = ptr; struct fcoe_softc *fc; struct fcoe_dev_stats *stats; - u16 new_status; + u32 new_link_up; u32 mfs; int rc = NOTIFY_OK; @@ -890,17 +887,15 @@ static int fcoe_device_notification(struct notifier_block *notifier, goto out; } - new_status = lp->link_status; + new_link_up = lp->link_up; switch (event) { case NETDEV_DOWN: case NETDEV_GOING_DOWN: - new_status &= ~FC_LINK_UP; + new_link_up = 0; break; case NETDEV_UP: case NETDEV_CHANGE: - new_status &= ~FC_LINK_UP; - if (!fcoe_link_ok(lp)) - new_status |= FC_LINK_UP; + new_link_up = !fcoe_link_ok(lp); break; case NETDEV_CHANGEMTU: mfs = fc->real_dev->mtu - @@ -908,17 +903,15 @@ static int fcoe_device_notification(struct notifier_block *notifier, sizeof(struct fcoe_crc_eof)); if (mfs >= FC_MIN_MAX_FRAME) fc_set_mfs(lp, mfs); - new_status &= ~FC_LINK_UP; - if (!fcoe_link_ok(lp)) - new_status |= FC_LINK_UP; + new_link_up = !fcoe_link_ok(lp); break; case NETDEV_REGISTER: break; default: FC_DBG("unknown event %ld call", event); } - if (lp->link_status != new_status) { - if ((new_status & FC_LINK_UP) == FC_LINK_UP) + if (lp->link_up != new_link_up) { + if (new_link_up) fc_linkup(lp); else { stats = lp->dev_stats[smp_processor_id()]; diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 404e63ff46b..f440aaca39c 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1621,7 +1621,7 @@ out: static inline int fc_fcp_lport_queue_ready(struct fc_lport *lp) { /* lock ? */ - return (lp->state == LPORT_ST_READY) && (lp->link_status & FC_LINK_UP); + return (lp->state == LPORT_ST_READY) && lp->link_up && !lp->qfull; } /** @@ -1890,7 +1890,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd) lp = shost_priv(sc_cmd->device->host); if (lp->state != LPORT_ST_READY) return rc; - else if (!(lp->link_status & FC_LINK_UP)) + else if (!lp->link_up) return rc; spin_lock_irqsave(lp->host->host_lock, flags); diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 5db223ce3b2..a6ab692f5f5 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -250,7 +250,7 @@ void fc_get_host_port_state(struct Scsi_Host *shost) { struct fc_lport *lp = shost_priv(shost); - if ((lp->link_status & FC_LINK_UP) == FC_LINK_UP) + if (lp->link_up) fc_host_port_state(shost) = FC_PORTSTATE_ONLINE; else fc_host_port_state(shost) = FC_PORTSTATE_OFFLINE; @@ -577,8 +577,8 @@ void fc_linkup(struct fc_lport *lport) fc_host_port_id(lport->host)); mutex_lock(&lport->lp_mutex); - if ((lport->link_status & FC_LINK_UP) != FC_LINK_UP) { - lport->link_status |= FC_LINK_UP; + if (!lport->link_up) { + lport->link_up = 1; if (lport->state == LPORT_ST_RESET) fc_lport_enter_flogi(lport); @@ -597,8 +597,8 @@ void fc_linkdown(struct fc_lport *lport) FC_DEBUG_LPORT("Link is down for port (%6x)\n", fc_host_port_id(lport->host)); - if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP) { - lport->link_status &= ~(FC_LINK_UP); + if (lport->link_up) { + lport->link_up = 0; fc_lport_enter_reset(lport); lport->tt.fcp_cleanup(lport); } @@ -606,30 +606,6 @@ void fc_linkdown(struct fc_lport *lport) } EXPORT_SYMBOL(fc_linkdown); -/** - * fc_pause - Pause the flow of frames - * @lport: The lport to be paused - */ -void fc_pause(struct fc_lport *lport) -{ - mutex_lock(&lport->lp_mutex); - lport->link_status |= FC_PAUSE; - mutex_unlock(&lport->lp_mutex); -} -EXPORT_SYMBOL(fc_pause); - -/** - * fc_unpause - Unpause the flow of frames - * @lport: The lport to be unpaused - */ -void fc_unpause(struct fc_lport *lport) -{ - mutex_lock(&lport->lp_mutex); - lport->link_status &= ~(FC_PAUSE); - mutex_unlock(&lport->lp_mutex); -} -EXPORT_SYMBOL(fc_unpause); - /** * fc_fabric_logoff - Logout of the fabric * @lport: fc_lport pointer to logoff the fabric @@ -977,7 +953,7 @@ static void fc_lport_enter_reset(struct fc_lport *lport) fc_host_fabric_name(lport->host) = 0; fc_host_port_id(lport->host) = 0; - if ((lport->link_status & FC_LINK_UP) == FC_LINK_UP) + if (lport->link_up) fc_lport_enter_flogi(lport); } -- cgit v1.2.3 From 6755db1cd4587084be85f860b7aa7c0cc9d776dc Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Fri, 27 Feb 2009 10:55:02 -0800 Subject: [SCSI] libfc: rport retry on LS_RJT from certain ELS This allows any rport ELS to retry on LS_RJT. The rport error handling would only retry on resource allocation failures and exchange timeouts. I have a target that will occasionally reject PLOGI when we do a quick LOGO/PLOGI. When a critical ELS was rejected, libfc would fail silently leaving the rport in a dead state. The retry count and delay are managed by fc_rport_error_retry. If the retry count is exceeded fc_rport_error will be called. When retrying is not the correct course of action, fc_rport_error can be called directly. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 2 - drivers/scsi/libfc/fc_rport.c | 111 ++++++++++++++++++++++++------------------ 2 files changed, 64 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index dd269e5f953..8c4018956d4 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -32,8 +32,6 @@ #include #include -#define FC_DEF_R_A_TOV (10 * 1000) /* resource allocation timeout */ - /* * fc_exch_debug can be set in debugger or at compile time to get more logs. */ diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 71757593415..600a8fffa94 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -81,6 +81,7 @@ static void fc_rport_recv_logo_req(struct fc_rport *, struct fc_seq *, struct fc_frame *); static void fc_rport_timeout(struct work_struct *); static void fc_rport_error(struct fc_rport *, struct fc_frame *); +static void fc_rport_error_retry(struct fc_rport *, struct fc_frame *); static void fc_rport_work(struct work_struct *); static const char *fc_rport_state_names[] = { @@ -410,57 +411,73 @@ static void fc_rport_timeout(struct work_struct *work) } /** - * fc_rport_error - Handler for any errors + * fc_rport_error - Error handler, called once retries have been exhausted * @rport: The fc_rport object * @fp: The frame pointer * - * If the error was caused by a resource allocation failure - * then wait for half a second and retry, otherwise retry - * immediately. - * * Locking Note: The rport lock is expected to be held before * calling this routine */ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp) { struct fc_rport_libfc_priv *rdata = rport->dd_data; - unsigned long delay = 0; FC_DEBUG_RPORT("Error %ld in state %s, retries %d\n", PTR_ERR(fp), fc_rport_state(rport), rdata->retries); - if (!fp || PTR_ERR(fp) == -FC_EX_TIMEOUT) { - /* - * Memory allocation failure, or the exchange timed out. - * Retry after delay - */ - if (rdata->retries < rdata->local_port->max_retry_count) { - rdata->retries++; - if (!fp) - delay = msecs_to_jiffies(500); - get_device(&rport->dev); - schedule_delayed_work(&rdata->retry_work, delay); - } else { - switch (rdata->rp_state) { - case RPORT_ST_PLOGI: - case RPORT_ST_PRLI: - case RPORT_ST_LOGO: - rdata->event = RPORT_EV_FAILED; - queue_work(rport_event_queue, - &rdata->event_work); - break; - case RPORT_ST_RTV: - fc_rport_enter_ready(rport); - break; - case RPORT_ST_NONE: - case RPORT_ST_READY: - case RPORT_ST_INIT: - break; - } - } + switch (rdata->rp_state) { + case RPORT_ST_PLOGI: + case RPORT_ST_PRLI: + case RPORT_ST_LOGO: + rdata->event = RPORT_EV_FAILED; + queue_work(rport_event_queue, + &rdata->event_work); + break; + case RPORT_ST_RTV: + fc_rport_enter_ready(rport); + break; + case RPORT_ST_NONE: + case RPORT_ST_READY: + case RPORT_ST_INIT: + break; } } +/** + * fc_rport_error_retry - Error handler when retries are desired + * @rport: The fc_rport object + * @fp: The frame pointer + * + * If the error was an exchange timeout retry immediately, + * otherwise wait for E_D_TOV. + * + * Locking Note: The rport lock is expected to be held before + * calling this routine + */ +static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp) +{ + struct fc_rport_libfc_priv *rdata = rport->dd_data; + unsigned long delay = FC_DEF_E_D_TOV; + + /* make sure this isn't an FC_EX_CLOSED error, never retry those */ + if (PTR_ERR(fp) == -FC_EX_CLOSED) + return fc_rport_error(rport, fp); + + if (rdata->retries < rdata->local_port->max_retry_count) { + FC_DEBUG_RPORT("Error %ld in state %s, retrying\n", + PTR_ERR(fp), fc_rport_state(rport)); + rdata->retries++; + /* no additional delay on exchange timeouts */ + if (PTR_ERR(fp) == -FC_EX_TIMEOUT) + delay = 0; + get_device(&rport->dev); + schedule_delayed_work(&rdata->retry_work, delay); + return; + } + + return fc_rport_error(rport, fp); +} + /** * fc_rport_plogi_recv_resp - Handle incoming ELS PLOGI response * @sp: current sequence in the PLOGI exchange @@ -495,7 +512,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); goto err; } @@ -527,7 +544,7 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, else fc_rport_enter_prli(rport); } else - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); out: fc_frame_free(fp); @@ -557,14 +574,14 @@ static void fc_rport_enter_plogi(struct fc_rport *rport) rport->maxframe_size = FC_MIN_MAX_PAYLOAD; fp = fc_frame_alloc(lport, sizeof(struct fc_els_flogi)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } rdata->e_d_tov = lport->e_d_tov; if (!lport->tt.elsct_send(lport, rport, fp, ELS_PLOGI, fc_rport_plogi_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } @@ -604,7 +621,7 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, } if (IS_ERR(fp)) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); goto err; } @@ -662,7 +679,7 @@ static void fc_rport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, rport->port_id); if (IS_ERR(fp)) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); goto err; } @@ -712,13 +729,13 @@ static void fc_rport_enter_prli(struct fc_rport *rport) fp = fc_frame_alloc(lport, sizeof(*pp)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } if (!lport->tt.elsct_send(lport, rport, fp, ELS_PRLI, fc_rport_prli_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } @@ -809,13 +826,13 @@ static void fc_rport_enter_rtv(struct fc_rport *rport) fp = fc_frame_alloc(lport, sizeof(struct fc_els_rtv)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } if (!lport->tt.elsct_send(lport, rport, fp, ELS_RTV, fc_rport_rtv_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } @@ -840,13 +857,13 @@ static void fc_rport_enter_logo(struct fc_rport *rport) fp = fc_frame_alloc(lport, sizeof(struct fc_els_logo)); if (!fp) { - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); return; } if (!lport->tt.elsct_send(lport, rport, fp, ELS_LOGO, fc_rport_logo_resp, rport, lport->e_d_tov)) - fc_rport_error(rport, fp); + fc_rport_error_retry(rport, fp); else get_device(&rport->dev); } -- cgit v1.2.3 From 26d9cab558f901051d0b69b2c445c8588931ce8d Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:55:07 -0800 Subject: [SCSI] libfc: fixed a read IO data integrity issue when a IO data frame lost The fc_fcp_complete_locked detected data underrun in this case and set the FC_DATA_UNDRUN but that was ignored by fc_io_compl for all cases including read underrun. Added code to not to ignore FC_DATA_UNDRUN for read IO and instead suggested scsi-ml to retry cmd to recover from lost data frame. Not sure if it is okay to ignore FC_DATA_UNDRUN for other case, so let code as is for other cases but removed or-ing with zero valued fsp->cdb_status for those cases. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_fcp.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index f440aaca39c..ecc72612c38 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -1810,12 +1810,12 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) sc_cmd->result = DID_ERROR << 16; break; case FC_DATA_UNDRUN: - if (fsp->cdb_status == 0) { + if ((fsp->cdb_status == 0) && !(fsp->req_flags & FC_SRB_READ)) { /* * scsi status is good but transport level - * underrun. for read it should be an error?? + * underrun. */ - sc_cmd->result = (DID_OK << 16) | fsp->cdb_status; + sc_cmd->result = DID_OK << 16; } else { /* * scsi got underrun, this is an error -- cgit v1.2.3 From f7db2c150cf5082cf74555f30a1305938041de80 Mon Sep 17 00:00:00 2001 From: Steve Ma Date: Fri, 27 Feb 2009 10:55:13 -0800 Subject: [SCSI] libfc: exch mgr is freed while lport still retrying sequences When a sequence cannot be delivered to the target, the local port will schedule retries, While this process is in progress, if we destroy the FCoE interface, the fcoe_sw_destroy routine is entered, and the fc_exch_mgr_free(lp->emp) is called. Thus if fc_exch_alloc() is called when retrying the sequence, the mempool_alloc() will fail to allocate the exchange because the mempool of the exchange manager has already been released. This patch is to cancel any pending retry work of the local port before we start to destroy the interface. Also, when resetting the local port, we should also stop the scheduled pending retries. Signed-off-by: Steve Ma Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index a6ab692f5f5..e6ea4f11953 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -619,6 +619,7 @@ int fc_fabric_logoff(struct fc_lport *lport) mutex_lock(&lport->lp_mutex); fc_lport_enter_logo(lport); mutex_unlock(&lport->lp_mutex); + cancel_delayed_work_sync(&lport->retry_work); return 0; } EXPORT_SYMBOL(fc_fabric_logoff); @@ -918,6 +919,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, */ int fc_lport_reset(struct fc_lport *lport) { + cancel_delayed_work_sync(&lport->retry_work); mutex_lock(&lport->lp_mutex); fc_lport_enter_reset(lport); mutex_unlock(&lport->lp_mutex); -- cgit v1.2.3 From 5101ff99f59aefb72e0c96e82aa32048ac9f8425 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:18 -0800 Subject: [SCSI] libfc: Don't violate transport template for rogue port creation Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 6 +++--- drivers/scsi/libfc/fc_lport.c | 4 ++-- drivers/scsi/libfc/fc_rport.c | 3 +++ 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index dd1564c9e04..15e3f840c04 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -430,7 +430,7 @@ static int fc_disc_new_target(struct fc_disc *disc, dp.ids.port_name = ids->port_name; dp.ids.node_name = ids->node_name; dp.ids.roles = ids->roles; - rport = fc_rport_rogue_create(&dp); + rport = lport->tt.rport_create(&dp); } if (!rport) error = -ENOMEM; @@ -617,7 +617,7 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) if ((dp.ids.port_id != fc_host_port_id(lport->host)) && (dp.ids.port_name != lport->wwpn)) { - rport = fc_rport_rogue_create(&dp); + rport = lport->tt.rport_create(&dp); if (rport) { rdata = rport->dd_data; rdata->ops = &fc_disc_rport_ops; @@ -769,7 +769,7 @@ static void fc_disc_single(struct fc_disc *disc, struct fc_disc_port *dp) if (rport) fc_disc_del_target(disc, rport); - new_rport = fc_rport_rogue_create(dp); + new_rport = lport->tt.rport_create(dp); if (new_rport) { rdata = new_rport->dd_data; rdata->ops = &fc_disc_rport_ops; diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index e6ea4f11953..07335ae2947 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -232,7 +232,7 @@ static void fc_lport_ptp_setup(struct fc_lport *lport, lport->ptp_rp = NULL; } - lport->ptp_rp = fc_rport_rogue_create(&dp); + lport->ptp_rp = lport->tt.rport_create(&dp); lport->tt.rport_login(lport->ptp_rp); @@ -1282,7 +1282,7 @@ static void fc_lport_enter_dns(struct fc_lport *lport) fc_lport_state_enter(lport, LPORT_ST_DNS); - rport = fc_rport_rogue_create(&dp); + rport = lport->tt.rport_create(&dp); if (!rport) goto err; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 600a8fffa94..81b3ca18878 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -1271,6 +1271,9 @@ static void fc_rport_flush_queue(void) int fc_rport_init(struct fc_lport *lport) { + if (!lport->tt.rport_create) + lport->tt.rport_create = fc_rport_rogue_create; + if (!lport->tt.rport_login) lport->tt.rport_login = fc_rport_login; -- cgit v1.2.3 From 23f11f9076fcd6ee20c56e413b11f1b5658e3f82 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:23 -0800 Subject: [SCSI] libfc: correct RPORT_TO_PRIV usage We only need to use this macro when assigning a value to rport->dd_data. All other accesses should just use dd_data. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 15e3f840c04..9f4e408bc7f 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -246,7 +246,7 @@ static void fc_disc_recv_rscn_req(struct fc_seq *sp, struct fc_frame *fp, list_del(&dp->peers); rport = lport->tt.rport_lookup(lport, dp->ids.port_id); if (rport) { - rdata = RPORT_TO_PRIV(rport); + rdata = rport->dd_data; list_del(&rdata->peers); lport->tt.rport_logoff(rport); } @@ -453,7 +453,7 @@ static int fc_disc_new_target(struct fc_disc *disc, static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport) { struct fc_lport *lport = disc->lport; - struct fc_rport_libfc_priv *rdata = RPORT_TO_PRIV(rport); + struct fc_rport_libfc_priv *rdata = rport->dd_data; list_del(&rdata->peers); lport->tt.rport_logoff(rport); } -- cgit v1.2.3 From d3b33327cab0c8e9cae2c12d908ca79433c0d1ac Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:29 -0800 Subject: [SCSI] libfc: rename rp to rdata in fc_disc_new_target() Just rename the variable as per our naming convention. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_disc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index 9f4e408bc7f..cfbce893941 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -396,7 +396,7 @@ static int fc_disc_new_target(struct fc_disc *disc, struct fc_rport_identifiers *ids) { struct fc_lport *lport = disc->lport; - struct fc_rport_libfc_priv *rp; + struct fc_rport_libfc_priv *rdata; int error = 0; if (rport && ids->port_name) { @@ -436,9 +436,9 @@ static int fc_disc_new_target(struct fc_disc *disc, error = -ENOMEM; } if (rport) { - rp = rport->dd_data; - rp->ops = &fc_disc_rport_ops; - rp->rp_state = RPORT_ST_INIT; + rdata = rport->dd_data; + rdata->ops = &fc_disc_rport_ops; + rdata->rp_state = RPORT_ST_INIT; lport->tt.rport_login(rport); } } -- cgit v1.2.3 From efaf5c085dd2d31757b0ff7886970dfddd8d1808 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:34 -0800 Subject: [SCSI] libfc: check for err when recv and state is incorrect If we've just created an interface and the an rport is logging in we may have a request on the wire (say PRLI). If we destroy the interface, we'll go through each rport on the disc->rports list and set each rport's state to NONE. Then the lport will reset the EM. The EM reset will send a CLOSED event to the prli_resp() handler which will notice that the state != PRLI. In this case it frees the frame pointer, decrements the refcount and unlocks the rport. The problem is that there isn't a frame in this case. It's just a pointer with an embedded error code. The free causes an Oops. This patch moves the error checking to be before the state checking. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_lport.c | 50 +++++++++++++++++++++---------------------- drivers/scsi/libfc/fc_rport.c | 30 +++++++++++++------------- 2 files changed, 40 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 07335ae2947..c00de2244c7 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -1031,17 +1031,17 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a RFT_ID response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_RFT_ID) { FC_DBG("Received a RFT_ID response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - fh = fc_frame_header_get(fp); ct = fc_frame_payload_get(fp, sizeof(*ct)); @@ -1083,17 +1083,17 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a RPN_ID response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_RPN_ID) { FC_DBG("Received a RPN_ID response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - fh = fc_frame_header_get(fp); ct = fc_frame_payload_get(fp, sizeof(*ct)); if (fh && ct && fh->fh_type == FC_TYPE_CT && @@ -1133,17 +1133,17 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a SCR response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_SCR) { FC_DBG("Received a SCR response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) fc_lport_enter_ready(lport); @@ -1359,17 +1359,17 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a LOGO response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_LOGO) { FC_DBG("Received a LOGO response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) fc_lport_enter_reset(lport); @@ -1443,17 +1443,17 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_LPORT("Received a FLOGI response\n"); + if (IS_ERR(fp)) { + fc_lport_error(lport, fp); + goto err; + } + if (lport->state != LPORT_ST_FLOGI) { FC_DBG("Received a FLOGI response, but in state %s\n", fc_lport_state(lport)); goto out; } - if (IS_ERR(fp)) { - fc_lport_error(lport, fp); - goto err; - } - fh = fc_frame_header_get(fp); did = ntoh24(fh->fh_d_id); if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 81b3ca18878..4f23a9bb15a 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -505,17 +505,17 @@ static void fc_rport_plogi_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a PLOGI response from port (%6x)\n", rport->port_id); + if (IS_ERR(fp)) { + fc_rport_error_retry(rport, fp); + goto err; + } + if (rdata->rp_state != RPORT_ST_PLOGI) { FC_DBG("Received a PLOGI response, but in state %s\n", fc_rport_state(rport)); goto out; } - if (IS_ERR(fp)) { - fc_rport_error_retry(rport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC && (plp = fc_frame_payload_get(fp, sizeof(*plp))) != NULL) { @@ -614,17 +614,17 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a PRLI response from port (%6x)\n", rport->port_id); + if (IS_ERR(fp)) { + fc_rport_error_retry(rport, fp); + goto err; + } + if (rdata->rp_state != RPORT_ST_PRLI) { FC_DBG("Received a PRLI response, but in state %s\n", fc_rport_state(rport)); goto out; } - if (IS_ERR(fp)) { - fc_rport_error_retry(rport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) { pp = fc_frame_payload_get(fp, sizeof(*pp)); @@ -764,17 +764,17 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, FC_DEBUG_RPORT("Received a RTV response from port (%6x)\n", rport->port_id); + if (IS_ERR(fp)) { + fc_rport_error(rport, fp); + goto err; + } + if (rdata->rp_state != RPORT_ST_RTV) { FC_DBG("Received a RTV response, but in state %s\n", fc_rport_state(rport)); goto out; } - if (IS_ERR(fp)) { - fc_rport_error(rport, fp); - goto err; - } - op = fc_frame_payload_op(fp); if (op == ELS_LS_ACC) { struct fc_els_rtv_acc *rtv; -- cgit v1.2.3 From cda56ac29f2d8288d62978272856884d26e0b47b Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Tue, 10 Feb 2009 16:32:33 +0200 Subject: mmc: fix data timeout for SEND_EXT_CSD Commit 0d3e0460f307e84904968aad6cff97bd688583d8 "MMC: CSD and CID timeout values" inadvertently broke the timeout for the MMC command SEND_EXT_CSD. This patch puts it back again. Depending on the characteristics of the controller, this bug may prevent the use of MMC cards. Signed-off-by: Adrian Hunter Signed-off-by: Pierre Ossman --- drivers/mmc/core/mmc_ops.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 9c50e6f1c23..34ce2703d29 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c @@ -248,12 +248,15 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, sg_init_one(&sg, data_buf, len); - /* - * The spec states that CSR and CID accesses have a timeout - * of 64 clock cycles. - */ - data.timeout_ns = 0; - data.timeout_clks = 64; + if (opcode == MMC_SEND_CSD || opcode == MMC_SEND_CID) { + /* + * The spec states that CSR and CID accesses have a timeout + * of 64 clock cycles. + */ + data.timeout_ns = 0; + data.timeout_clks = 64; + } else + mmc_set_data_timeout(&data, card); mmc_wait_for_req(host, &mrq); -- cgit v1.2.3 From 6db6a5f3ae2ca6b874b0fd97ae16fdc9b5cdd6cc Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 9 Mar 2009 10:06:28 -0600 Subject: lguest: fix for CONFIG_SPARSE_IRQ=y Impact: remove lots of lguest boot WARN_ON() when CONFIG_SPARSE_IRQ=y We now need to call irq_to_desc_alloc_cpu() before set_irq_chip_and_handler_name(), but we can't do that from init_IRQ (no kmalloc available). So do it as we use interrupts instead. Also means we only alloc for irqs we use, which was the intent of CONFIG_SPARSE_IRQ anyway. Signed-off-by: Rusty Russell Cc: Ingo Molnar --- drivers/lguest/lguest_device.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index b4d44e571d7..8132533d71f 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -212,6 +212,9 @@ static void lg_notify(struct virtqueue *vq) hcall(LHCALL_NOTIFY, lvq->config.pfn << PAGE_SHIFT, 0, 0); } +/* An extern declaration inside a C file is bad form. Don't do it. */ +extern void lguest_setup_irq(unsigned int irq); + /* This routine finds the first virtqueue described in the configuration of * this device and sets it up. * @@ -266,6 +269,9 @@ static struct virtqueue *lg_find_vq(struct virtio_device *vdev, goto unmap; } + /* Make sure the interrupt is allocated. */ + lguest_setup_irq(lvq->config.irq); + /* Tell the interrupt for this virtqueue to go to the virtio_ring * interrupt handler. */ /* FIXME: We used to have a flag for the Host to tell us we could use -- cgit v1.2.3 From 0796e75503adc6b0a119493ce2e599fb5fd8f96e Mon Sep 17 00:00:00 2001 From: Friedrich Oslage Date: Sun, 8 Mar 2009 20:13:42 -0700 Subject: sunhme: Fix qfe parent detection. Signed-off-by: Friedrich Oslage Signed-off-by: David S. Miller --- drivers/net/sunhme.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index cc4013be5e1..0ff837a9c80 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c @@ -2630,8 +2630,6 @@ static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) int err = -ENODEV; sbus_dp = to_of_device(op->dev.parent)->node; - if (is_qfe) - sbus_dp = to_of_device(op->dev.parent->parent)->node; /* We can match PCI devices too, do not accept those here. */ if (strcmp(sbus_dp->name, "sbus")) -- cgit v1.2.3 From 129f8ae9b1b5be94517da76009ea956e89104ce8 Mon Sep 17 00:00:00 2001 From: Dave Jones Date: Mon, 9 Mar 2009 15:07:33 -0400 Subject: Revert "[CPUFREQ] Disable sysfs ui for p4-clockmod." This reverts commit e088e4c9cdb618675874becb91b2fd581ee707e6. Removing the sysfs interface for p4-clockmod was flagged as a regression in bug 12826. Course of action: - Find out the remaining causes of overheating, and fix them if possible. ACPI should be doing the right thing automatically. If it isn't, we need to fix that. - mark p4-clockmod ui as deprecated - try again with the removal in six months. It's not really feasible to printk about the deprecation, because it needs to happen at all the sysfs entry points, which means adding a lot of strcmp("p4-clockmod".. calls to the core, which.. bleuch. Signed-off-by: Dave Jones --- drivers/cpufreq/cpufreq.c | 51 +++++++++++++++++------------------------------ 1 file changed, 18 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b55cb67435b..d6daf3c507d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -754,11 +754,6 @@ static struct kobj_type ktype_cpufreq = { .release = cpufreq_sysfs_release, }; -static struct kobj_type ktype_empty_cpufreq = { - .sysfs_ops = &sysfs_ops, - .release = cpufreq_sysfs_release, -}; - /** * cpufreq_add_dev - add a CPU device @@ -892,36 +887,26 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); /* prepare interface data */ - if (!cpufreq_driver->hide_interface) { - ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, - &sys_dev->kobj, "cpufreq"); + ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj, + "cpufreq"); + if (ret) + goto err_out_driver_exit; + + /* set up files for this cpu device */ + drv_attr = cpufreq_driver->attr; + while ((drv_attr) && (*drv_attr)) { + ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); if (ret) goto err_out_driver_exit; - - /* set up files for this cpu device */ - drv_attr = cpufreq_driver->attr; - while ((drv_attr) && (*drv_attr)) { - ret = sysfs_create_file(&policy->kobj, - &((*drv_attr)->attr)); - if (ret) - goto err_out_driver_exit; - drv_attr++; - } - if (cpufreq_driver->get) { - ret = sysfs_create_file(&policy->kobj, - &cpuinfo_cur_freq.attr); - if (ret) - goto err_out_driver_exit; - } - if (cpufreq_driver->target) { - ret = sysfs_create_file(&policy->kobj, - &scaling_cur_freq.attr); - if (ret) - goto err_out_driver_exit; - } - } else { - ret = kobject_init_and_add(&policy->kobj, &ktype_empty_cpufreq, - &sys_dev->kobj, "cpufreq"); + drv_attr++; + } + if (cpufreq_driver->get) { + ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); + if (ret) + goto err_out_driver_exit; + } + if (cpufreq_driver->target) { + ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); if (ret) goto err_out_driver_exit; } -- cgit v1.2.3 From 467fc4988986865b5dbcc8cc6a86c9b650cb0c6f Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 10 Mar 2009 06:08:49 +0000 Subject: video: deferred io cleanup fix for sh_mobile_lcdcfb Fix deferred io cleanup patch in the sh_mobile_lcdcfb driver. If probe() fails early the sh_mobile_lcdc_stop() function will be called to clean up deferred io. This patch modifies the code to only call fb_deferred_io_cleanup() after deferred io has been initialized. With this patch applied we no longer hit BUG_ON() inside fb_deferred_io_cleanup(). Triggers on a Migo-R with the SYS QVGA panel board unmounted. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_lcdcfb.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 0e2b8fd24df..2c5d069e5f0 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -446,7 +446,6 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) { struct sh_mobile_lcdc_chan *ch; struct sh_mobile_lcdc_board_cfg *board_cfg; - unsigned long tmp; int k; /* tell the board code to disable the panel */ @@ -456,9 +455,8 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) if (board_cfg->display_off) board_cfg->display_off(board_cfg->board_data); - /* cleanup deferred io if SYS bus */ - tmp = ch->cfg.sys_bus_cfg.deferred_io_msec; - if (ch->ldmt1r_value & (1 << 12) && tmp) { + /* cleanup deferred io if enabled */ + if (ch->info.fbdefio) { fb_deferred_io_cleanup(&ch->info); ch->info.fbdefio = NULL; } -- cgit v1.2.3 From a29b99eccecefe5026713b226f66f117c8837ad5 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Tue, 10 Mar 2009 06:24:21 +0000 Subject: input: add suspend wakeup support to sh_keysc This patch adds wakeup support to the sh_keysc driver. With this feature the ".../power/wakeup" file can be used to enable and disable if the device takes the system out of suspend. Default is enabled. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/input/keyboard/sh_keysc.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index 5c8a1bcf7ca..bf92178644a 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -219,6 +219,8 @@ static int __devinit sh_keysc_probe(struct platform_device *pdev) pdata->scan_timing, priv->iomem_base + KYCR1_OFFS); iowrite16(0, priv->iomem_base + KYOUTDR_OFFS); iowrite16(KYCR2_IRQ_LEVEL, priv->iomem_base + KYCR2_OFFS); + + device_init_wakeup(&pdev->dev, 1); return 0; err5: free_irq(irq, pdev); @@ -253,17 +255,36 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) return 0; } +static int sh_keysc_suspend(struct device *dev) +{ + struct platform_device *pdev; + struct sh_keysc_priv *priv; + unsigned short value; + + pdev = container_of(dev, struct platform_device, dev); + priv = platform_get_drvdata(pdev); + + value = ioread16(priv->iomem_base + KYCR1_OFFS); -#define sh_keysc_suspend NULL -#define sh_keysc_resume NULL + if (device_may_wakeup(dev)) + value |= 0x80; + else + value &= ~0x80; + + iowrite16(value, priv->iomem_base + KYCR1_OFFS); + return 0; +} + +static struct dev_pm_ops sh_keysc_dev_pm_ops = { + .suspend = sh_keysc_suspend, +}; struct platform_driver sh_keysc_device_driver = { .probe = sh_keysc_probe, .remove = __devexit_p(sh_keysc_remove), - .suspend = sh_keysc_suspend, - .resume = sh_keysc_resume, .driver = { .name = "sh_keysc", + .pm = &sh_keysc_dev_pm_ops, } }; -- cgit v1.2.3 From 47a72688fae7298e1ad5fdc9bff7e04b6a549620 Mon Sep 17 00:00:00 2001 From: Adrian McMenamin Date: Wed, 4 Mar 2009 00:31:04 +0000 Subject: mtd: flash mapping support for Dreamcast VMU. This patch adds support for the Sega Dreamcast visual memory unit as a flash mapping. It requires changes in the maple bus driver (posted separately) to support block reads and writes. The VMU is a 'smart' flash device, with a built-in 8-bit controller - for instance there is an erase before a write but it is hidden from the user. But the device's overall behaviour means it works well with the mtd layer and it is appropriate to add it as an mtd mapping. Signed-off-by: Adrian McMenamin Acked-By: David Woodhouse Signed-off-by: Paul Mundt --- drivers/mtd/maps/Kconfig | 12 +- drivers/mtd/maps/Makefile | 1 + drivers/mtd/maps/vmu-flash.c | 832 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 844 insertions(+), 1 deletion(-) create mode 100644 drivers/mtd/maps/vmu-flash.c (limited to 'drivers') diff --git a/drivers/mtd/maps/Kconfig b/drivers/mtd/maps/Kconfig index 043d50fb6ef..729f899a5cd 100644 --- a/drivers/mtd/maps/Kconfig +++ b/drivers/mtd/maps/Kconfig @@ -551,5 +551,15 @@ config MTD_PLATRAM This selection automatically selects the map_ram driver. -endmenu +config MTD_VMU + tristate "Map driver for Dreamcast VMU" + depends on MAPLE + help + This driver enables access to the Dreamcast Visual Memory Unit (VMU). + + Most Dreamcast users will want to say Y here. + To build this as a module select M here, the module will be called + vmu-flash. + +endmenu diff --git a/drivers/mtd/maps/Makefile b/drivers/mtd/maps/Makefile index 6d9ba35caf1..26b28a7a90b 100644 --- a/drivers/mtd/maps/Makefile +++ b/drivers/mtd/maps/Makefile @@ -61,3 +61,4 @@ obj-$(CONFIG_MTD_PLATRAM) += plat-ram.o obj-$(CONFIG_MTD_OMAP_NOR) += omap_nor.o obj-$(CONFIG_MTD_INTEL_VR_NOR) += intel_vr_nor.o obj-$(CONFIG_MTD_BFIN_ASYNC) += bfin-async-flash.o +obj-$(CONFIG_MTD_VMU) += vmu-flash.o diff --git a/drivers/mtd/maps/vmu-flash.c b/drivers/mtd/maps/vmu-flash.c new file mode 100644 index 00000000000..1f73297e777 --- /dev/null +++ b/drivers/mtd/maps/vmu-flash.c @@ -0,0 +1,832 @@ +/* vmu-flash.c + * Driver for SEGA Dreamcast Visual Memory Unit + * + * Copyright (c) Adrian McMenamin 2002 - 2009 + * Copyright (c) Paul Mundt 2001 + * + * Licensed under version 2 of the + * GNU General Public Licence + */ +#include +#include +#include +#include +#include +#include + +struct vmu_cache { + unsigned char *buffer; /* Cache */ + unsigned int block; /* Which block was cached */ + unsigned long jiffies_atc; /* When was it cached? */ + int valid; +}; + +struct mdev_part { + struct maple_device *mdev; + int partition; +}; + +struct vmupart { + u16 user_blocks; + u16 root_block; + u16 numblocks; + char *name; + struct vmu_cache *pcache; +}; + +struct memcard { + u16 tempA; + u16 tempB; + u32 partitions; + u32 blocklen; + u32 writecnt; + u32 readcnt; + u32 removeable; + int partition; + int read; + unsigned char *blockread; + struct vmupart *parts; + struct mtd_info *mtd; +}; + +struct vmu_block { + unsigned int num; /* block number */ + unsigned int ofs; /* block offset */ +}; + +static struct vmu_block *ofs_to_block(unsigned long src_ofs, + struct mtd_info *mtd, int partition) +{ + struct vmu_block *vblock; + struct maple_device *mdev; + struct memcard *card; + struct mdev_part *mpart; + int num; + + mpart = mtd->priv; + mdev = mpart->mdev; + card = maple_get_drvdata(mdev); + + if (src_ofs >= card->parts[partition].numblocks * card->blocklen) + goto failed; + + num = src_ofs / card->blocklen; + if (num > card->parts[partition].numblocks) + goto failed; + + vblock = kmalloc(sizeof(struct vmu_block), GFP_KERNEL); + if (!vblock) + goto failed; + + vblock->num = num; + vblock->ofs = src_ofs % card->blocklen; + return vblock; + +failed: + return NULL; +} + +/* Maple bus callback function for reads */ +static void vmu_blockread(struct mapleq *mq) +{ + struct maple_device *mdev; + struct memcard *card; + + mdev = mq->dev; + card = maple_get_drvdata(mdev); + /* copy the read in data */ + + if (unlikely(!card->blockread)) + return; + + memcpy(card->blockread, mq->recvbuf->buf + 12, + card->blocklen/card->readcnt); + +} + +/* Interface with maple bus to read blocks + * caching the results so that other parts + * of the driver can access block reads */ +static int maple_vmu_read_block(unsigned int num, unsigned char *buf, + struct mtd_info *mtd) +{ + struct memcard *card; + struct mdev_part *mpart; + struct maple_device *mdev; + int partition, error = 0, x, wait; + unsigned char *blockread = NULL; + struct vmu_cache *pcache; + __be32 sendbuf; + + mpart = mtd->priv; + mdev = mpart->mdev; + partition = mpart->partition; + card = maple_get_drvdata(mdev); + pcache = card->parts[partition].pcache; + pcache->valid = 0; + + /* prepare the cache for this block */ + if (!pcache->buffer) { + pcache->buffer = kmalloc(card->blocklen, GFP_KERNEL); + if (!pcache->buffer) { + dev_err(&mdev->dev, "VMU at (%d, %d) - read fails due" + " to lack of memory\n", mdev->port, + mdev->unit); + error = -ENOMEM; + goto outB; + } + } + + /* + * Reads may be phased - again the hardware spec + * supports this - though may not be any devices in + * the wild that implement it, but we will here + */ + for (x = 0; x < card->readcnt; x++) { + sendbuf = cpu_to_be32(partition << 24 | x << 16 | num); + + if (atomic_read(&mdev->busy) == 1) { + wait_event_interruptible_timeout(mdev->maple_wait, + atomic_read(&mdev->busy) == 0, HZ); + if (atomic_read(&mdev->busy) == 1) { + dev_notice(&mdev->dev, "VMU at (%d, %d)" + " is busy\n", mdev->port, mdev->unit); + error = -EAGAIN; + goto outB; + } + } + + atomic_set(&mdev->busy, 1); + blockread = kmalloc(card->blocklen/card->readcnt, GFP_KERNEL); + if (!blockread) { + error = -ENOMEM; + atomic_set(&mdev->busy, 0); + goto outB; + } + card->blockread = blockread; + + maple_getcond_callback(mdev, vmu_blockread, 0, + MAPLE_FUNC_MEMCARD); + error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD, + MAPLE_COMMAND_BREAD, 2, &sendbuf); + /* Very long timeouts seem to be needed when box is stressed */ + wait = wait_event_interruptible_timeout(mdev->maple_wait, + (atomic_read(&mdev->busy) == 0 || + atomic_read(&mdev->busy) == 2), HZ * 3); + /* + * MTD layer does not handle hotplugging well + * so have to return errors when VMU is unplugged + * in the middle of a read (busy == 2) + */ + if (error || atomic_read(&mdev->busy) == 2) { + if (atomic_read(&mdev->busy) == 2) + error = -ENXIO; + atomic_set(&mdev->busy, 0); + card->blockread = NULL; + goto outA; + } + if (wait == 0 || wait == -ERESTARTSYS) { + card->blockread = NULL; + atomic_set(&mdev->busy, 0); + error = -EIO; + list_del_init(&(mdev->mq->list)); + kfree(mdev->mq->sendbuf); + mdev->mq->sendbuf = NULL; + if (wait == -ERESTARTSYS) { + dev_warn(&mdev->dev, "VMU read on (%d, %d)" + " interrupted on block 0x%X\n", + mdev->port, mdev->unit, num); + } else + dev_notice(&mdev->dev, "VMU read on (%d, %d)" + " timed out on block 0x%X\n", + mdev->port, mdev->unit, num); + goto outA; + } + + memcpy(buf + (card->blocklen/card->readcnt) * x, blockread, + card->blocklen/card->readcnt); + + memcpy(pcache->buffer + (card->blocklen/card->readcnt) * x, + card->blockread, card->blocklen/card->readcnt); + card->blockread = NULL; + pcache->block = num; + pcache->jiffies_atc = jiffies; + pcache->valid = 1; + kfree(blockread); + } + + return error; + +outA: + kfree(blockread); +outB: + return error; +} + +/* communicate with maple bus for phased writing */ +static int maple_vmu_write_block(unsigned int num, const unsigned char *buf, + struct mtd_info *mtd) +{ + struct memcard *card; + struct mdev_part *mpart; + struct maple_device *mdev; + int partition, error, locking, x, phaselen, wait; + __be32 *sendbuf; + + mpart = mtd->priv; + mdev = mpart->mdev; + partition = mpart->partition; + card = maple_get_drvdata(mdev); + + phaselen = card->blocklen/card->writecnt; + + sendbuf = kmalloc(phaselen + 4, GFP_KERNEL); + if (!sendbuf) { + error = -ENOMEM; + goto fail_nosendbuf; + } + for (x = 0; x < card->writecnt; x++) { + sendbuf[0] = cpu_to_be32(partition << 24 | x << 16 | num); + memcpy(&sendbuf[1], buf + phaselen * x, phaselen); + /* wait until the device is not busy doing something else + * or 1 second - which ever is longer */ + if (atomic_read(&mdev->busy) == 1) { + wait_event_interruptible_timeout(mdev->maple_wait, + atomic_read(&mdev->busy) == 0, HZ); + if (atomic_read(&mdev->busy) == 1) { + error = -EBUSY; + dev_notice(&mdev->dev, "VMU write at (%d, %d)" + "failed - device is busy\n", + mdev->port, mdev->unit); + goto fail_nolock; + } + } + atomic_set(&mdev->busy, 1); + + locking = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD, + MAPLE_COMMAND_BWRITE, phaselen / 4 + 2, sendbuf); + wait = wait_event_interruptible_timeout(mdev->maple_wait, + atomic_read(&mdev->busy) == 0, HZ/10); + if (locking) { + error = -EIO; + atomic_set(&mdev->busy, 0); + goto fail_nolock; + } + if (atomic_read(&mdev->busy) == 2) { + atomic_set(&mdev->busy, 0); + } else if (wait == 0 || wait == -ERESTARTSYS) { + error = -EIO; + dev_warn(&mdev->dev, "Write at (%d, %d) of block" + " 0x%X at phase %d failed: could not" + " communicate with VMU", mdev->port, + mdev->unit, num, x); + atomic_set(&mdev->busy, 0); + kfree(mdev->mq->sendbuf); + mdev->mq->sendbuf = NULL; + list_del_init(&(mdev->mq->list)); + goto fail_nolock; + } + } + kfree(sendbuf); + + return card->blocklen; + +fail_nolock: + kfree(sendbuf); +fail_nosendbuf: + dev_err(&mdev->dev, "VMU (%d, %d): write failed\n", mdev->port, + mdev->unit); + return error; +} + +/* mtd function to simulate reading byte by byte */ +static unsigned char vmu_flash_read_char(unsigned long ofs, int *retval, + struct mtd_info *mtd) +{ + struct vmu_block *vblock; + struct memcard *card; + struct mdev_part *mpart; + struct maple_device *mdev; + unsigned char *buf, ret; + int partition, error; + + mpart = mtd->priv; + mdev = mpart->mdev; + partition = mpart->partition; + card = maple_get_drvdata(mdev); + *retval = 0; + + buf = kmalloc(card->blocklen, GFP_KERNEL); + if (!buf) { + *retval = 1; + ret = -ENOMEM; + goto finish; + } + + vblock = ofs_to_block(ofs, mtd, partition); + if (!vblock) { + *retval = 3; + ret = -ENOMEM; + goto out_buf; + } + + error = maple_vmu_read_block(vblock->num, buf, mtd); + if (error) { + ret = error; + *retval = 2; + goto out_vblock; + } + + ret = buf[vblock->ofs]; + +out_vblock: + kfree(vblock); +out_buf: + kfree(buf); +finish: + return ret; +} + +/* mtd higher order function to read flash */ +static int vmu_flash_read(struct mtd_info *mtd, loff_t from, size_t len, + size_t *retlen, u_char *buf) +{ + struct maple_device *mdev; + struct memcard *card; + struct mdev_part *mpart; + struct vmu_cache *pcache; + struct vmu_block *vblock; + int index = 0, retval, partition, leftover, numblocks; + unsigned char cx; + + if (len < 1) + return -EIO; + + mpart = mtd->priv; + mdev = mpart->mdev; + partition = mpart->partition; + card = maple_get_drvdata(mdev); + + numblocks = card->parts[partition].numblocks; + if (from + len > numblocks * card->blocklen) + len = numblocks * card->blocklen - from; + if (len == 0) + return -EIO; + /* Have we cached this bit already? */ + pcache = card->parts[partition].pcache; + do { + vblock = ofs_to_block(from + index, mtd, partition); + if (!vblock) + return -ENOMEM; + /* Have we cached this and is the cache valid and timely? */ + if (pcache->valid && + time_before(jiffies, pcache->jiffies_atc + HZ) && + (pcache->block == vblock->num)) { + /* we have cached it, so do necessary copying */ + leftover = card->blocklen - vblock->ofs; + if (vblock->ofs + len - index < card->blocklen) { + /* only a bit of this block to copy */ + memcpy(buf + index, + pcache->buffer + vblock->ofs, + len - index); + index = len; + } else { + /* otherwise copy remainder of whole block */ + memcpy(buf + index, pcache->buffer + + vblock->ofs, leftover); + index += leftover; + } + } else { + /* + * Not cached so read one byte - + * but cache the rest of the block + */ + cx = vmu_flash_read_char(from + index, &retval, mtd); + if (retval) { + *retlen = index; + kfree(vblock); + return cx; + } + memset(buf + index, cx, 1); + index++; + } + kfree(vblock); + } while (len > index); + *retlen = index; + + return 0; +} + +static int vmu_flash_write(struct mtd_info *mtd, loff_t to, size_t len, + size_t *retlen, const u_char *buf) +{ + struct maple_device *mdev; + struct memcard *card; + struct mdev_part *mpart; + int index = 0, partition, error = 0, numblocks; + struct vmu_cache *pcache; + struct vmu_block *vblock; + unsigned char *buffer; + + mpart = mtd->priv; + mdev = mpart->mdev; + partition = mpart->partition; + card = maple_get_drvdata(mdev); + + /* simple sanity checks */ + if (len < 1) { + error = -EIO; + goto failed; + } + numblocks = card->parts[partition].numblocks; + if (to + len > numblocks * card->blocklen) + len = numblocks * card->blocklen - to; + if (len == 0) { + error = -EIO; + goto failed; + } + + vblock = ofs_to_block(to, mtd, partition); + if (!vblock) { + error = -ENOMEM; + goto failed; + } + + buffer = kmalloc(card->blocklen, GFP_KERNEL); + if (!buffer) { + error = -ENOMEM; + goto fail_buffer; + } + + do { + /* Read in the block we are to write to */ + error = maple_vmu_read_block(vblock->num, buffer, mtd); + if (error) + goto fail_io; + + do { + buffer[vblock->ofs] = buf[index]; + vblock->ofs++; + index++; + if (index >= len) + break; + } while (vblock->ofs < card->blocklen); + + /* write out new buffer */ + error = maple_vmu_write_block(vblock->num, buffer, mtd); + /* invalidate the cache */ + pcache = card->parts[partition].pcache; + pcache->valid = 0; + + if (error != card->blocklen) + goto fail_io; + + vblock->num++; + vblock->ofs = 0; + } while (len > index); + + kfree(buffer); + *retlen = index; + kfree(vblock); + return 0; + +fail_io: + kfree(buffer); +fail_buffer: + kfree(vblock); +failed: + dev_err(&mdev->dev, "VMU write failing with error %d\n", error); + return error; +} + +static void vmu_flash_sync(struct mtd_info *mtd) +{ + /* Do nothing here */ +} + +/* Maple bus callback function to recursively query hardware details */ +static void vmu_queryblocks(struct mapleq *mq) +{ + struct maple_device *mdev; + unsigned short *res; + struct memcard *card; + __be32 partnum; + struct vmu_cache *pcache; + struct mdev_part *mpart; + struct mtd_info *mtd_cur; + struct vmupart *part_cur; + int error; + + mdev = mq->dev; + card = maple_get_drvdata(mdev); + res = (unsigned short *) (mq->recvbuf->buf); + card->tempA = res[12]; + card->tempB = res[6]; + + dev_info(&mdev->dev, "VMU device at partition %d has %d user " + "blocks with a root block at %d\n", card->partition, + card->tempA, card->tempB); + + part_cur = &card->parts[card->partition]; + part_cur->user_blocks = card->tempA; + part_cur->root_block = card->tempB; + part_cur->numblocks = card->tempB + 1; + part_cur->name = kmalloc(12, GFP_KERNEL); + if (!part_cur->name) + goto fail_name; + + sprintf(part_cur->name, "vmu%d.%d.%d", + mdev->port, mdev->unit, card->partition); + mtd_cur = &card->mtd[card->partition]; + mtd_cur->name = part_cur->name; + mtd_cur->type = 8; + mtd_cur->flags = MTD_WRITEABLE|MTD_NO_ERASE; + mtd_cur->size = part_cur->numblocks * card->blocklen; + mtd_cur->erasesize = card->blocklen; + mtd_cur->write = vmu_flash_write; + mtd_cur->read = vmu_flash_read; + mtd_cur->sync = vmu_flash_sync; + mtd_cur->writesize = card->blocklen; + + mpart = kmalloc(sizeof(struct mdev_part), GFP_KERNEL); + if (!mpart) + goto fail_mpart; + + mpart->mdev = mdev; + mpart->partition = card->partition; + mtd_cur->priv = mpart; + mtd_cur->owner = THIS_MODULE; + + pcache = kzalloc(sizeof(struct vmu_cache), GFP_KERNEL); + if (!pcache) + goto fail_cache_create; + part_cur->pcache = pcache; + + error = add_mtd_device(mtd_cur); + if (error) + goto fail_mtd_register; + + maple_getcond_callback(mdev, NULL, 0, + MAPLE_FUNC_MEMCARD); + + /* + * Set up a recursive call to the (probably theoretical) + * second or more partition + */ + if (++card->partition < card->partitions) { + partnum = cpu_to_be32(card->partition << 24); + maple_getcond_callback(mdev, vmu_queryblocks, 0, + MAPLE_FUNC_MEMCARD); + maple_add_packet(mdev, MAPLE_FUNC_MEMCARD, + MAPLE_COMMAND_GETMINFO, 2, &partnum); + } + return; + +fail_mtd_register: + dev_err(&mdev->dev, "Could not register maple device at (%d, %d)" + "error is 0x%X\n", mdev->port, mdev->unit, error); + for (error = 0; error <= card->partition; error++) { + kfree(((card->parts)[error]).pcache); + ((card->parts)[error]).pcache = NULL; + } +fail_cache_create: +fail_mpart: + for (error = 0; error <= card->partition; error++) { + kfree(((card->mtd)[error]).priv); + ((card->mtd)[error]).priv = NULL; + } + maple_getcond_callback(mdev, NULL, 0, + MAPLE_FUNC_MEMCARD); + kfree(part_cur->name); +fail_name: + return; +} + +/* Handles very basic info about the flash, queries for details */ +static int __devinit vmu_connect(struct maple_device *mdev) +{ + unsigned long test_flash_data, basic_flash_data; + int c, error; + struct memcard *card; + u32 partnum = 0; + + test_flash_data = be32_to_cpu(mdev->devinfo.function); + /* Need to count how many bits are set - to find out which + * function_data element has details of the memory card: + * using Brian Kernighan's/Peter Wegner's method */ + for (c = 0; test_flash_data; c++) + test_flash_data &= test_flash_data - 1; + + basic_flash_data = be32_to_cpu(mdev->devinfo.function_data[c - 1]); + + card = kmalloc(sizeof(struct memcard), GFP_KERNEL); + if (!card) { + error = ENOMEM; + goto fail_nomem; + } + + card->partitions = (basic_flash_data >> 24 & 0xFF) + 1; + card->blocklen = ((basic_flash_data >> 16 & 0xFF) + 1) << 5; + card->writecnt = basic_flash_data >> 12 & 0xF; + card->readcnt = basic_flash_data >> 8 & 0xF; + card->removeable = basic_flash_data >> 7 & 1; + + card->partition = 0; + + /* + * Not sure there are actually any multi-partition devices in the + * real world, but the hardware supports them, so, so will we + */ + card->parts = kmalloc(sizeof(struct vmupart) * card->partitions, + GFP_KERNEL); + if (!card->parts) { + error = -ENOMEM; + goto fail_partitions; + } + + card->mtd = kmalloc(sizeof(struct mtd_info) * card->partitions, + GFP_KERNEL); + if (!card->mtd) { + error = -ENOMEM; + goto fail_mtd_info; + } + + maple_set_drvdata(mdev, card); + + /* + * We want to trap meminfo not get cond + * so set interval to zero, but rely on maple bus + * driver to pass back the results of the meminfo + */ + maple_getcond_callback(mdev, vmu_queryblocks, 0, + MAPLE_FUNC_MEMCARD); + + /* Make sure we are clear to go */ + if (atomic_read(&mdev->busy) == 1) { + wait_event_interruptible_timeout(mdev->maple_wait, + atomic_read(&mdev->busy) == 0, HZ); + if (atomic_read(&mdev->busy) == 1) { + dev_notice(&mdev->dev, "VMU at (%d, %d) is busy\n", + mdev->port, mdev->unit); + error = -EAGAIN; + goto fail_device_busy; + } + } + + atomic_set(&mdev->busy, 1); + + /* + * Set up the minfo call: vmu_queryblocks will handle + * the information passed back + */ + error = maple_add_packet(mdev, MAPLE_FUNC_MEMCARD, + MAPLE_COMMAND_GETMINFO, 2, &partnum); + if (error) { + dev_err(&mdev->dev, "Could not lock VMU at (%d, %d)" + " error is 0x%X\n", mdev->port, mdev->unit, error); + goto fail_mtd_info; + } + return 0; + +fail_device_busy: + kfree(card->mtd); +fail_mtd_info: + kfree(card->parts); +fail_partitions: + kfree(card); +fail_nomem: + return error; +} + +static void __devexit vmu_disconnect(struct maple_device *mdev) +{ + struct memcard *card; + struct mdev_part *mpart; + int x; + + mdev->callback = NULL; + card = maple_get_drvdata(mdev); + for (x = 0; x < card->partitions; x++) { + mpart = ((card->mtd)[x]).priv; + mpart->mdev = NULL; + del_mtd_device(&((card->mtd)[x])); + kfree(((card->parts)[x]).name); + } + kfree(card->parts); + kfree(card->mtd); + kfree(card); +} + +/* Callback to handle eccentricities of both mtd subsystem + * and general flakyness of Dreamcast VMUs + */ +static int vmu_can_unload(struct maple_device *mdev) +{ + struct memcard *card; + int x; + struct mtd_info *mtd; + + card = maple_get_drvdata(mdev); + for (x = 0; x < card->partitions; x++) { + mtd = &((card->mtd)[x]); + if (mtd->usecount > 0) + return 0; + } + return 1; +} + +#define ERRSTR "VMU at (%d, %d) file error -" + +static void vmu_file_error(struct maple_device *mdev, void *recvbuf) +{ + enum maple_file_errors error = ((int *)recvbuf)[1]; + + switch (error) { + + case MAPLE_FILEERR_INVALID_PARTITION: + dev_notice(&mdev->dev, ERRSTR " invalid partition number\n", + mdev->port, mdev->unit); + break; + + case MAPLE_FILEERR_PHASE_ERROR: + dev_notice(&mdev->dev, ERRSTR " phase error\n", + mdev->port, mdev->unit); + break; + + case MAPLE_FILEERR_INVALID_BLOCK: + dev_notice(&mdev->dev, ERRSTR " invalid block number\n", + mdev->port, mdev->unit); + break; + + case MAPLE_FILEERR_WRITE_ERROR: + dev_notice(&mdev->dev, ERRSTR " write error\n", + mdev->port, mdev->unit); + break; + + case MAPLE_FILEERR_INVALID_WRITE_LENGTH: + dev_notice(&mdev->dev, ERRSTR " invalid write length\n", + mdev->port, mdev->unit); + break; + + case MAPLE_FILEERR_BAD_CRC: + dev_notice(&mdev->dev, ERRSTR " bad CRC\n", + mdev->port, mdev->unit); + break; + + default: + dev_notice(&mdev->dev, ERRSTR " 0x%X\n", + mdev->port, mdev->unit, error); + } +} + + +static int __devinit probe_maple_vmu(struct device *dev) +{ + int error; + struct maple_device *mdev = to_maple_dev(dev); + struct maple_driver *mdrv = to_maple_driver(dev->driver); + + mdev->can_unload = vmu_can_unload; + mdev->fileerr_handler = vmu_file_error; + mdev->driver = mdrv; + + error = vmu_connect(mdev); + if (error) + return error; + + return 0; +} + +static int __devexit remove_maple_vmu(struct device *dev) +{ + struct maple_device *mdev = to_maple_dev(dev); + + vmu_disconnect(mdev); + return 0; +} + +static struct maple_driver vmu_flash_driver = { + .function = MAPLE_FUNC_MEMCARD, + .drv = { + .name = "Dreamcast_visual_memory", + .probe = probe_maple_vmu, + .remove = __devexit_p(remove_maple_vmu), + }, +}; + +static int __init vmu_flash_map_init(void) +{ + return maple_driver_register(&vmu_flash_driver); +} + +static void __exit vmu_flash_map_exit(void) +{ + maple_driver_unregister(&vmu_flash_driver); +} + +module_init(vmu_flash_map_init); +module_exit(vmu_flash_map_exit); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Adrian McMenamin"); +MODULE_DESCRIPTION("Flash mapping for Sega Dreamcast visual memory"); -- cgit v1.2.3 From 34f42a070fc98f5dc07e9fa2338b7b8d1dc347eb Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:45 -0800 Subject: [SCSI] libfc, fcoe: Fix kerneldoc comments 1) Added '()' for function names in kerneldoc comments 2) Changed comment bookends from '**/' to '*/'. The comment on the the mailing list was that '**/' "is consistently unconventional. Not wrong, just odd." The Documentation/kernel-doc-nano-HOWTO.txt states that kerneldoc comment blocks should end with '**/' but most (if not all) instance I found under drivers/scsi/ were only using the '*/' so I converted to that style. 3) Removed incorrect linebreaks in kerneldoc comments where found 4) Removed a few unnecessary blank comment lines in kerneldoc comment blocks Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fc_transport_fcoe.c | 77 ++++++++-------- drivers/scsi/fcoe/fcoe_sw.c | 42 ++++----- drivers/scsi/fcoe/libfcoe.c | 162 +++++++++++++++++----------------- drivers/scsi/libfc/fc_disc.c | 45 +++++----- drivers/scsi/libfc/fc_fcp.c | 46 +++++----- drivers/scsi/libfc/fc_lport.c | 77 ++++++++-------- drivers/scsi/libfc/fc_rport.c | 46 +++++----- 7 files changed, 245 insertions(+), 250 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c index bf7fe6fc082..0eea4c434c3 100644 --- a/drivers/scsi/fcoe/fc_transport_fcoe.c +++ b/drivers/scsi/fcoe/fc_transport_fcoe.c @@ -33,19 +33,19 @@ static LIST_HEAD(fcoe_transports); static DEFINE_MUTEX(fcoe_transports_lock); /** - * fcoe_transport_default - returns ptr to the default transport fcoe_sw - **/ + * fcoe_transport_default() - Returns ptr to the default transport fcoe_sw + */ struct fcoe_transport *fcoe_transport_default(void) { return &fcoe_sw_transport; } /** - * fcoe_transport_to_pcidev - get the pci dev from a netdev + * fcoe_transport_to_pcidev() - get the pci dev from a netdev * @netdev: the netdev that pci dev will be retrived from * * Returns: NULL or the corrsponding pci_dev - **/ + */ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) { if (!netdev->dev.parent) @@ -54,16 +54,14 @@ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) } /** - * fcoe_transport_device_lookup - find out netdev is managed by the - * transport - * assign a transport to a device + * fcoe_transport_device_lookup() - Lookup a transport * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ static struct fcoe_transport_internal *fcoe_transport_device_lookup( struct fcoe_transport *t, struct net_device *netdev) { @@ -81,14 +79,14 @@ static struct fcoe_transport_internal *fcoe_transport_device_lookup( return NULL; } /** - * fcoe_transport_device_add - assign a transport to a device + * fcoe_transport_device_add() - Assign a transport to a device * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ static int fcoe_transport_device_add(struct fcoe_transport *t, struct net_device *netdev) { @@ -123,14 +121,14 @@ static int fcoe_transport_device_add(struct fcoe_transport *t, } /** - * fcoe_transport_device_remove - remove a device from its transport + * fcoe_transport_device_remove() - Remove a device from its transport * @netdev: the netdev the transport to be attached to * - * this removes the device from the transport so the given transport will + * This removes the device from the transport so the given transport will * not manage this device any more * * Returns: 0 for success - **/ + */ static int fcoe_transport_device_remove(struct fcoe_transport *t, struct net_device *netdev) { @@ -155,13 +153,13 @@ static int fcoe_transport_device_remove(struct fcoe_transport *t, } /** - * fcoe_transport_device_remove_all - remove all from transport devlist + * fcoe_transport_device_remove_all() - Remove all from transport devlist * - * this removes the device from the transport so the given transport will + * This removes the device from the transport so the given transport will * not manage this device any more * * Returns: 0 for success - **/ + */ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) { struct fcoe_transport_internal *ti, *tmp; @@ -175,16 +173,16 @@ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) } /** - * fcoe_transport_match - use the bus device match function to match the hw - * @t: the fcoe transport - * @netdev: + * fcoe_transport_match() - Use the bus device match function to match the hw + * @t: The fcoe transport to check + * @netdev: The netdev to match against * - * This function is used to check if the givne transport wants to manage the + * This function is used to check if the given transport wants to manage the * input netdev. if the transports implements the match function, it will be * called, o.w. we just compare the pci vendor and device id. * * Returns: true for match up - **/ + */ static bool fcoe_transport_match(struct fcoe_transport *t, struct net_device *netdev) { @@ -210,15 +208,15 @@ static bool fcoe_transport_match(struct fcoe_transport *t, } /** - * fcoe_transport_lookup - check if the transport is already registered + * fcoe_transport_lookup() - Check if the transport is already registered * @t: the transport to be looked up * * This compares the parent device (pci) vendor and device id * * Returns: NULL if not found * - * TODO - return default sw transport if no other transport is found - **/ + * TODO: return default sw transport if no other transport is found + */ static struct fcoe_transport *fcoe_transport_lookup( struct net_device *netdev) { @@ -239,11 +237,11 @@ static struct fcoe_transport *fcoe_transport_lookup( } /** - * fcoe_transport_register - adds a fcoe transport to the fcoe transports list + * fcoe_transport_register() - Adds a fcoe transport to the fcoe transports list * @t: ptr to the fcoe transport to be added * * Returns: 0 for success - **/ + */ int fcoe_transport_register(struct fcoe_transport *t) { struct fcoe_transport *tt; @@ -269,11 +267,11 @@ int fcoe_transport_register(struct fcoe_transport *t) EXPORT_SYMBOL_GPL(fcoe_transport_register); /** - * fcoe_transport_unregister - remove the tranport fro the fcoe transports list + * fcoe_transport_unregister() - Remove the tranport fro the fcoe transports list * @t: ptr to the fcoe transport to be removed * * Returns: 0 for success - **/ + */ int fcoe_transport_unregister(struct fcoe_transport *t) { struct fcoe_transport *tt, *tmp; @@ -294,8 +292,8 @@ int fcoe_transport_unregister(struct fcoe_transport *t) } EXPORT_SYMBOL_GPL(fcoe_transport_unregister); -/* - * fcoe_load_transport_driver - load an offload driver by alias name +/** + * fcoe_load_transport_driver() - Load an offload driver by alias name * @netdev: the target net device * * Requests for an offload driver module as the fcoe transport, if fails, it @@ -307,7 +305,7 @@ EXPORT_SYMBOL_GPL(fcoe_transport_unregister); * 3. pure hw fcoe hba may not have netdev * * Returns: 0 for success - **/ + */ int fcoe_load_transport_driver(struct net_device *netdev) { struct pci_dev *pci; @@ -335,14 +333,14 @@ int fcoe_load_transport_driver(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_load_transport_driver); /** - * fcoe_transport_attach - load transport to fcoe + * fcoe_transport_attach() - Load transport to fcoe * @netdev: the netdev the transport to be attached to * * This will look for existing offload driver, if not found, it falls back to * the default sw hba (fcoe_sw) as its fcoe transport. * * Returns: 0 for success - **/ + */ int fcoe_transport_attach(struct net_device *netdev) { struct fcoe_transport *t; @@ -373,11 +371,11 @@ int fcoe_transport_attach(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_transport_attach); /** - * fcoe_transport_release - unload transport from fcoe + * fcoe_transport_release() - Unload transport from fcoe * @netdev: the net device on which fcoe is to be released * * Returns: 0 for success - **/ + */ int fcoe_transport_release(struct net_device *netdev) { struct fcoe_transport *t; @@ -410,12 +408,12 @@ int fcoe_transport_release(struct net_device *netdev) EXPORT_SYMBOL_GPL(fcoe_transport_release); /** - * fcoe_transport_init - initializes fcoe transport layer + * fcoe_transport_init() - Initializes fcoe transport layer * * This prepares for the fcoe transport layer * * Returns: none - **/ + */ int __init fcoe_transport_init(void) { INIT_LIST_HEAD(&fcoe_transports); @@ -424,12 +422,13 @@ int __init fcoe_transport_init(void) } /** - * fcoe_transport_exit - cleans up the fcoe transport layer + * fcoe_transport_exit() - Cleans up the fcoe transport layer + * * This cleans up the fcoe transport layer. removing any transport on the list, * note that the transport destroy func is not called here. * * Returns: none - **/ + */ int __exit fcoe_transport_exit(void) { struct fcoe_transport *t, *tmp; diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index cf83675a0fb..007d1fbae80 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -104,13 +104,12 @@ static struct scsi_host_template fcoe_sw_shost_template = { .max_sectors = 0xffff, }; -/* - * fcoe_sw_lport_config - sets up the fc_lport +/** + * fcoe_sw_lport_config() - sets up the fc_lport * @lp: ptr to the fc_lport * @shost: ptr to the parent scsi host * * Returns: 0 for success - * */ static int fcoe_sw_lport_config(struct fc_lport *lp) { @@ -137,16 +136,14 @@ static int fcoe_sw_lport_config(struct fc_lport *lp) return 0; } -/* - * fcoe_sw_netdev_config - sets up fcoe_softc for lport and network - * related properties +/** + * fcoe_sw_netdev_config() - Set up netdev for SW FCoE * @lp : ptr to the fc_lport * @netdev : ptr to the associated netdevice struct * * Must be called after fcoe_sw_lport_config() as it will use lport mutex * * Returns : 0 for success - * */ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) { @@ -224,16 +221,15 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) return 0; } -/* - * fcoe_sw_shost_config - sets up fc_lport->host +/** + * fcoe_sw_shost_config() - Sets up fc_lport->host * @lp : ptr to the fc_lport * @shost : ptr to the associated scsi host * @dev : device associated to scsi host * - * Must be called after fcoe_sw_lport_config) and fcoe_sw_netdev_config() + * Must be called after fcoe_sw_lport_config() and fcoe_sw_netdev_config() * * Returns : 0 for success - * */ static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, struct device *dev) @@ -261,8 +257,8 @@ static int fcoe_sw_shost_config(struct fc_lport *lp, struct Scsi_Host *shost, return 0; } -/* - * fcoe_sw_em_config - allocates em for this lport +/** + * fcoe_sw_em_config() - allocates em for this lport * @lp: the port that em is to allocated for * * Returns : 0 on success @@ -279,8 +275,8 @@ static inline int fcoe_sw_em_config(struct fc_lport *lp) return 0; } -/* - * fcoe_sw_destroy - FCoE software HBA tear-down function +/** + * fcoe_sw_destroy() - FCoE software HBA tear-down function * @netdev: ptr to the associated net_device * * Returns: 0 if link is OK for use by FCoE. @@ -353,8 +349,8 @@ static struct libfc_function_template fcoe_sw_libfc_fcn_templ = { .frame_send = fcoe_xmit, }; -/* - * fcoe_sw_create - this function creates the fcoe interface +/** + * fcoe_sw_create() - this function creates the fcoe interface * @netdev: pointer the associated netdevice * * Creates fc_lport struct and scsi_host for lport, configures lport @@ -440,8 +436,8 @@ out_host_put: return rc; } -/* - * fcoe_sw_match - the fcoe sw transport match function +/** + * fcoe_sw_match() - The FCoE SW transport match function * * Returns : false always */ @@ -461,8 +457,8 @@ struct fcoe_transport fcoe_sw_transport = { .device = 0xffff, }; -/* - * fcoe_sw_init - registers fcoe_sw_transport +/** + * fcoe_sw_init() - Registers fcoe_sw_transport * * Returns : 0 on success */ @@ -480,8 +476,8 @@ int __init fcoe_sw_init(void) return 0; } -/* - * fcoe_sw_exit - unregisters fcoe_sw_transport +/** + * fcoe_sw_exit() - Unregisters fcoe_sw_transport * * Returns : 0 on success */ diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 296071043f5..5e68652985b 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -91,13 +91,13 @@ static struct notifier_block fcoe_cpu_notifier = { }; /** - * fcoe_create_percpu_data - creates the associated cpu data + * fcoe_create_percpu_data() - creates the associated cpu data * @cpu: index for the cpu where fcoe cpu data will be created * * create percpu stats block, from cpu add notifier * * Returns: none - **/ + */ static void fcoe_create_percpu_data(int cpu) { struct fc_lport *lp; @@ -115,13 +115,13 @@ static void fcoe_create_percpu_data(int cpu) } /** - * fcoe_destroy_percpu_data - destroys the associated cpu data + * fcoe_destroy_percpu_data() - destroys the associated cpu data * @cpu: index for the cpu where fcoe cpu data will destroyed * * destroy percpu stats block called by cpu add/remove notifier * * Retuns: none - **/ + */ static void fcoe_destroy_percpu_data(int cpu) { struct fc_lport *lp; @@ -137,7 +137,7 @@ static void fcoe_destroy_percpu_data(int cpu) } /** - * fcoe_cpu_callback - fcoe cpu hotplug event callback + * fcoe_cpu_callback() - fcoe cpu hotplug event callback * @nfb: callback data block * @action: event triggering the callback * @hcpu: index for the cpu of this event @@ -145,7 +145,7 @@ static void fcoe_destroy_percpu_data(int cpu) * this creates or destroys per cpu data for fcoe * * Returns NOTIFY_OK always. - **/ + */ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) { @@ -166,7 +166,7 @@ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, #endif /* CONFIG_HOTPLUG_CPU */ /** - * fcoe_rcv - this is the fcoe receive function called by NET_RX_SOFTIRQ + * fcoe_rcv() - this is the fcoe receive function called by NET_RX_SOFTIRQ * @skb: the receive skb * @dev: associated net device * @ptype: context @@ -175,7 +175,7 @@ static int fcoe_cpu_callback(struct notifier_block *nfb, unsigned long action, * this function will receive the packet and build fc frame and pass it up * * Returns: 0 for success - **/ + */ int fcoe_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *ptype, struct net_device *olddev) { @@ -265,11 +265,11 @@ err2: EXPORT_SYMBOL_GPL(fcoe_rcv); /** - * fcoe_start_io - pass to netdev to start xmit for fcoe + * fcoe_start_io() - pass to netdev to start xmit for fcoe * @skb: the skb to be xmitted * * Returns: 0 for success - **/ + */ static inline int fcoe_start_io(struct sk_buff *skb) { int rc; @@ -283,12 +283,12 @@ static inline int fcoe_start_io(struct sk_buff *skb) } /** - * fcoe_get_paged_crc_eof - in case we need alloc a page for crc_eof + * fcoe_get_paged_crc_eof() - in case we need alloc a page for crc_eof * @skb: the skb to be xmitted * @tlen: total len * * Returns: 0 for success - **/ + */ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) { struct fcoe_percpu_s *fps; @@ -326,13 +326,12 @@ static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen) } /** - * fcoe_fc_crc - calculates FC CRC in this fcoe skb + * fcoe_fc_crc() - calculates FC CRC in this fcoe skb * @fp: the fc_frame containg data to be checksummed * * This uses crc32() to calculate the crc for fc frame * Return : 32 bit crc - * - **/ + */ u32 fcoe_fc_crc(struct fc_frame *fp) { struct sk_buff *skb = fp_skb(fp); @@ -363,13 +362,12 @@ u32 fcoe_fc_crc(struct fc_frame *fp) EXPORT_SYMBOL_GPL(fcoe_fc_crc); /** - * fcoe_xmit - FCoE frame transmit function + * fcoe_xmit() - FCoE frame transmit function * @lp: the associated local port * @fp: the fc_frame to be transmitted * * Return : 0 for success - * - **/ + */ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) { int wlen, rc = 0; @@ -511,12 +509,11 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) } EXPORT_SYMBOL_GPL(fcoe_xmit); -/* - * fcoe_percpu_receive_thread - recv thread per cpu +/** + * fcoe_percpu_receive_thread() - recv thread per cpu * @arg: ptr to the fcoe per cpu struct * * Return: 0 for success - * */ int fcoe_percpu_receive_thread(void *arg) { @@ -658,7 +655,7 @@ int fcoe_percpu_receive_thread(void *arg) } /** - * fcoe_recv_flogi - flogi receive function + * fcoe_recv_flogi() - flogi receive function * @fc: associated fcoe_softc * @fp: the recieved frame * @sa: the source address of this flogi @@ -667,7 +664,7 @@ int fcoe_percpu_receive_thread(void *arg) * mac address for the initiator, eitehr OUI based or GW based. * * Returns: none - **/ + */ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) { struct fc_frame_header *fh; @@ -715,7 +712,7 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) } /** - * fcoe_watchdog - fcoe timer callback + * fcoe_watchdog() - fcoe timer callback * @vp: * * This checks the pending queue length for fcoe and set lport qfull @@ -723,7 +720,7 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) * fcoe_hostlist. * * Returns: 0 for success - **/ + */ void fcoe_watchdog(ulong vp) { struct fc_lport *lp; @@ -750,7 +747,7 @@ void fcoe_watchdog(ulong vp) /** - * fcoe_check_wait_queue - put the skb into fcoe pending xmit queue + * fcoe_check_wait_queue() - put the skb into fcoe pending xmit queue * @lp: the fc_port for this skb * @skb: the associated skb to be xmitted * @@ -764,7 +761,7 @@ void fcoe_watchdog(ulong vp) * by the next skb transmit. * * Returns: 0 for success - **/ + */ static int fcoe_check_wait_queue(struct fc_lport *lp) { int rc; @@ -797,12 +794,12 @@ static int fcoe_check_wait_queue(struct fc_lport *lp) } /** - * fcoe_insert_wait_queue_head - puts skb to fcoe pending queue head + * fcoe_insert_wait_queue_head() - puts skb to fcoe pending queue head * @lp: the fc_port for this skb * @skb: the associated skb to be xmitted * * Returns: none - **/ + */ static void fcoe_insert_wait_queue_head(struct fc_lport *lp, struct sk_buff *skb) { @@ -815,12 +812,12 @@ static void fcoe_insert_wait_queue_head(struct fc_lport *lp, } /** - * fcoe_insert_wait_queue - put the skb into fcoe pending queue tail + * fcoe_insert_wait_queue() - put the skb into fcoe pending queue tail * @lp: the fc_port for this skb * @skb: the associated skb to be xmitted * * Returns: none - **/ + */ static void fcoe_insert_wait_queue(struct fc_lport *lp, struct sk_buff *skb) { @@ -833,10 +830,9 @@ static void fcoe_insert_wait_queue(struct fc_lport *lp, } /** - * fcoe_dev_setup - setup link change notification interface - * - **/ -static void fcoe_dev_setup(void) + * fcoe_dev_setup() - setup link change notification interface + */ +static void fcoe_dev_setup() { /* * here setup a interface specific wd time to @@ -846,15 +842,15 @@ static void fcoe_dev_setup(void) } /** - * fcoe_dev_setup - cleanup link change notification interface - **/ + * fcoe_dev_setup() - cleanup link change notification interface + */ static void fcoe_dev_cleanup(void) { unregister_netdevice_notifier(&fcoe_notifier); } /** - * fcoe_device_notification - netdev event notification callback + * fcoe_device_notification() - netdev event notification callback * @notifier: context of the notification * @event: type of event * @ptr: fixed array for output parsed ifname @@ -862,7 +858,7 @@ static void fcoe_dev_cleanup(void) * This function is called by the ethernet driver in case of link change event * * Returns: 0 for success - **/ + */ static int fcoe_device_notification(struct notifier_block *notifier, ulong event, void *ptr) { @@ -926,12 +922,12 @@ out: } /** - * fcoe_if_to_netdev - parse a name buffer to get netdev + * fcoe_if_to_netdev() - parse a name buffer to get netdev * @ifname: fixed array for output parsed ifname * @buffer: incoming buffer to be copied * * Returns: NULL or ptr to netdeive - **/ + */ static struct net_device *fcoe_if_to_netdev(const char *buffer) { char *cp; @@ -948,11 +944,11 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) } /** - * fcoe_netdev_to_module_owner - finds out the nic drive moddule of the netdev + * fcoe_netdev_to_module_owner() - finds out the nic drive moddule of the netdev * @netdev: the target netdev * * Returns: ptr to the struct module, NULL for failure - **/ + */ static struct module *fcoe_netdev_to_module_owner( const struct net_device *netdev) { @@ -972,12 +968,14 @@ static struct module *fcoe_netdev_to_module_owner( } /** - * fcoe_ethdrv_get - holds the nic driver module by try_module_get() for - * the corresponding netdev. + * fcoe_ethdrv_get() - Hold the Ethernet driver * @netdev: the target netdev * + * Holds the Ethernet driver module by try_module_get() for + * the corresponding netdev. + * * Returns: 0 for succsss - **/ + */ static int fcoe_ethdrv_get(const struct net_device *netdev) { struct module *owner; @@ -992,12 +990,14 @@ static int fcoe_ethdrv_get(const struct net_device *netdev) } /** - * fcoe_ethdrv_get - releases the nic driver module by module_put for - * the corresponding netdev. + * fcoe_ethdrv_put() - Release the Ethernet driver * @netdev: the target netdev * + * Releases the Ethernet driver module by module_put for + * the corresponding netdev. + * * Returns: 0 for succsss - **/ + */ static int fcoe_ethdrv_put(const struct net_device *netdev) { struct module *owner; @@ -1013,12 +1013,12 @@ static int fcoe_ethdrv_put(const struct net_device *netdev) } /** - * fcoe_destroy- handles the destroy from sysfs + * fcoe_destroy() - handles the destroy from sysfs * @buffer: expcted to be a eth if name * @kp: associated kernel param * * Returns: 0 for success - **/ + */ static int fcoe_destroy(const char *buffer, struct kernel_param *kp) { int rc; @@ -1051,12 +1051,12 @@ out_nodev: } /** - * fcoe_create - handles the create call from sysfs + * fcoe_create() - Handles the create call from sysfs * @buffer: expcted to be a eth if name * @kp: associated kernel param * * Returns: 0 for success - **/ + */ static int fcoe_create(const char *buffer, struct kernel_param *kp) { int rc; @@ -1097,8 +1097,8 @@ module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR); __MODULE_PARM_TYPE(destroy, "string"); MODULE_PARM_DESC(destroy, "Destroy fcoe port"); -/* - * fcoe_link_ok - check if link is ok for the fc_lport +/** + * fcoe_link_ok() - Check if link is ok for the fc_lport * @lp: ptr to the fc_lport * * Any permanently-disqualifying conditions have been previously checked. @@ -1142,9 +1142,8 @@ int fcoe_link_ok(struct fc_lport *lp) } EXPORT_SYMBOL_GPL(fcoe_link_ok); -/* - * fcoe_percpu_clean - frees skb of the corresponding lport from the per - * cpu queue. +/** + * fcoe_percpu_clean() - Clear the pending skbs for an lport * @lp: the fc_lport */ void fcoe_percpu_clean(struct fc_lport *lp) @@ -1178,11 +1177,11 @@ void fcoe_percpu_clean(struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_percpu_clean); /** - * fcoe_clean_pending_queue - dequeue skb and free it + * fcoe_clean_pending_queue() - Dequeue a skb and free it * @lp: the corresponding fc_lport * * Returns: none - **/ + */ void fcoe_clean_pending_queue(struct fc_lport *lp) { struct fcoe_softc *fc = lport_priv(lp); @@ -1199,12 +1198,12 @@ void fcoe_clean_pending_queue(struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); /** - * libfc_host_alloc - allocate a Scsi_Host with room for the fc_lport + * libfc_host_alloc() - Allocate a Scsi_Host with room for the fc_lport * @sht: ptr to the scsi host templ * @priv_size: size of private data after fc_lport * * Returns: ptr to Scsi_Host - * TODO - to libfc? + * TODO: to libfc? */ static inline struct Scsi_Host *libfc_host_alloc( struct scsi_host_template *sht, int priv_size) @@ -1213,7 +1212,7 @@ static inline struct Scsi_Host *libfc_host_alloc( } /** - * fcoe_host_alloc - allocate a Scsi_Host with room for the fcoe_softc + * fcoe_host_alloc() - Allocate a Scsi_Host with room for the fcoe_softc * @sht: ptr to the scsi host templ * @priv_size: size of private data after fc_lport * @@ -1225,8 +1224,8 @@ struct Scsi_Host *fcoe_host_alloc(struct scsi_host_template *sht, int priv_size) } EXPORT_SYMBOL_GPL(fcoe_host_alloc); -/* - * fcoe_reset - resets the fcoe +/** + * fcoe_reset() - Resets the fcoe * @shost: shost the reset is from * * Returns: always 0 @@ -1239,8 +1238,8 @@ int fcoe_reset(struct Scsi_Host *shost) } EXPORT_SYMBOL_GPL(fcoe_reset); -/* - * fcoe_wwn_from_mac - converts 48-bit IEEE MAC address to 64-bit FC WWN. +/** + * fcoe_wwn_from_mac() - Converts 48-bit IEEE MAC address to 64-bit FC WWN. * @mac: mac address * @scheme: check port * @port: port indicator for converting @@ -1279,8 +1278,9 @@ u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN], return wwn; } EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); -/* - * fcoe_hostlist_lookup_softc - find the corresponding lport by a given device + +/** + * fcoe_hostlist_lookup_softc() - find the corresponding lport by a given device * @device: this is currently ptr to net_device * * Returns: NULL or the located fcoe_softc @@ -1301,8 +1301,8 @@ static struct fcoe_softc *fcoe_hostlist_lookup_softc( return NULL; } -/* - * fcoe_hostlist_lookup - find the corresponding lport by netdev +/** + * fcoe_hostlist_lookup() - Find the corresponding lport by netdev * @netdev: ptr to net_device * * Returns: 0 for success @@ -1317,8 +1317,8 @@ struct fc_lport *fcoe_hostlist_lookup(const struct net_device *netdev) } EXPORT_SYMBOL_GPL(fcoe_hostlist_lookup); -/* - * fcoe_hostlist_add - add a lport to lports list +/** + * fcoe_hostlist_add() - Add a lport to lports list * @lp: ptr to the fc_lport to badded * * Returns: 0 for success @@ -1338,8 +1338,8 @@ int fcoe_hostlist_add(const struct fc_lport *lp) } EXPORT_SYMBOL_GPL(fcoe_hostlist_add); -/* - * fcoe_hostlist_remove - remove a lport from lports list +/** + * fcoe_hostlist_remove() - remove a lport from lports list * @lp: ptr to the fc_lport to badded * * Returns: 0 for success @@ -1359,12 +1359,12 @@ int fcoe_hostlist_remove(const struct fc_lport *lp) EXPORT_SYMBOL_GPL(fcoe_hostlist_remove); /** - * fcoe_libfc_config - sets up libfc related properties for lport + * fcoe_libfc_config() - sets up libfc related properties for lport * @lp: ptr to the fc_lport * @tt: libfc function template * * Returns : 0 for success - **/ + */ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) { /* Set the function pointers set by the LLDD */ @@ -1382,14 +1382,14 @@ int fcoe_libfc_config(struct fc_lport *lp, struct libfc_function_template *tt) EXPORT_SYMBOL_GPL(fcoe_libfc_config); /** - * fcoe_init - fcoe module loading initialization + * fcoe_init() - fcoe module loading initialization * * Initialization routine * 1. Will create fc transport software structure * 2. initialize the link list of port information structure * * Returns 0 on success, negative on failure - **/ + */ static int __init fcoe_init(void) { int cpu; @@ -1452,10 +1452,10 @@ static int __init fcoe_init(void) module_init(fcoe_init); /** - * fcoe_exit - fcoe module unloading cleanup + * fcoe_exit() - fcoe module unloading cleanup * * Returns 0 on success, negative on failure - **/ + */ static void __exit fcoe_exit(void) { u32 idx; diff --git a/drivers/scsi/libfc/fc_disc.c b/drivers/scsi/libfc/fc_disc.c index cfbce893941..e57556ea5b4 100644 --- a/drivers/scsi/libfc/fc_disc.c +++ b/drivers/scsi/libfc/fc_disc.c @@ -64,7 +64,7 @@ static void fc_disc_single(struct fc_disc *, struct fc_disc_port *); static void fc_disc_restart(struct fc_disc *); /** - * fc_disc_lookup_rport - lookup a remote port by port_id + * fc_disc_lookup_rport() - lookup a remote port by port_id * @lport: Fibre Channel host port instance * @port_id: remote port port_id to match */ @@ -92,7 +92,7 @@ struct fc_rport *fc_disc_lookup_rport(const struct fc_lport *lport, } /** - * fc_disc_stop_rports - delete all the remote ports associated with the lport + * fc_disc_stop_rports() - delete all the remote ports associated with the lport * @disc: The discovery job to stop rports on * * Locking Note: This function expects that the lport mutex is locked before @@ -117,7 +117,7 @@ void fc_disc_stop_rports(struct fc_disc *disc) } /** - * fc_disc_rport_callback - Event handler for rport events + * fc_disc_rport_callback() - Event handler for rport events * @lport: The lport which is receiving the event * @rport: The rport which the event has occured on * @event: The event that occured @@ -151,7 +151,7 @@ static void fc_disc_rport_callback(struct fc_lport *lport, } /** - * fc_disc_recv_rscn_req - Handle Registered State Change Notification (RSCN) + * fc_disc_recv_rscn_req() - Handle Registered State Change Notification (RSCN) * @sp: Current sequence of the RSCN exchange * @fp: RSCN Frame * @lport: Fibre Channel host port instance @@ -265,7 +265,7 @@ reject: } /** - * fc_disc_recv_req - Handle incoming requests + * fc_disc_recv_req() - Handle incoming requests * @sp: Current sequence of the request exchange * @fp: The frame * @lport: The FC local port @@ -294,7 +294,7 @@ static void fc_disc_recv_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_disc_restart - Restart discovery + * fc_disc_restart() - Restart discovery * @lport: FC discovery context * * Locking Note: This function expects that the disc mutex @@ -322,7 +322,7 @@ static void fc_disc_restart(struct fc_disc *disc) } /** - * fc_disc_start - Fibre Channel Target discovery + * fc_disc_start() - Fibre Channel Target discovery * @lport: FC local port * * Returns non-zero if discovery cannot be started. @@ -383,7 +383,7 @@ static struct fc_rport_operations fc_disc_rport_ops = { }; /** - * fc_disc_new_target - Handle new target found by discovery + * fc_disc_new_target() - Handle new target found by discovery * @lport: FC local port * @rport: The previous FC remote port (NULL if new remote port) * @ids: Identifiers for the new FC remote port @@ -446,7 +446,7 @@ static int fc_disc_new_target(struct fc_disc *disc, } /** - * fc_disc_del_target - Delete a target + * fc_disc_del_target() - Delete a target * @disc: FC discovery context * @rport: The remote port to be removed */ @@ -459,7 +459,7 @@ static void fc_disc_del_target(struct fc_disc *disc, struct fc_rport *rport) } /** - * fc_disc_done - Discovery has been completed + * fc_disc_done() - Discovery has been completed * @disc: FC discovery context */ static void fc_disc_done(struct fc_disc *disc) @@ -479,7 +479,7 @@ static void fc_disc_done(struct fc_disc *disc) } /** - * fc_disc_error - Handle error on dNS request + * fc_disc_error() - Handle error on dNS request * @disc: FC discovery context * @fp: The frame pointer */ @@ -519,7 +519,7 @@ static void fc_disc_error(struct fc_disc *disc, struct fc_frame *fp) } /** - * fc_disc_gpn_ft_req - Send Get Port Names by FC-4 type (GPN_FT) request + * fc_disc_gpn_ft_req() - Send Get Port Names by FC-4 type (GPN_FT) request * @lport: FC discovery context * * Locking Note: This function expects that the disc_mutex is locked @@ -553,7 +553,7 @@ err: } /** - * fc_disc_gpn_ft_parse - Parse the list of IDs and names resulting from a request + * fc_disc_gpn_ft_parse() - Parse the list of IDs and names resulting from a request * @lport: Fibre Channel host port instance * @buf: GPN_FT response buffer * @len: size of response buffer @@ -658,7 +658,10 @@ static int fc_disc_gpn_ft_parse(struct fc_disc *disc, void *buf, size_t len) return error; } -/* +/** + * fc_disc_timeout() - Retry handler for the disc component + * @work: Structure holding disc obj that needs retry discovery + * * Handle retry of memory allocation for remote ports. */ static void fc_disc_timeout(struct work_struct *work) @@ -673,7 +676,7 @@ static void fc_disc_timeout(struct work_struct *work) } /** - * fc_disc_gpn_ft_resp - Handle a response frame from Get Port Names (GPN_FT) + * fc_disc_gpn_ft_resp() - Handle a response frame from Get Port Names (GPN_FT) * @sp: Current sequence of GPN_FT exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -712,9 +715,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, fr_len(fp)); } else if (ntohs(cp->ct_cmd) == FC_FS_ACC) { - /* - * Accepted. Parse response. - */ + /* Accepted, parse the response. */ buf = cp + 1; len -= sizeof(*cp); } else if (ntohs(cp->ct_cmd) == FC_FS_RJT) { @@ -746,7 +747,7 @@ static void fc_disc_gpn_ft_resp(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_disc_single - Discover the directory information for a single target + * fc_disc_single() - Discover the directory information for a single target * @lport: FC local port * @dp: The port to rediscover * @@ -782,7 +783,7 @@ out: } /** - * fc_disc_stop - Stop discovery for a given lport + * fc_disc_stop() - Stop discovery for a given lport * @lport: The lport that discovery should stop for */ void fc_disc_stop(struct fc_lport *lport) @@ -796,7 +797,7 @@ void fc_disc_stop(struct fc_lport *lport) } /** - * fc_disc_stop_final - Stop discovery for a given lport + * fc_disc_stop_final() - Stop discovery for a given lport * @lport: The lport that discovery should stop for * * This function will block until discovery has been @@ -809,7 +810,7 @@ void fc_disc_stop_final(struct fc_lport *lport) } /** - * fc_disc_init - Initialize the discovery block + * fc_disc_init() - Initialize the discovery block * @lport: FC local port */ int fc_disc_init(struct fc_lport *lport) diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index ecc72612c38..2a631d7dbce 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -161,7 +161,7 @@ static struct fc_fcp_pkt *fc_fcp_pkt_alloc(struct fc_lport *lp, gfp_t gfp) } /** - * fc_fcp_pkt_release - release hold on scsi_pkt packet + * fc_fcp_pkt_release() - release hold on scsi_pkt packet * @fsp: fcp packet struct * * This is used by upper layer scsi driver. @@ -183,8 +183,7 @@ static void fc_fcp_pkt_hold(struct fc_fcp_pkt *fsp) } /** - * fc_fcp_pkt_destory - release hold on scsi_pkt packet - * + * fc_fcp_pkt_destory() - release hold on scsi_pkt packet * @seq: exchange sequence * @fsp: fcp packet struct * @@ -199,7 +198,7 @@ static void fc_fcp_pkt_destroy(struct fc_seq *seq, void *fsp) } /** - * fc_fcp_lock_pkt - lock a packet and get a ref to it. + * fc_fcp_lock_pkt() - lock a packet and get a ref to it. * @fsp: fcp packet * * We should only return error if we return a command to scsi-ml before @@ -291,9 +290,7 @@ static void fc_fcp_recv_data(struct fc_fcp_pkt *fsp, struct fc_frame *fp) buf = fc_frame_payload_get(fp, 0); if (offset + len > fsp->data_len) { - /* - * this should never happen - */ + /* this should never happen */ if ((fr_flags(fp) & FCPHF_CRC_UNCHECKED) && fc_frame_crc_check(fp)) goto crc_err; @@ -387,8 +384,8 @@ crc_err: fc_fcp_complete_locked(fsp); } -/* - * fc_fcp_send_data - Send SCSI data to target. +/** + * fc_fcp_send_data() - Send SCSI data to target. * @fsp: ptr to fc_fcp_pkt * @sp: ptr to this sequence * @offset: starting offset for this data request @@ -610,8 +607,8 @@ static void fc_fcp_abts_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp) } } -/* - * fc_fcp_reduce_can_queue - drop can_queue +/** + * fc_fcp_reduce_can_queue() - drop can_queue * @lp: lport to drop queueing for * * If we are getting memory allocation failures, then we may @@ -642,9 +639,11 @@ done: spin_unlock_irqrestore(lp->host->host_lock, flags); } -/* - * exch mgr calls this routine to process scsi - * exchanges. +/** + * fc_fcp_recv() - Reveive FCP frames + * @seq: The sequence the frame is on + * @fp: The FC frame + * @arg: The related FCP packet * * Return : None * Context : called from Soft IRQ context @@ -832,7 +831,7 @@ err: } /** - * fc_fcp_complete_locked - complete processing of a fcp packet + * fc_fcp_complete_locked() - complete processing of a fcp packet * @fsp: fcp packet * * This function may sleep if a timer is pending. The packet lock must be @@ -900,7 +899,7 @@ static void fc_fcp_cleanup_cmd(struct fc_fcp_pkt *fsp, int error) } /** - * fc_fcp_cleanup_each_cmd - run fn on each active command + * fc_fcp_cleanup_each_cmd() - Cleanup active commads * @lp: logical port * @id: target id * @lun: lun @@ -952,7 +951,7 @@ static void fc_fcp_abort_io(struct fc_lport *lp) } /** - * fc_fcp_pkt_send - send a fcp packet to the lower level. + * fc_fcp_pkt_send() - send a fcp packet to the lower level. * @lp: fc lport * @fsp: fc packet. * @@ -1727,7 +1726,7 @@ out: EXPORT_SYMBOL(fc_queuecommand); /** - * fc_io_compl - Handle responses for completed commands + * fc_io_compl() - Handle responses for completed commands * @fsp: scsi packet * * Translates a error to a Linux SCSI error. @@ -1857,7 +1856,7 @@ static void fc_io_compl(struct fc_fcp_pkt *fsp) } /** - * fc_fcp_complete - complete processing of a fcp packet + * fc_fcp_complete() - complete processing of a fcp packet * @fsp: fcp packet * * This function may sleep if a fsp timer is pending. @@ -1874,9 +1873,10 @@ void fc_fcp_complete(struct fc_fcp_pkt *fsp) EXPORT_SYMBOL(fc_fcp_complete); /** - * fc_eh_abort - Abort a command...from scsi host template + * fc_eh_abort() - Abort a command * @sc_cmd: scsi command to abort * + * From scsi host template. * send ABTS to the target device and wait for the response * sc_cmd is the pointer to the command to be aborted. */ @@ -1920,7 +1920,7 @@ release_pkt: EXPORT_SYMBOL(fc_eh_abort); /** - * fc_eh_device_reset: Reset a single LUN + * fc_eh_device_reset() Reset a single LUN * @sc_cmd: scsi command * * Set from scsi host template to send tm cmd to the target and wait for the @@ -1973,7 +1973,7 @@ out: EXPORT_SYMBOL(fc_eh_device_reset); /** - * fc_eh_host_reset - The reset function will reset the ports on the host. + * fc_eh_host_reset() - The reset function will reset the ports on the host. * @sc_cmd: scsi command */ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) @@ -1999,7 +1999,7 @@ int fc_eh_host_reset(struct scsi_cmnd *sc_cmd) EXPORT_SYMBOL(fc_eh_host_reset); /** - * fc_slave_alloc - configure queue depth + * fc_slave_alloc() - configure queue depth * @sdev: scsi device * * Configures queue depth based on host's cmd_per_len. If not set diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index c00de2244c7..2ae50a1188e 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c @@ -139,7 +139,7 @@ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp) } /** - * fc_lport_rport_callback - Event handler for rport events + * fc_lport_rport_callback() - Event handler for rport events * @lport: The lport which is receiving the event * @rport: The rport which the event has occured on * @event: The event that occured @@ -195,7 +195,7 @@ static void fc_lport_rport_callback(struct fc_lport *lport, } /** - * fc_lport_state - Return a string which represents the lport's state + * fc_lport_state() - Return a string which represents the lport's state * @lport: The lport whose state is to converted to a string */ static const char *fc_lport_state(struct fc_lport *lport) @@ -209,7 +209,7 @@ static const char *fc_lport_state(struct fc_lport *lport) } /** - * fc_lport_ptp_setup - Create an rport for point-to-point mode + * fc_lport_ptp_setup() - Create an rport for point-to-point mode * @lport: The lport to attach the ptp rport to * @fid: The FID of the ptp rport * @remote_wwpn: The WWPN of the ptp rport @@ -351,7 +351,7 @@ static void fc_lport_add_fc4_type(struct fc_lport *lport, enum fc_fh_type type) } /** - * fc_lport_recv_rlir_req - Handle received Registered Link Incident Report. + * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report. * @lport: Fibre Channel local port recieving the RLIR * @sp: current sequence in the RLIR exchange * @fp: RLIR request frame @@ -370,7 +370,7 @@ static void fc_lport_recv_rlir_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_lport_recv_echo_req - Handle received ECHO request + * fc_lport_recv_echo_req() - Handle received ECHO request * @lport: Fibre Channel local port recieving the ECHO * @sp: current sequence in the ECHO exchange * @fp: ECHO request frame @@ -412,7 +412,7 @@ static void fc_lport_recv_echo_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_echo_req - Handle received Request Node ID data request + * fc_lport_recv_echo_req() - Handle received Request Node ID data request * @lport: Fibre Channel local port recieving the RNID * @sp: current sequence in the RNID exchange * @fp: RNID request frame @@ -479,7 +479,7 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_adisc_req - Handle received Address Discovery Request + * fc_lport_recv_adisc_req() - Handle received Address Discovery Request * @lport: Fibre Channel local port recieving the ADISC * @sp: current sequence in the ADISC exchange * @fp: ADISC request frame @@ -529,7 +529,7 @@ static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp, } /** - * fc_lport_recv_logo_req - Handle received fabric LOGO request + * fc_lport_recv_logo_req() - Handle received fabric LOGO request * @lport: Fibre Channel local port recieving the LOGO * @sp: current sequence in the LOGO exchange * @fp: LOGO request frame @@ -546,7 +546,7 @@ static void fc_lport_recv_logo_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_fabric_login - Start the lport state machine + * fc_fabric_login() - Start the lport state machine * @lport: The lport that should log into the fabric * * Locking Note: This function should not be called @@ -568,7 +568,7 @@ int fc_fabric_login(struct fc_lport *lport) EXPORT_SYMBOL(fc_fabric_login); /** - * fc_linkup - Handler for transport linkup events + * fc_linkup() - Handler for transport linkup events * @lport: The lport whose link is up */ void fc_linkup(struct fc_lport *lport) @@ -588,7 +588,7 @@ void fc_linkup(struct fc_lport *lport) EXPORT_SYMBOL(fc_linkup); /** - * fc_linkdown - Handler for transport linkdown events + * fc_linkdown() - Handler for transport linkdown events * @lport: The lport whose link is down */ void fc_linkdown(struct fc_lport *lport) @@ -607,12 +607,12 @@ void fc_linkdown(struct fc_lport *lport) EXPORT_SYMBOL(fc_linkdown); /** - * fc_fabric_logoff - Logout of the fabric + * fc_fabric_logoff() - Logout of the fabric * @lport: fc_lport pointer to logoff the fabric * * Return value: * 0 for success, -1 for failure - **/ + */ int fc_fabric_logoff(struct fc_lport *lport) { lport->tt.disc_stop_final(lport); @@ -625,7 +625,7 @@ int fc_fabric_logoff(struct fc_lport *lport) EXPORT_SYMBOL(fc_fabric_logoff); /** - * fc_lport_destroy - unregister a fc_lport + * fc_lport_destroy() - unregister a fc_lport * @lport: fc_lport pointer to unregister * * Return value: @@ -635,7 +635,7 @@ EXPORT_SYMBOL(fc_fabric_logoff); * clean-up all the allocated memory * and free up other system resources. * - **/ + */ int fc_lport_destroy(struct fc_lport *lport) { lport->tt.frame_send = fc_frame_drop; @@ -646,15 +646,14 @@ int fc_lport_destroy(struct fc_lport *lport) EXPORT_SYMBOL(fc_lport_destroy); /** - * fc_set_mfs - sets up the mfs for the corresponding fc_lport + * fc_set_mfs() - sets up the mfs for the corresponding fc_lport * @lport: fc_lport pointer to unregister * @mfs: the new mfs for fc_lport * * Set mfs for the given fc_lport to the new mfs. * * Return: 0 for success - * - **/ + */ int fc_set_mfs(struct fc_lport *lport, u32 mfs) { unsigned int old_mfs; @@ -683,7 +682,7 @@ int fc_set_mfs(struct fc_lport *lport, u32 mfs) EXPORT_SYMBOL(fc_set_mfs); /** - * fc_lport_disc_callback - Callback for discovery events + * fc_lport_disc_callback() - Callback for discovery events * @lport: FC local port * @event: The discovery event */ @@ -708,7 +707,7 @@ void fc_lport_disc_callback(struct fc_lport *lport, enum fc_disc_event event) } /** - * fc_rport_enter_ready - Enter the ready state and start discovery + * fc_rport_enter_ready() - Enter the ready state and start discovery * @lport: Fibre Channel local port that is ready * * Locking Note: The lport lock is expected to be held before calling @@ -725,7 +724,7 @@ static void fc_lport_enter_ready(struct fc_lport *lport) } /** - * fc_lport_recv_flogi_req - Receive a FLOGI request + * fc_lport_recv_flogi_req() - Receive a FLOGI request * @sp_in: The sequence the FLOGI is on * @rx_fp: The frame the FLOGI is in * @lport: The lport that recieved the request @@ -815,7 +814,7 @@ out: } /** - * fc_lport_recv_req - The generic lport request handler + * fc_lport_recv_req() - The generic lport request handler * @lport: The lport that received the request * @sp: The sequence the request is on * @fp: The frame the request is in @@ -911,7 +910,7 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, } /** - * fc_lport_reset - Reset an lport + * fc_lport_reset() - Reset an lport * @lport: The lport which should be reset * * Locking Note: This functions should not be called with the @@ -928,7 +927,7 @@ int fc_lport_reset(struct fc_lport *lport) EXPORT_SYMBOL(fc_lport_reset); /** - * fc_rport_enter_reset - Reset the local port + * fc_rport_enter_reset() - Reset the local port * @lport: Fibre Channel local port to be reset * * Locking Note: The lport lock is expected to be held before calling @@ -960,7 +959,7 @@ static void fc_lport_enter_reset(struct fc_lport *lport) } /** - * fc_lport_error - Handler for any errors + * fc_lport_error() - Handler for any errors * @lport: The fc_lport object * @fp: The frame pointer * @@ -1007,8 +1006,8 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp) } /** - * fc_lport_rft_id_resp - Handle response to Register Fibre - * Channel Types by ID (RPN_ID) request + * fc_lport_rft_id_resp() - Handle response to Register Fibre + * Channel Types by ID (RPN_ID) request * @sp: current sequence in RPN_ID exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -1059,8 +1058,8 @@ err: } /** - * fc_lport_rpn_id_resp - Handle response to Register Port - * Name by ID (RPN_ID) request + * fc_lport_rpn_id_resp() - Handle response to Register Port + * Name by ID (RPN_ID) request * @sp: current sequence in RPN_ID exchange * @fp: response frame * @lp_arg: Fibre Channel host port instance @@ -1111,7 +1110,7 @@ err: } /** - * fc_lport_scr_resp - Handle response to State Change Register (SCR) request + * fc_lport_scr_resp() - Handle response to State Change Register (SCR) request * @sp: current sequence in SCR exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the registration request @@ -1157,7 +1156,7 @@ err: } /** - * fc_lport_enter_scr - Send a State Change Register (SCR) request + * fc_lport_enter_scr() - Send a State Change Register (SCR) request * @lport: Fibre Channel local port to register for state changes * * Locking Note: The lport lock is expected to be held before calling @@ -1184,7 +1183,7 @@ static void fc_lport_enter_scr(struct fc_lport *lport) } /** - * fc_lport_enter_rft_id - Register FC4-types with the name server + * fc_lport_enter_rft_id() - Register FC4-types with the name server * @lport: Fibre Channel local port to register * * Locking Note: The lport lock is expected to be held before calling @@ -1226,7 +1225,7 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport) } /** - * fc_rport_enter_rft_id - Register port name with the name server + * fc_rport_enter_rft_id() - Register port name with the name server * @lport: Fibre Channel local port to register * * Locking Note: The lport lock is expected to be held before calling @@ -1259,7 +1258,7 @@ static struct fc_rport_operations fc_lport_rport_ops = { }; /** - * fc_rport_enter_dns - Create a rport to the name server + * fc_rport_enter_dns() - Create a rport to the name server * @lport: Fibre Channel local port requesting a rport for the name server * * Locking Note: The lport lock is expected to be held before calling @@ -1296,7 +1295,7 @@ err: } /** - * fc_lport_timeout - Handler for the retry_work timer. + * fc_lport_timeout() - Handler for the retry_work timer. * @work: The work struct of the fc_lport */ static void fc_lport_timeout(struct work_struct *work) @@ -1337,7 +1336,7 @@ static void fc_lport_timeout(struct work_struct *work) } /** - * fc_lport_logo_resp - Handle response to LOGO request + * fc_lport_logo_resp() - Handle response to LOGO request * @sp: current sequence in LOGO exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the LOGO request @@ -1383,7 +1382,7 @@ err: } /** - * fc_rport_enter_logo - Logout of the fabric + * fc_rport_enter_logo() - Logout of the fabric * @lport: Fibre Channel local port to be logged out * * Locking Note: The lport lock is expected to be held before calling @@ -1415,7 +1414,7 @@ static void fc_lport_enter_logo(struct fc_lport *lport) } /** - * fc_lport_flogi_resp - Handle response to FLOGI request + * fc_lport_flogi_resp() - Handle response to FLOGI request * @sp: current sequence in FLOGI exchange * @fp: response frame * @lp_arg: Fibre Channel lport port instance that sent the FLOGI request @@ -1510,7 +1509,7 @@ err: } /** - * fc_rport_enter_flogi - Send a FLOGI request to the fabric manager + * fc_rport_enter_flogi() - Send a FLOGI request to the fabric manager * @lport: Fibre Channel local port to be logged in to the fabric * * Locking Note: The lport lock is expected to be held before calling diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 4f23a9bb15a..6f07de15c49 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -146,7 +146,7 @@ struct fc_rport *fc_rport_rogue_create(struct fc_disc_port *dp) } /** - * fc_rport_state - return a string for the state the rport is in + * fc_rport_state() - return a string for the state the rport is in * @rport: The rport whose state we want to get a string for */ static const char *fc_rport_state(struct fc_rport *rport) @@ -161,7 +161,7 @@ static const char *fc_rport_state(struct fc_rport *rport) } /** - * fc_set_rport_loss_tmo - Set the remote port loss timeout in seconds. + * fc_set_rport_loss_tmo() - Set the remote port loss timeout in seconds. * @rport: Pointer to Fibre Channel remote port structure * @timeout: timeout in seconds */ @@ -175,7 +175,7 @@ void fc_set_rport_loss_tmo(struct fc_rport *rport, u32 timeout) EXPORT_SYMBOL(fc_set_rport_loss_tmo); /** - * fc_plogi_get_maxframe - Get max payload from the common service parameters + * fc_plogi_get_maxframe() - Get max payload from the common service parameters * @flp: FLOGI payload structure * @maxval: upper limit, may be less than what is in the service parameters */ @@ -198,7 +198,7 @@ fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval) } /** - * fc_rport_state_enter - Change the rport's state + * fc_rport_state_enter() - Change the rport's state * @rport: The rport whose state should change * @new: The new state of the rport * @@ -292,7 +292,7 @@ static void fc_rport_work(struct work_struct *work) } /** - * fc_rport_login - Start the remote port login state machine + * fc_rport_login() - Start the remote port login state machine * @rport: Fibre Channel remote port * * Locking Note: Called without the rport lock held. This @@ -315,7 +315,7 @@ int fc_rport_login(struct fc_rport *rport) } /** - * fc_rport_logoff - Logoff and remove an rport + * fc_rport_logoff() - Logoff and remove an rport * @rport: Fibre Channel remote port to be removed * * Locking Note: Called without the rport lock held. This @@ -353,7 +353,7 @@ int fc_rport_logoff(struct fc_rport *rport) } /** - * fc_rport_enter_ready - The rport is ready + * fc_rport_enter_ready() - The rport is ready * @rport: Fibre Channel remote port that is ready * * Locking Note: The rport lock is expected to be held before calling @@ -372,7 +372,7 @@ static void fc_rport_enter_ready(struct fc_rport *rport) } /** - * fc_rport_timeout - Handler for the retry_work timer. + * fc_rport_timeout() - Handler for the retry_work timer. * @work: The work struct of the fc_rport_libfc_priv * * Locking Note: Called without the rport lock held. This @@ -411,7 +411,7 @@ static void fc_rport_timeout(struct work_struct *work) } /** - * fc_rport_error - Error handler, called once retries have been exhausted + * fc_rport_error() - Error handler, called once retries have been exhausted * @rport: The fc_rport object * @fp: The frame pointer * @@ -444,7 +444,7 @@ static void fc_rport_error(struct fc_rport *rport, struct fc_frame *fp) } /** - * fc_rport_error_retry - Error handler when retries are desired + * fc_rport_error_retry() - Error handler when retries are desired * @rport: The fc_rport object * @fp: The frame pointer * @@ -479,7 +479,7 @@ static void fc_rport_error_retry(struct fc_rport *rport, struct fc_frame *fp) } /** - * fc_rport_plogi_recv_resp - Handle incoming ELS PLOGI response + * fc_rport_plogi_recv_resp() - Handle incoming ELS PLOGI response * @sp: current sequence in the PLOGI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -554,7 +554,7 @@ err: } /** - * fc_rport_enter_plogi - Send Port Login (PLOGI) request to peer + * fc_rport_enter_plogi() - Send Port Login (PLOGI) request to peer * @rport: Fibre Channel remote port to send PLOGI to * * Locking Note: The rport lock is expected to be held before calling @@ -587,7 +587,7 @@ static void fc_rport_enter_plogi(struct fc_rport *rport) } /** - * fc_rport_prli_resp - Process Login (PRLI) response handler + * fc_rport_prli_resp() - Process Login (PRLI) response handler * @sp: current sequence in the PRLI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -657,7 +657,7 @@ err: } /** - * fc_rport_logo_resp - Logout (LOGO) response handler + * fc_rport_logo_resp() - Logout (LOGO) response handler * @sp: current sequence in the LOGO exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -706,7 +706,7 @@ err: } /** - * fc_rport_enter_prli - Send Process Login (PRLI) request to peer + * fc_rport_enter_prli() - Send Process Login (PRLI) request to peer * @rport: Fibre Channel remote port to send PRLI to * * Locking Note: The rport lock is expected to be held before calling @@ -741,7 +741,7 @@ static void fc_rport_enter_prli(struct fc_rport *rport) } /** - * fc_rport_els_rtv_resp - Request Timeout Value response handler + * fc_rport_els_rtv_resp() - Request Timeout Value response handler * @sp: current sequence in the RTV exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -807,7 +807,7 @@ err: } /** - * fc_rport_enter_rtv - Send Request Timeout Value (RTV) request to peer + * fc_rport_enter_rtv() - Send Request Timeout Value (RTV) request to peer * @rport: Fibre Channel remote port to send RTV to * * Locking Note: The rport lock is expected to be held before calling @@ -838,7 +838,7 @@ static void fc_rport_enter_rtv(struct fc_rport *rport) } /** - * fc_rport_enter_logo - Send Logout (LOGO) request to peer + * fc_rport_enter_logo() - Send Logout (LOGO) request to peer * @rport: Fibre Channel remote port to send LOGO to * * Locking Note: The rport lock is expected to be held before calling @@ -870,7 +870,7 @@ static void fc_rport_enter_logo(struct fc_rport *rport) /** - * fc_rport_recv_req - Receive a request from a rport + * fc_rport_recv_req() - Receive a request from a rport * @sp: current sequence in the PLOGI exchange * @fp: response frame * @rp_arg: Fibre Channel remote port @@ -931,7 +931,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, } /** - * fc_rport_recv_plogi_req - Handle incoming Port Login (PLOGI) request + * fc_rport_recv_plogi_req() - Handle incoming Port Login (PLOGI) request * @rport: Fibre Channel remote port that initiated PLOGI * @sp: current sequence in the PLOGI exchange * @fp: PLOGI request frame @@ -1053,7 +1053,7 @@ static void fc_rport_recv_plogi_req(struct fc_rport *rport, } /** - * fc_rport_recv_prli_req - Handle incoming Process Login (PRLI) request + * fc_rport_recv_prli_req() - Handle incoming Process Login (PRLI) request * @rport: Fibre Channel remote port that initiated PRLI * @sp: current sequence in the PRLI exchange * @fp: PRLI request frame @@ -1204,7 +1204,7 @@ static void fc_rport_recv_prli_req(struct fc_rport *rport, } /** - * fc_rport_recv_prlo_req - Handle incoming Process Logout (PRLO) request + * fc_rport_recv_prlo_req() - Handle incoming Process Logout (PRLO) request * @rport: Fibre Channel remote port that initiated PRLO * @sp: current sequence in the PRLO exchange * @fp: PRLO request frame @@ -1235,7 +1235,7 @@ static void fc_rport_recv_prlo_req(struct fc_rport *rport, struct fc_seq *sp, } /** - * fc_rport_recv_logo_req - Handle incoming Logout (LOGO) request + * fc_rport_recv_logo_req() - Handle incoming Logout (LOGO) request * @rport: Fibre Channel remote port that initiated LOGO * @sp: current sequence in the LOGO exchange * @fp: LOGO request frame -- cgit v1.2.3 From b2ab99c9a300e572105d6db7f6efe0a4d1572167 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:50 -0800 Subject: [SCSI] libfc, fcoe: Cleanup function formatting and minor typos 1) There were a few functions with a strange layout, i.e. all arguments on the second line, when not necessary. Where ever possible I moved the return value to the same line as the function name. However, when the line was too long to have a single argument on the same line I moved the return value to above line. For example: (, ) and (, ) 2) Removed one extra whitespace line 3) Fixed two typos Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fc_transport_fcoe.c | 11 ++++++----- drivers/scsi/fcoe/libfcoe.c | 15 +++++++-------- drivers/scsi/libfc/fc_exch.c | 10 +++++----- drivers/scsi/libfc/fc_rport.c | 4 ++-- 4 files changed, 20 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c index 0eea4c434c3..847453a70c6 100644 --- a/drivers/scsi/fcoe/fc_transport_fcoe.c +++ b/drivers/scsi/fcoe/fc_transport_fcoe.c @@ -62,8 +62,9 @@ struct pci_dev *fcoe_transport_pcidev(const struct net_device *netdev) * * Returns: 0 for success */ -static struct fcoe_transport_internal *fcoe_transport_device_lookup( - struct fcoe_transport *t, struct net_device *netdev) +static struct fcoe_transport_internal * +fcoe_transport_device_lookup(struct fcoe_transport *t, + struct net_device *netdev) { struct fcoe_transport_internal *ti; @@ -184,7 +185,7 @@ static void fcoe_transport_device_remove_all(struct fcoe_transport *t) * Returns: true for match up */ static bool fcoe_transport_match(struct fcoe_transport *t, - struct net_device *netdev) + struct net_device *netdev) { /* match transport by vendor and device id */ struct pci_dev *pci; @@ -217,8 +218,8 @@ static bool fcoe_transport_match(struct fcoe_transport *t, * * TODO: return default sw transport if no other transport is found */ -static struct fcoe_transport *fcoe_transport_lookup( - struct net_device *netdev) +static struct fcoe_transport * +fcoe_transport_lookup(struct net_device *netdev) { struct fcoe_transport *t; diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 5e68652985b..d006d657681 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -949,8 +949,8 @@ static struct net_device *fcoe_if_to_netdev(const char *buffer) * * Returns: ptr to the struct module, NULL for failure */ -static struct module *fcoe_netdev_to_module_owner( - const struct net_device *netdev) +static struct module * +fcoe_netdev_to_module_owner(const struct net_device *netdev) { struct device *dev; @@ -1205,8 +1205,8 @@ EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue); * Returns: ptr to Scsi_Host * TODO: to libfc? */ -static inline struct Scsi_Host *libfc_host_alloc( - struct scsi_host_template *sht, int priv_size) +static inline struct Scsi_Host * +libfc_host_alloc(struct scsi_host_template *sht, int priv_size) { return scsi_host_alloc(sht, sizeof(struct fc_lport) + priv_size); } @@ -1285,8 +1285,8 @@ EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac); * * Returns: NULL or the located fcoe_softc */ -static struct fcoe_softc *fcoe_hostlist_lookup_softc( - const struct net_device *dev) +static struct fcoe_softc * +fcoe_hostlist_lookup_softc(const struct net_device *dev) { struct fcoe_softc *fc; @@ -1426,7 +1426,6 @@ static int __init fcoe_init(void) } else { fcoe_percpu[cpu] = NULL; kfree(p); - } } } @@ -1476,7 +1475,7 @@ static void __exit fcoe_exit(void) */ del_timer_sync(&fcoe_timer); - /* releases the assocaited fcoe transport for each lport */ + /* releases the associated fcoe transport for each lport */ list_for_each_entry_safe(fc, tmp, &fcoe_hostlist, list) fcoe_transport_release(fc->real_dev); diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 8c4018956d4..7b933954c10 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -675,8 +675,8 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) * If fc_pf_rjt_reason is FC_RJT_NONE then this function will have a hold * on the ep that should be released by the caller. */ -static enum fc_pf_rjt_reason -fc_seq_lookup_recip(struct fc_exch_mgr *mp, struct fc_frame *fp) +static enum fc_pf_rjt_reason fc_seq_lookup_recip(struct fc_exch_mgr *mp, + struct fc_frame *fp) { struct fc_frame_header *fh = fc_frame_header_get(fp); struct fc_exch *ep = NULL; @@ -994,9 +994,9 @@ static void fc_seq_send_ack(struct fc_seq *sp, const struct fc_frame *rx_fp) * Send BLS Reject. * This is for rejecting BA_ABTS only. */ -static void -fc_exch_send_ba_rjt(struct fc_frame *rx_fp, enum fc_ba_rjt_reason reason, - enum fc_ba_rjt_explan explan) +static void fc_exch_send_ba_rjt(struct fc_frame *rx_fp, + enum fc_ba_rjt_reason reason, + enum fc_ba_rjt_explan explan) { struct fc_frame *fp; struct fc_frame_header *rx_fh; diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 6f07de15c49..dae65133a83 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -179,8 +179,8 @@ EXPORT_SYMBOL(fc_set_rport_loss_tmo); * @flp: FLOGI payload structure * @maxval: upper limit, may be less than what is in the service parameters */ -static unsigned int -fc_plogi_get_maxframe(struct fc_els_flogi *flp, unsigned int maxval) +static unsigned int fc_plogi_get_maxframe(struct fc_els_flogi *flp, + unsigned int maxval) { unsigned int mfs; -- cgit v1.2.3 From fc47ff6b1b27fb736f255ed8cd490356e0cd228f Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:55:55 -0800 Subject: [SCSI] libfc, fcoe: Remove unnecessary cast by removing inline wrapper Comment from "Andrew Morton " > +{ > + return (struct fcoe_softc *)lport_priv(lp); unneeded/undesirable cast of void*. There are probably zillions of instances of this - there always are. This whole inline function was unnecessary. The FCoE layer knows that it's data structure is stored in the lport private data, it can just access it from lport_priv(). Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_sw.c | 2 +- drivers/scsi/fcoe/libfcoe.c | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index 007d1fbae80..f667dce1bbb 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -297,7 +297,7 @@ static int fcoe_sw_destroy(struct net_device *netdev) if (!lp) return -ENODEV; - fc = fcoe_softc(lp); + fc = lport_priv(lp); /* Logout of the fabric */ fc_fabric_logoff(lp); diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index d006d657681..02f044a8715 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -387,7 +387,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) WARN_ON((fr_len(fp) % sizeof(u32)) != 0); - fc = fcoe_softc(lp); + fc = lport_priv(lp); /* * if it is a flogi then we need to learn gw-addr * and my own fcid @@ -768,7 +768,7 @@ static int fcoe_check_wait_queue(struct fc_lport *lp) struct sk_buff *skb; struct fcoe_softc *fc; - fc = fcoe_softc(lp); + fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); /* @@ -805,7 +805,7 @@ static void fcoe_insert_wait_queue_head(struct fc_lport *lp, { struct fcoe_softc *fc; - fc = fcoe_softc(lp); + fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); __skb_queue_head(&fc->fcoe_pending_queue, skb); spin_unlock_bh(&fc->fcoe_pending_queue.lock); @@ -823,7 +823,7 @@ static void fcoe_insert_wait_queue(struct fc_lport *lp, { struct fcoe_softc *fc; - fc = fcoe_softc(lp); + fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); __skb_queue_tail(&fc->fcoe_pending_queue, skb); spin_unlock_bh(&fc->fcoe_pending_queue.lock); @@ -1113,7 +1113,7 @@ MODULE_PARM_DESC(destroy, "Destroy fcoe port"); */ int fcoe_link_ok(struct fc_lport *lp) { - struct fcoe_softc *fc = fcoe_softc(lp); + struct fcoe_softc *fc = lport_priv(lp); struct net_device *dev = fc->real_dev; struct ethtool_cmd ecmd = { ETHTOOL_GSET }; int rc = 0; @@ -1329,7 +1329,7 @@ int fcoe_hostlist_add(const struct fc_lport *lp) fc = fcoe_hostlist_lookup_softc(fcoe_netdev(lp)); if (!fc) { - fc = fcoe_softc(lp); + fc = lport_priv(lp); write_lock_bh(&fcoe_hostlist_lock); list_add_tail(&fc->list, &fcoe_hostlist); write_unlock_bh(&fcoe_hostlist_lock); -- cgit v1.2.3 From a468f328ad83f14556e5961ef1de80b32b428d32 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:56:00 -0800 Subject: [SCSI] fcoe: Use setup_timer() and mod_timer() Use helper functions for watchdog timer setup. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 02f044a8715..7887f2a7c2a 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -1435,11 +1435,9 @@ static int __init fcoe_init(void) */ fcoe_dev_setup(); - init_timer(&fcoe_timer); - fcoe_timer.data = 0; - fcoe_timer.function = fcoe_watchdog; - fcoe_timer.expires = (jiffies + (10 * HZ)); - add_timer(&fcoe_timer); + setup_timer(&fcoe_timer, fcoe_watchdog, 0); + + mod_timer(&fcoe_timer, jiffies + (10 * HZ)); /* initiatlize the fcoe transport */ fcoe_transport_init(); -- cgit v1.2.3 From 03ec862dff57ca3d1fcb439b99aadc45bc5c2f28 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:56:06 -0800 Subject: [SCSI] fcoe: Correct fcoe_transports initialization vs. registration The registration function shouldn't initialize the mutex or list head. The fcoe SW transport should initialize itself before registering. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fc_transport_fcoe.c | 3 --- drivers/scsi/fcoe/fcoe_sw.c | 5 +++++ 2 files changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fc_transport_fcoe.c b/drivers/scsi/fcoe/fc_transport_fcoe.c index 847453a70c6..8862758006c 100644 --- a/drivers/scsi/fcoe/fc_transport_fcoe.c +++ b/drivers/scsi/fcoe/fc_transport_fcoe.c @@ -258,9 +258,6 @@ int fcoe_transport_register(struct fcoe_transport *t) list_add_tail(&t->list, &fcoe_transports); mutex_unlock(&fcoe_transports_lock); - mutex_init(&t->devlock); - INIT_LIST_HEAD(&t->devlist); - printk(KERN_DEBUG "fcoe_transport_register:%s\n", t->name); return 0; diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index f667dce1bbb..37d359db164 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -467,10 +467,15 @@ int __init fcoe_sw_init(void) /* attach to scsi transport */ scsi_transport_fcoe_sw = fc_attach_transport(&fcoe_sw_transport_function); + if (!scsi_transport_fcoe_sw) { printk(KERN_ERR "fcoe_sw_init:fc_attach_transport() failed\n"); return -ENODEV; } + + mutex_init(&fcoe_sw_transport.devlock); + INIT_LIST_HEAD(&fcoe_sw_transport.devlist); + /* register sw transport */ fcoe_transport_register(&fcoe_sw_transport); return 0; -- cgit v1.2.3 From 422819cfa3a2605a0b3bdc33aaef0bc2feaeaada Mon Sep 17 00:00:00 2001 From: Yi Zou Date: Fri, 27 Feb 2009 10:56:11 -0800 Subject: [SCSI] libfc: do not change the fh_rx_id of a recevied frame We shouldn't be altering inbound frames. Signed-off-by: Yi Zou Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/libfc/fc_exch.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 7b933954c10..505825b6124 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -625,7 +625,6 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) { struct fc_exch *ep; struct fc_frame_header *fh; - u16 rxid; ep = mp->lp->tt.exch_get(mp->lp, fp); if (ep) { @@ -652,18 +651,6 @@ static struct fc_exch *fc_exch_resp(struct fc_exch_mgr *mp, struct fc_frame *fp) if ((ntoh24(fh->fh_f_ctl) & FC_FC_SEQ_INIT) == 0) ep->esb_stat &= ~ESB_ST_SEQ_INIT; - /* - * Set the responder ID in the frame header. - * The old one should've been 0xffff. - * If it isn't, don't assign one. - * Incoming basic link service frames may specify - * a referenced RX_ID. - */ - if (fh->fh_type != FC_TYPE_BLS) { - rxid = ntohs(fh->fh_rx_id); - WARN_ON(rxid != FC_XID_UNKNOWN); - fh->fh_rx_id = htons(ep->rxid); - } fc_exch_hold(ep); /* hold for caller */ spin_unlock_bh(&ep->ex_lock); /* lock from exch_get */ } -- cgit v1.2.3 From e904158159e9812d06646767b7c81846dc3b05e6 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 27 Feb 2009 10:56:22 -0800 Subject: [SCSI] fcoe: fix kfree(skb) Use kfree_skb instead of kfree for struct sk_buff pointers. Signed-off-by: Roel Kluin Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 7887f2a7c2a..7265e093799 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -437,7 +437,7 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) if (skb_is_nonlinear(skb)) { skb_frag_t *frag; if (fcoe_get_paged_crc_eof(skb, tlen)) { - kfree(skb); + kfree_skb(skb); return -ENOMEM; } frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1]; -- cgit v1.2.3 From c826a3145736e3baabebccfd0aecfbb6dae059f2 Mon Sep 17 00:00:00 2001 From: Vasu Dev Date: Fri, 27 Feb 2009 10:56:27 -0800 Subject: [SCSI] fcoe: Out of order tx frames was causing several check condition SCSI status frames followed by these errors in log. [sdp] Result: hostbyte=DID_OK driverbyte=DRIVER_SENSE,SUGGEST_OK [sdp] Sense Key : Aborted Command [current] [sdp] Add. Sense: Data phase error This was causing some test apps to exit due to write failure under heavy load. This was due to a race around adding and removing tx frame skb in fcoe_pending_queue, Chris Leech helped me to find that brief unlocking period when pulling skb from fcoe_pending_queue in various contexts (fcoe_watchdog and fcoe_xmit) and then adding skb back into fcoe_pending_queue up on a failed fcoe_start_io could change skb/tx frame order in fcoe_pending_queue. Thanks Chris. This patch allows only single context to pull skb from fcoe_pending_queue at any time to prevent above described ordering issue/race by use of fcoe_pending_queue_active flag. This patch simplified fcoe_watchdog with modified fcoe_check_wait_queue by use of FCOE_LOW_QUEUE_DEPTH instead previously used several conditionals to clear and set lp->qfull. I think FCOE_MAX_QUEUE_DEPTH with FCOE_LOW_QUEUE_DEPTH will work better in re/setting lp->qfull and these could be fine tuned for performance. Signed-off-by: Vasu Dev Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/fcoe_sw.c | 1 + drivers/scsi/fcoe/libfcoe.c | 45 +++++++++++++++++++++------------------------ 2 files changed, 22 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/fcoe_sw.c b/drivers/scsi/fcoe/fcoe_sw.c index 37d359db164..da210eba194 100644 --- a/drivers/scsi/fcoe/fcoe_sw.c +++ b/drivers/scsi/fcoe/fcoe_sw.c @@ -188,6 +188,7 @@ static int fcoe_sw_netdev_config(struct fc_lport *lp, struct net_device *netdev) skb_queue_head_init(&fc->fcoe_pending_queue); + fc->fcoe_pending_queue_active = 0; /* setup Source Mac Address */ memcpy(fc->ctl_src_addr, fc->real_dev->dev_addr, diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 7265e093799..14dd8a0402b 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -49,6 +49,7 @@ static int debug_fcoe; #define FCOE_MAX_QUEUE_DEPTH 256 +#define FCOE_LOW_QUEUE_DEPTH 32 /* destination address mode */ #define FCOE_GW_ADDR_MODE 0x00 @@ -723,21 +724,12 @@ static void fcoe_recv_flogi(struct fcoe_softc *fc, struct fc_frame *fp, u8 *sa) */ void fcoe_watchdog(ulong vp) { - struct fc_lport *lp; struct fcoe_softc *fc; - int qfilled = 0; read_lock(&fcoe_hostlist_lock); list_for_each_entry(fc, &fcoe_hostlist, list) { - lp = fc->lp; - if (lp) { - if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - qfilled = 1; - if (fcoe_check_wait_queue(lp) < FCOE_MAX_QUEUE_DEPTH) { - if (qfilled) - lp->qfull = 0; - } - } + if (fc->lp) + fcoe_check_wait_queue(fc->lp); } read_unlock(&fcoe_hostlist_lock); @@ -753,8 +745,8 @@ void fcoe_watchdog(ulong vp) * * This empties the wait_queue, dequeue the head of the wait_queue queue * and calls fcoe_start_io() for each packet, if all skb have been - * transmitted, return 0 if a error occurs, then restore wait_queue and - * try again later. + * transmitted, return qlen or -1 if a error occurs, then restore + * wait_queue and try again later. * * The wait_queue is used when the skb transmit fails. skb will go * in the wait_queue which will be emptied by the time function OR @@ -764,33 +756,38 @@ void fcoe_watchdog(ulong vp) */ static int fcoe_check_wait_queue(struct fc_lport *lp) { - int rc; struct sk_buff *skb; struct fcoe_softc *fc; + int rc = -1; fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); - /* - * if interface pending queue full then set qfull in lport. - */ - if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) - lp->qfull = 1; + if (fc->fcoe_pending_queue_active) + goto out; + fc->fcoe_pending_queue_active = 1; if (fc->fcoe_pending_queue.qlen) { while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { spin_unlock_bh(&fc->fcoe_pending_queue.lock); rc = fcoe_start_io(skb); - if (rc) { + if (rc) fcoe_insert_wait_queue_head(lp, skb); - return rc; - } spin_lock_bh(&fc->fcoe_pending_queue.lock); + if (rc) + break; } - if (fc->fcoe_pending_queue.qlen < FCOE_MAX_QUEUE_DEPTH) + /* + * if interface pending queue is below FCOE_LOW_QUEUE_DEPTH + * then clear qfull flag. + */ + if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) lp->qfull = 0; } + fc->fcoe_pending_queue_active = 0; + rc = fc->fcoe_pending_queue.qlen; +out: spin_unlock_bh(&fc->fcoe_pending_queue.lock); - return fc->fcoe_pending_queue.qlen; + return rc; } /** -- cgit v1.2.3 From 55c8bafba549e3e82f6999db8c5a62fc3c255c14 Mon Sep 17 00:00:00 2001 From: Chris Leech Date: Fri, 27 Feb 2009 10:56:32 -0800 Subject: [SCSI] fcoe: fix handling of pending queue, prevent out of order frames (v3) In fcoe_check_wait_queue() the queue length could temporarily drop to 0, before the last frame was successfully sent. This resulted in out of order data frames within a single sequence, leading to IO timeout errors. This builds on the approach from Vasu Dev to only fix the queue management in fcoe_check_wait_queue, where my first patch added locking to the transmit path even when the pending queue was not in use. This patch continues to use fcoe_pending_queue.qlen instead of introducing a new length counter, but takes precautions to ensure it never drops to 0 before the final frame in the queue has successfully been passed to the netdev qdisc layer. It also includes some cleanup of fcoe_check_wait_queue and removes the fcoe_insert_wait_queue(_head) wrapper functions. Signed-off-by: Chris Leech Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 81 ++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 14dd8a0402b..0e0b494fc17 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -70,8 +70,6 @@ struct fcoe_percpu_s *fcoe_percpu[NR_CPUS]; /* Function Prototyes */ static int fcoe_check_wait_queue(struct fc_lport *); -static void fcoe_insert_wait_queue_head(struct fc_lport *, struct sk_buff *); -static void fcoe_insert_wait_queue(struct fc_lport *, struct sk_buff *); static void fcoe_recv_flogi(struct fcoe_softc *, struct fc_frame *, u8 *); #ifdef CONFIG_HOTPLUG_CPU static int fcoe_cpu_callback(struct notifier_block *, ulong, void *); @@ -501,7 +499,9 @@ int fcoe_xmit(struct fc_lport *lp, struct fc_frame *fp) rc = fcoe_start_io(skb); if (rc) { - fcoe_insert_wait_queue(lp, skb); + spin_lock_bh(&fc->fcoe_pending_queue.lock); + __skb_queue_tail(&fc->fcoe_pending_queue, skb); + spin_unlock_bh(&fc->fcoe_pending_queue.lock); if (fc->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH) lp->qfull = 1; } @@ -756,33 +756,36 @@ void fcoe_watchdog(ulong vp) */ static int fcoe_check_wait_queue(struct fc_lport *lp) { + struct fcoe_softc *fc = lport_priv(lp); struct sk_buff *skb; - struct fcoe_softc *fc; int rc = -1; - fc = lport_priv(lp); spin_lock_bh(&fc->fcoe_pending_queue.lock); - if (fc->fcoe_pending_queue_active) goto out; fc->fcoe_pending_queue_active = 1; - if (fc->fcoe_pending_queue.qlen) { - while ((skb = __skb_dequeue(&fc->fcoe_pending_queue)) != NULL) { - spin_unlock_bh(&fc->fcoe_pending_queue.lock); - rc = fcoe_start_io(skb); - if (rc) - fcoe_insert_wait_queue_head(lp, skb); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - if (rc) - break; + + while (fc->fcoe_pending_queue.qlen) { + /* keep qlen > 0 until fcoe_start_io succeeds */ + fc->fcoe_pending_queue.qlen++; + skb = __skb_dequeue(&fc->fcoe_pending_queue); + + spin_unlock_bh(&fc->fcoe_pending_queue.lock); + rc = fcoe_start_io(skb); + spin_lock_bh(&fc->fcoe_pending_queue.lock); + + if (rc) { + __skb_queue_head(&fc->fcoe_pending_queue, skb); + /* undo temporary increment above */ + fc->fcoe_pending_queue.qlen--; + break; } - /* - * if interface pending queue is below FCOE_LOW_QUEUE_DEPTH - * then clear qfull flag. - */ - if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) - lp->qfull = 0; + /* undo temporary increment above */ + fc->fcoe_pending_queue.qlen--; } + + if (fc->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH) + lp->qfull = 0; fc->fcoe_pending_queue_active = 0; rc = fc->fcoe_pending_queue.qlen; out: @@ -790,42 +793,6 @@ out: return rc; } -/** - * fcoe_insert_wait_queue_head() - puts skb to fcoe pending queue head - * @lp: the fc_port for this skb - * @skb: the associated skb to be xmitted - * - * Returns: none - */ -static void fcoe_insert_wait_queue_head(struct fc_lport *lp, - struct sk_buff *skb) -{ - struct fcoe_softc *fc; - - fc = lport_priv(lp); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - __skb_queue_head(&fc->fcoe_pending_queue, skb); - spin_unlock_bh(&fc->fcoe_pending_queue.lock); -} - -/** - * fcoe_insert_wait_queue() - put the skb into fcoe pending queue tail - * @lp: the fc_port for this skb - * @skb: the associated skb to be xmitted - * - * Returns: none - */ -static void fcoe_insert_wait_queue(struct fc_lport *lp, - struct sk_buff *skb) -{ - struct fcoe_softc *fc; - - fc = lport_priv(lp); - spin_lock_bh(&fc->fcoe_pending_queue.lock); - __skb_queue_tail(&fc->fcoe_pending_queue, skb); - spin_unlock_bh(&fc->fcoe_pending_queue.lock); -} - /** * fcoe_dev_setup() - setup link change notification interface */ -- cgit v1.2.3 From 4469c195da43bf8220f53da8b576c0e154c2b662 Mon Sep 17 00:00:00 2001 From: Robert Love Date: Fri, 27 Feb 2009 10:56:38 -0800 Subject: [SCSI] fcoe: Change fcoe receive thread nice value from 19 (lowest priority) to -20 This change makes the fcoe Rx threads have the same nice value as lpfc and qla2xxx Rx threads. Signed-off-by: Robert Love Signed-off-by: James Bottomley --- drivers/scsi/fcoe/libfcoe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/fcoe/libfcoe.c b/drivers/scsi/fcoe/libfcoe.c index 0e0b494fc17..5548bf3bb58 100644 --- a/drivers/scsi/fcoe/libfcoe.c +++ b/drivers/scsi/fcoe/libfcoe.c @@ -531,7 +531,7 @@ int fcoe_percpu_receive_thread(void *arg) struct fcoe_softc *fc; struct fcoe_hdr *hp; - set_user_nice(current, 19); + set_user_nice(current, -20); while (!kthread_should_stop()) { -- cgit v1.2.3 From 6431c5dc5eeaa79863b4af300c081a01e2ccd0bb Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:00 -0800 Subject: [SCSI] qla2xxx: Correct address range checking for option-rom updates. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index f4c57227ec1..ee9d4015243 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -244,12 +244,6 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, if (ha->optrom_state != QLA_SWAITING) break; - if (start & 0xfff) { - qla_printk(KERN_WARNING, ha, - "Invalid start region 0x%x/0x%x.\n", start, size); - return -EINVAL; - } - ha->optrom_region_start = start; ha->optrom_region_size = start + size > ha->optrom_size ? ha->optrom_size - start : size; @@ -303,8 +297,7 @@ qla2x00_sysfs_write_optrom_ctl(struct kobject *kobj, else if (start == (ha->flt_region_boot * 4) || start == (ha->flt_region_fw * 4)) valid = 1; - else if ((IS_QLA25XX(ha) || IS_QLA81XX(ha)) && - start == (ha->flt_region_vpd_nvram * 4)) + else if (IS_QLA25XX(ha) || IS_QLA81XX(ha)) valid = 1; if (!valid) { qla_printk(KERN_WARNING, ha, -- cgit v1.2.3 From 605aa2bcd5e9dddc4666f12e0c19822809186d6d Mon Sep 17 00:00:00 2001 From: Lalit Chandivade Date: Thu, 5 Mar 2009 11:07:01 -0800 Subject: [SCSI] qla2xxx: Use correct value for max vport in LOOP topology. Use minimum value for max vport during firmware initialization in LOOP topology. Using max vport value from get resource count in LOOP topology causes firmware initialization failure. Signed-off-by: Lalit Chandivade Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 986501759ad..14325c02733 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -1308,8 +1308,12 @@ qla2x00_init_rings(scsi_qla_host_t *vha) DEBUG(printk("scsi(%ld): Issue init firmware.\n", vha->host_no)); - if (ha->flags.npiv_supported) + if (ha->flags.npiv_supported) { + if (ha->operating_mode == LOOP) + ha->max_npiv_vports = MIN_MULTI_ID_FABRIC - 1; mid_init_cb->count = cpu_to_le16(ha->max_npiv_vports); + } + mid_init_cb->options = __constant_cpu_to_le16(BIT_1); -- cgit v1.2.3 From ee546b6e048586381462ce7bb51c7ddc03819619 Mon Sep 17 00:00:00 2001 From: Anirban Chakraborty Date: Thu, 5 Mar 2009 11:07:02 -0800 Subject: [SCSI] qla2xxx: Correct vport delete bug. Signed-off-by: Anirban Chakraborty Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 11 +++++++---- drivers/scsi/qla2xxx/qla_mbx.c | 3 ++- drivers/scsi/qla2xxx/qla_mid.c | 10 ++++++---- 3 files changed, 15 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 14325c02733..e54ab2f1079 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -2614,6 +2614,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, port_id_t wrap, nxt_d_id; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp, *base_vha = pci_get_drvdata(ha->pdev); + struct scsi_qla_host *tvp; rval = QLA_SUCCESS; @@ -2713,7 +2714,7 @@ qla2x00_find_all_fabric_devs(scsi_qla_host_t *vha, /* Bypass virtual ports of the same host. */ found = 0; if (ha->num_vhosts) { - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (new_fcport->d_id.b24 == vp->d_id.b24) { found = 1; break; @@ -2836,6 +2837,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) uint16_t first_loop_id; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp; + struct scsi_qla_host *tvp; rval = QLA_SUCCESS; @@ -2860,7 +2862,7 @@ qla2x00_find_new_loop_id(scsi_qla_host_t *vha, fc_port_t *dev) /* Check for loop ID being already in use. */ found = 0; fcport = NULL; - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { list_for_each_entry(fcport, &vp->vp_fcports, list) { if (fcport->loop_id == dev->loop_id && fcport != dev) { @@ -3295,6 +3297,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) uint8_t status = 0; struct qla_hw_data *ha = vha->hw; struct scsi_qla_host *vp; + struct scsi_qla_host *tvp; struct req_que *req = ha->req_q_map[0]; if (vha->flags.online) { @@ -3310,7 +3313,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) if (atomic_read(&vha->loop_state) != LOOP_DOWN) { atomic_set(&vha->loop_state, LOOP_DOWN); qla2x00_mark_all_devices_lost(vha, 0); - list_for_each_entry(vp, &ha->vp_list, list) + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) qla2x00_mark_all_devices_lost(vp, 0); } else { if (!atomic_read(&vha->loop_down_timer)) @@ -3407,7 +3410,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) DEBUG(printk(KERN_INFO "qla2x00_abort_isp(%ld): succeeded.\n", vha->host_no)); - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (vp->vp_idx) qla2x00_vp_abort_isp(vp); } diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index 4c7504cb399..4aab7acf752 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2685,6 +2685,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, uint16_t stat = le16_to_cpu(rptid_entry->vp_idx); struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; + scsi_qla_host_t *tvp; if (rptid_entry->entry_status != 0) return; @@ -2710,7 +2711,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *vha, if (MSB(stat) == 1) return; - list_for_each_entry(vp, &ha->vp_list, list) + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) if (vp_idx == vp->vp_idx) break; if (!vp) diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 3f23932210c..785c61279e6 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -69,9 +69,10 @@ static scsi_qla_host_t * qla24xx_find_vhost_by_name(struct qla_hw_data *ha, uint8_t *port_name) { scsi_qla_host_t *vha; + struct scsi_qla_host *tvha; /* Locate matching device in database. */ - list_for_each_entry(vha, &ha->vp_list, list) { + list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { if (!memcmp(port_name, vha->port_name, WWN_SIZE)) return vha; } @@ -194,11 +195,11 @@ qla24xx_configure_vp(scsi_qla_host_t *vha) void qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb) { - scsi_qla_host_t *vha; + scsi_qla_host_t *vha, *tvha; struct qla_hw_data *ha = rsp->hw; int i = 0; - list_for_each_entry(vha, &ha->vp_list, list) { + list_for_each_entry_safe(vha, tvha, &ha->vp_list, list) { if (vha->vp_idx) { switch (mb[0]) { case MBA_LIP_OCCURRED: @@ -300,6 +301,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) int ret; struct qla_hw_data *ha = vha->hw; scsi_qla_host_t *vp; + struct scsi_qla_host *tvp; if (vha->vp_idx) return; @@ -308,7 +310,7 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha) clear_bit(VP_DPC_NEEDED, &vha->dpc_flags); - list_for_each_entry(vp, &ha->vp_list, list) { + list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) { if (vp->vp_idx) ret = qla2x00_do_dpc_vp(vp); } -- cgit v1.2.3 From c6b2fca8205dc33e3bb444835769e4ea4c6bc58d Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:03 -0800 Subject: [SCSI] qla2xxx: Correct truncation in return-code status checking. QLA_* return codes are 'int' in size. There were still several legacy check-points which assumed a return-code width of 8-bits. This could cause incorrect assumptions of 'good' status if a return of QLA_FUNCTION_TIMEOUT. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e54ab2f1079..87f9abc7146 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3435,7 +3435,7 @@ qla2x00_abort_isp(scsi_qla_host_t *vha) static int qla2x00_restart_isp(scsi_qla_host_t *vha) { - uint8_t status = 0; + int status = 0; uint32_t wait_time; struct qla_hw_data *ha = vha->hw; struct req_que *req = ha->req_q_map[0]; diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 2f5f72531e2..16c34760b95 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2568,7 +2568,7 @@ qla2x00_do_work(struct scsi_qla_host *vha) void qla2x00_relogin(struct scsi_qla_host *vha) { fc_port_t *fcport; - uint8_t status; + int status; uint16_t next_loopid = 0; struct qla_hw_data *ha = vha->hw; -- cgit v1.2.3 From ca42f2b5f58702e5751e1423bd2f7987b0760eab Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:04 -0800 Subject: [SCSI] qla2xxx: Correct overwrite of pre-assigned init-control-block structure size. The value is already pre-assigned prior to the qla2x00_mem_alloc(). Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 16c34760b95..3ddfa889e94 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -2222,10 +2222,6 @@ qla2x00_mem_alloc(struct qla_hw_data *ha, uint16_t req_len, uint16_t rsp_len, { char name[16]; - ha->init_cb_size = sizeof(init_cb_t); - if (IS_QLA2XXX_MIDTYPE(ha)) - ha->init_cb_size = sizeof(struct mid_init_cb_24xx); - ha->init_cb = dma_alloc_coherent(&ha->pdev->dev, ha->init_cb_size, &ha->init_cb_dma, GFP_KERNEL); if (!ha->init_cb) -- cgit v1.2.3 From 5fa0ae19822d60307059ee64b80ba9e5effdce58 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Thu, 5 Mar 2009 11:07:05 -0800 Subject: [SCSI] qla2xxx: Update version number to 8.03.00-k4. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_version.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h index 79f7053da99..a772eab2f0e 100644 --- a/drivers/scsi/qla2xxx/qla_version.h +++ b/drivers/scsi/qla2xxx/qla_version.h @@ -7,7 +7,7 @@ /* * Driver version */ -#define QLA2XXX_VERSION "8.03.00-k3" +#define QLA2XXX_VERSION "8.03.00-k4" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 3 -- cgit v1.2.3 From b70d11da61d751ad968c6f686d83ac1b0ae41466 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kristian=20H=C3=B8gsberg?= Date: Tue, 3 Mar 2009 14:45:57 -0500 Subject: drm: Return EINVAL on duplicate objects in execbuffer object list MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If userspace passes an object list with the same object appearing more than once, we end up hitting the BUG_ON() in i915_gem_object_set_to_gpu_domain() as it gets called a second time for the same object. Signed-off-by: Kristian Høgsberg Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 6 ++++++ drivers/gpu/drm/i915/i915_gem.c | 17 ++++++++++++++++- 2 files changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 17fa40858d2..9186d43be01 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -457,6 +457,12 @@ struct drm_i915_gem_object { /** for phy allocated objects */ struct drm_i915_gem_phys_object *phys_obj; + + /** + * Used for checking the object doesn't appear more than once + * in an execbuffer object list. + */ + int in_execbuffer; }; /** diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 85685bfd12d..7bdcc752f13 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2469,6 +2469,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, struct drm_i915_gem_exec_object *exec_list = NULL; struct drm_gem_object **object_list = NULL; struct drm_gem_object *batch_obj; + struct drm_i915_gem_object *obj_priv; int ret, i, pinned = 0; uint64_t exec_offset; uint32_t seqno, flush_domains; @@ -2533,6 +2534,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, ret = -EBADF; goto err; } + + obj_priv = object_list[i]->driver_private; + if (obj_priv->in_execbuffer) { + DRM_ERROR("Object %p appears more than once in object list\n", + object_list[i]); + ret = -EBADF; + goto err; + } + obj_priv->in_execbuffer = true; } /* Pin and relocate */ @@ -2674,8 +2684,13 @@ err: for (i = 0; i < pinned; i++) i915_gem_object_unpin(object_list[i]); - for (i = 0; i < args->buffer_count; i++) + for (i = 0; i < args->buffer_count; i++) { + if (object_list[i]) { + obj_priv = object_list[i]->driver_private; + obj_priv->in_execbuffer = false; + } drm_gem_object_unreference(object_list[i]); + } mutex_unlock(&dev->struct_mutex); -- cgit v1.2.3 From 0fce81e3ccd093f4826de40fbd27fac9632f6170 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sat, 28 Feb 2009 15:01:16 -0500 Subject: i915: add newline to i915_gem_object_pin failure msg Prevents formatting nasty as below: [drm:i915_gem_object_pin] *ERROR* Failure to bind: -12<3>[drm:i915_gem_evict_something] *ERROR* inactive empty 1 request empty 1 flushing empty 1 Signed-off-by: Kyle McMartin Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 7bdcc752f13..c94069b28a4 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2727,7 +2727,7 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) ret = i915_gem_object_bind_to_gtt(obj, alignment); if (ret != 0) { if (ret != -EBUSY && ret != -ERESTARTSYS) - DRM_ERROR("Failure to bind: %d", ret); + DRM_ERROR("Failure to bind: %d\n", ret); return ret; } /* -- cgit v1.2.3 From 66824bd7b5dc22da367595359bfcd1149c4ce92a Mon Sep 17 00:00:00 2001 From: Pierre Willenbrock Date: Wed, 25 Feb 2009 17:49:51 +0100 Subject: drm/i915: Don't restore palettes through VGA registers. The VGA registers just hit the pipe registers that we already set through MMIO. This fixes strange colors on resume. Signed-off-by: Pierre Willenbrock Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_drv.h | 1 - drivers/gpu/drm/i915/i915_suspend.c | 11 ----------- 2 files changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 9186d43be01..d6cc9861e0a 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h @@ -279,7 +279,6 @@ typedef struct drm_i915_private { u8 saveAR_INDEX; u8 saveAR[21]; u8 saveDACMASK; - u8 saveDACDATA[256*3]; /* 256 3-byte colors */ u8 saveCR[37]; struct { diff --git a/drivers/gpu/drm/i915/i915_suspend.c b/drivers/gpu/drm/i915/i915_suspend.c index 5d84027ee8f..d669cc2b42c 100644 --- a/drivers/gpu/drm/i915/i915_suspend.c +++ b/drivers/gpu/drm/i915/i915_suspend.c @@ -119,11 +119,6 @@ static void i915_save_vga(struct drm_device *dev) /* VGA color palette registers */ dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK); - /* DACCRX automatically increments during read */ - I915_WRITE8(VGA_DACRX, 0); - /* Read 3 bytes of color data from each index */ - for (i = 0; i < 256 * 3; i++) - dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA); /* MSR bits */ dev_priv->saveMSR = I915_READ8(VGA_MSR_READ); @@ -225,12 +220,6 @@ static void i915_restore_vga(struct drm_device *dev) /* VGA color palette registers */ I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK); - /* DACCRX automatically increments during read */ - I915_WRITE8(VGA_DACWX, 0); - /* Read 3 bytes of color data from each index */ - for (i = 0; i < 256 * 3; i++) - I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]); - } int i915_save_state(struct drm_device *dev) -- cgit v1.2.3 From 040aefa263aa9cd7bd5df50586c35e1e15e77f84 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 10 Mar 2009 12:31:12 -0700 Subject: drm/i915: Fix bad \n in MTRR failure notice. Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 6dab63bdc4c..6d21b9e48b8 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c @@ -1105,7 +1105,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) 1024 * 1024, MTRR_TYPE_WRCOMB, 1); if (dev_priv->mm.gtt_mtrr < 0) { - DRM_INFO("MTRR allocation failed\n. Graphics " + DRM_INFO("MTRR allocation failed. Graphics " "performance may suffer.\n"); } -- cgit v1.2.3 From 48e7a3c95c9f98c2cb6f894820e3cc2d0448e92f Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 10 Mar 2009 22:43:56 +0100 Subject: HID: fix incorrect free in hiddev If hiddev_open() fails, it wrongly frees the shared hiddev structure kept in hiddev_table instead of the hiddev_list structure allocated for the opened file descriptor. Existing references to this structure will then accessed free memory. This was introduced by 079034073 "HID: hiddev cleanup -- handle all error conditions properly". Signed-off-by: Johannes Weiner Cc: Oliver Neukum Cc: Jiri Kosina Signed-off-by: Andrew Morton Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 4940e4d70c2..00ea1ed282a 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -306,7 +306,7 @@ static int hiddev_open(struct inode *inode, struct file *file) return 0; bail: file->private_data = NULL; - kfree(list->hiddev); + kfree(list); return res; } -- cgit v1.2.3 From 96fe2ab830d7dffee1b3d8abf27ced4d7d5765e7 Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Tue, 10 Mar 2009 22:44:01 +0100 Subject: HID: fix waitqueue usage in hiddev DECLARE_WAITQUEUE doesn't initialize the wait descriptor's task_list to 'empty' but to zero. prepare_to_wait() will not enqueue the descriptor to the waitqueue and finish_wait() will do list_del_init() on a list head that contains NULL pointers, which oopses. This was introduced by 079034073 "HID: hiddev cleanup -- handle all error conditions properly". The prior code used an unconditional add_to_waitqueue() which didn't care about the wait descriptor's list head and enqueued the thing unconditionally. The new code uses prepare_to_wait() which DOES check the prior list state, so use DEFINE_WAIT instead. Signed-off-by: Johannes Weiner Cc: Oliver Neukum Cc: Jiri Kosina Signed-off-by: Andrew Morton Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 00ea1ed282a..1f5b5d4c3c3 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -323,7 +323,7 @@ static ssize_t hiddev_write(struct file * file, const char __user * buffer, size */ static ssize_t hiddev_read(struct file * file, char __user * buffer, size_t count, loff_t *ppos) { - DECLARE_WAITQUEUE(wait, current); + DEFINE_WAIT(wait); struct hiddev_list *list = file->private_data; int event_size; int retval; -- cgit v1.2.3 From 475049809977bf3975d78f2d2fd992e19ce2d59e Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Tue, 10 Mar 2009 12:55:45 -0700 Subject: mm: get_nid_for_pfn() returns int get_nid_for_pfn() returns int Presumably the (nid < 0) case has never happened. We do know that it is happening on one system while creating a symlink for a memory section so it should also happen on the same system if unregister_mem_sect_under_nodes() were called to remove the same symlink. The test was actually added in response to a problem with an earlier version reported by Yasunori Goto where one or more of the leading pages of a memory section on the 2nd node of one of his systems was uninitialized because I believe they coincided with a memory hole. That earlier version did not ignore uninitialized pages and determined the nid by considering only the 1st page of each memory section. This caused the symlink to the 1st memory section on the 2nd node to be incorrectly created in /sys/devices/system/node/node0 instead of /sys/devices/system/node/node1. The problem was fixed by adding the test to skip over uninitialized pages. I suspect we have not seen any reports of the non-removal of a symlink due to the incorrect declaration of the nid variable in unregister_mem_sect_under_nodes() because - systems where a memory section could have an uninitialized range of leading pages are probably rare. - memory remove is probably not done very frequently on the systems that are capable of demonstrating the problem. - lingering symlink(s) that should have been removed may have simply gone unnoticed. [garyhade@us.ibm.com: wrote changelog] Signed-off-by: Roel Kluin Cc: Gary Hade Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/base/node.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/node.c b/drivers/base/node.c index 43fa90b837e..f8f578a71b2 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c @@ -303,7 +303,7 @@ int unregister_mem_sect_under_nodes(struct memory_block *mem_blk) sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index); sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1; for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) { - unsigned int nid; + int nid; nid = get_nid_for_pfn(pfn); if (nid < 0) -- cgit v1.2.3 From c15ade65788b70797c947f7de3e049e6a23f407f Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 10 Mar 2009 12:55:47 -0700 Subject: lm85: fix the version check that broke adt7468 probing The verstep check in the lm85 driver fails because the upper nibble of the version register is 0x7, not 0x6, on the adt7468 chip. Probing of all adt7468s was broken by 69fc1feba2d5856ff74dedb6ae9d8c490210825c ("hwmon: (lm85) Rework the device detection"), and this patch fixes that. Also add in a missing i2c_device_id that accidentally got dropped from the original patch. Signed-off-by: Darrick J. Wong Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/lm85.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index cfc1ee90f5a..cf1422ef6ef 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -72,6 +72,7 @@ I2C_CLIENT_INSMOD_7(lm85b, lm85c, adm1027, adt7463, adt7468, emc6d100, #define LM85_COMPANY_SMSC 0x5c #define LM85_VERSTEP_VMASK 0xf0 #define LM85_VERSTEP_GENERIC 0x60 +#define LM85_VERSTEP_GENERIC2 0x70 #define LM85_VERSTEP_LM85C 0x60 #define LM85_VERSTEP_LM85B 0x62 #define LM85_VERSTEP_ADM1027 0x60 @@ -334,6 +335,7 @@ static struct lm85_data *lm85_update_device(struct device *dev); static const struct i2c_device_id lm85_id[] = { { "adm1027", adm1027 }, { "adt7463", adt7463 }, + { "adt7468", adt7468 }, { "lm85", any_chip }, { "lm85b", lm85b }, { "lm85c", lm85c }, @@ -1153,7 +1155,8 @@ static int lm85_detect(struct i2c_client *client, int kind, address, company, verstep); /* All supported chips have the version in common */ - if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC) { + if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC && + (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) { dev_dbg(&adapter->dev, "Autodetection failed: " "unsupported version\n"); return -ENODEV; -- cgit v1.2.3 From 8ef1f0291a5d126f678b2f0225843c1ab550559c Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 10 Mar 2009 12:55:48 -0700 Subject: lm85: add VRM10 support for adt7468 chip The adt7468 chip supports VRM10 sensors just like the adt7463; add a missing check for it. Signed-off-by: Darrick J. Wong Cc: Jean Delvare Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/hwmon/lm85.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index cf1422ef6ef..b251d8674b4 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -410,7 +410,8 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, struct lm85_data *data = lm85_update_device(dev); int vid; - if (data->type == adt7463 && (data->vid & 0x80)) { + if ((data->type == adt7463 || data->type == adt7468) && + (data->vid & 0x80)) { /* 6-pin VID (VRM 10) */ vid = vid_from_reg(data->vid & 0x3f, data->vrm); } else { -- cgit v1.2.3 From 2f68891314b14e7e0ef07b4e77a8ea6e917fc74b Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Tue, 10 Mar 2009 12:55:50 -0700 Subject: x86/agp: tighten check to update amd nb aperture Impact: fix bug to make agp work with dri Jeffrey reported that dri does work with 64bit, but doesn't work with 32bit it turns out NB aperture is 32M, aperture on agp is 128M 64bit is using 64M for vaidation for 64 iommu/gart 32bit is only using 32M..., and will not update the nb aperture. So try to compare nb apterture and agp apterture before leaving not touch nb aperture. Reported-by: Jeffrey Trull Tested-by: Jeffrey Trull Signed-off-by: Yinghai Lu Acked-by: Dave Airlie Cc: Ingo Molnar Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/agp/amd64-agp.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 52f4361eb6e..d765afda9c2 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c @@ -271,15 +271,15 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, nb_order = (nb_order >> 1) & 7; pci_read_config_dword(nb, AMD64_GARTAPERTUREBASE, &nb_base); nb_aper = nb_base << 25; - if (agp_aperture_valid(nb_aper, (32*1024*1024)<= order) { + if (agp_aperture_valid(nb_aper, (32*1024*1024)<dev, "aperture from AGP @ %Lx size %u MB\n", aper, 32 << order); if (order < 0 || !agp_aperture_valid(aper, (32*1024*1024)< Date: Tue, 10 Mar 2009 12:55:53 -0700 Subject: mtd_dataflash: fix probing of AT45DB321C chips. Commit 771999b65f79264acde4b855e5d35696eca5e80c ("[MTD] DataFlash: bugfix, binary page sizes now handled") broke support for probing AT45DB321C flash chips. These chips do not support the "page size" status bit, so if we match the JEDEC id return early. [akpm@linux-foundation.org: coding-style fixes] Signed-off-by: Will Newton Cc: David Woodhouse Acked-by: David Brownell Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/devices/mtd_dataflash.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/devices/mtd_dataflash.c b/drivers/mtd/devices/mtd_dataflash.c index d44f741ae22..6d9f810565c 100644 --- a/drivers/mtd/devices/mtd_dataflash.c +++ b/drivers/mtd/devices/mtd_dataflash.c @@ -821,7 +821,8 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi) if (!(info->flags & IS_POW2PS)) return info; } - } + } else + return info; } } -- cgit v1.2.3 From 9c1e8a4ebcc04226cb6f3a1bf1d72f4cafd6b089 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 10 Mar 2009 12:55:54 -0700 Subject: intel-agp: fix a panic with 1M of shared memory, no GTT entries When GTT size is equal to amount of video memory, the amount of GTT entries is computed lower than zero, which is invalid and leads to off-by-one error in intel_i915_configure() Originally posted here: http://bugzilla.kernel.org/show_bug.cgi?id=12539 http://bugzilla.redhat.com/show_bug.cgi?id=445592 Signed-off-by: Lubomir Rintel Cc: Lubomir Rintel Cc: Dave Airlie Reviewed-by: Eric Anholt Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/agp/intel-agp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index c7714185f83..4373adb2119 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c @@ -633,13 +633,15 @@ static void intel_i830_init_gtt_entries(void) break; } } - if (gtt_entries > 0) + if (gtt_entries > 0) { dev_info(&agp_bridge->dev->dev, "detected %dK %s memory\n", gtt_entries / KB(1), local ? "local" : "stolen"); - else + gtt_entries /= KB(4); + } else { dev_info(&agp_bridge->dev->dev, "no pre-allocated video memory detected\n"); - gtt_entries /= KB(4); + gtt_entries = 0; + } intel_private.gtt_entries = gtt_entries; } -- cgit v1.2.3 From d58ab5cf09679d8cb4824e22cae900c0eab5ab31 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Tue, 10 Mar 2009 12:55:55 -0700 Subject: mtd: physmap: fix NULL pointer dereference in error path commit e480814f138cd5d78a8efe397756ba6b6518fdb6 ("[MTD] [MAPS] physmap: fix wrong free and del_mtd_{partition,device}") introduces a NULL pointer dereference in physmap_flash_remove when called from the error path in physmap_flash_probe (if map_probe failed). Call del_mtd_{partition,device} only if info->cmtd was not NULL. Reported-by: pHilipp Zabel Signed-off-by: Atsushi Nemoto Cc: David Woodhouse Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mtd/maps/physmap.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/maps/physmap.c b/drivers/mtd/maps/physmap.c index 4b122e7ab4b..229718222db 100644 --- a/drivers/mtd/maps/physmap.c +++ b/drivers/mtd/maps/physmap.c @@ -46,16 +46,19 @@ static int physmap_flash_remove(struct platform_device *dev) physmap_data = dev->dev.platform_data; + if (info->cmtd) { #ifdef CONFIG_MTD_PARTITIONS - if (info->nr_parts) { - del_mtd_partitions(info->cmtd); - kfree(info->parts); - } else if (physmap_data->nr_parts) - del_mtd_partitions(info->cmtd); - else - del_mtd_device(info->cmtd); + if (info->nr_parts || physmap_data->nr_parts) + del_mtd_partitions(info->cmtd); + else + del_mtd_device(info->cmtd); #else - del_mtd_device(info->cmtd); + del_mtd_device(info->cmtd); +#endif + } +#ifdef CONFIG_MTD_PARTITIONS + if (info->nr_parts) + kfree(info->parts); #endif #ifdef CONFIG_MTD_CONCAT -- cgit v1.2.3 From 16b71fdf97599f1b1b7f38418ee9922d9f117396 Mon Sep 17 00:00:00 2001 From: Samuel CUELLA Date: Tue, 10 Mar 2009 12:56:00 -0700 Subject: i810: fix kernel crash fix when struct fb_var_screeninfo is supplied Prevent the kernel from being crashed by a divide-by-zero operation when supplied an incorrectly filled 'struct fb_var_screeninfo' from userland. Previously i810_main.c:1005 (i810_check_params) was using the global 'yres' symbol previously defined at i810_main.c:145 as a module parameter value holder (i810_main.c:2174). If i810fb is compiled-in or if this param doesn't get a default value, this direct usage leads to a divide-by-zero at i810_main.c:1005 (i810_check_params). The patch simply replace the 'yres' global, perhaps undefined symbol usage by a given parameter structure lookup. This problem occurs with directfb, mplayer -vo fbdev, SDL library. It was also reported ( but non solved ) at: http://mail.directfb.org/pipermail/directfb-dev/2008-March/004050.html Signed-off-by: Samuel CUELLA Cc: Jiri Kosina Cc: Krzysztof Helt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/i810/i810_main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/i810/i810_main.c b/drivers/video/i810/i810_main.c index a24e680d2b9..2e940199fc8 100644 --- a/drivers/video/i810/i810_main.c +++ b/drivers/video/i810/i810_main.c @@ -993,6 +993,7 @@ static int i810_check_params(struct fb_var_screeninfo *var, struct i810fb_par *par = info->par; int line_length, vidmem, mode_valid = 0, retval = 0; u32 vyres = var->yres_virtual, vxres = var->xres_virtual; + /* * Memory limit */ @@ -1002,12 +1003,12 @@ static int i810_check_params(struct fb_var_screeninfo *var, if (vidmem > par->fb.size) { vyres = par->fb.size/line_length; if (vyres < var->yres) { - vyres = yres; + vyres = info->var.yres; vxres = par->fb.size/vyres; vxres /= var->bits_per_pixel >> 3; line_length = get_line_length(par, vxres, var->bits_per_pixel); - vidmem = line_length * yres; + vidmem = line_length * info->var.yres; if (vxres < var->xres) { printk("i810fb: required video memory, " "%d bytes, for %dx%d-%d (virtual) " -- cgit v1.2.3 From 187cfc439f7b1a7c91ff72d561b2a7c9c0b83431 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 9 Mar 2009 14:36:15 +0000 Subject: hvc_console: Remove tty->low_latency on pseries backends The hvcs and hvsi backends both set tty->low_latency to one, along with more or less scary comments regarding bugs or races that would happen if not doing so. However, they also both call tty_flip_buffer_push() in conexts where it's illegal to do so since some recent tty changes (or at least it may have been illegal always but it nows blows) when low_latency is set (ie, hard interrupt or with spinlock held and irqs disabled). This removes the setting for now to get them back to working condition, we'll have to address the races described in the comments separately if they are still an issue (some of this might have been fixed already). Signed-off-by: Benjamin Herrenschmidt --- drivers/char/hvcs.c | 9 --------- drivers/char/hvsi.c | 1 - 2 files changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c index 6e6eb445d37..c76bccf5354 100644 --- a/drivers/char/hvcs.c +++ b/drivers/char/hvcs.c @@ -1139,15 +1139,6 @@ static int hvcs_open(struct tty_struct *tty, struct file *filp) hvcsd->tty = tty; tty->driver_data = hvcsd; - /* - * Set this driver to low latency so that we actually have a chance at - * catching a throttled TTY after we flip_buffer_push. Otherwise the - * flush_to_async may not execute until after the kernel_thread has - * yielded and resumed the next flip_buffer_push resulting in data - * loss. - */ - tty->low_latency = 1; - memset(&hvcsd->buffer[0], 0x00, HVCS_BUFF_LEN); /* diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c index 406f8742a26..2989056a9e3 100644 --- a/drivers/char/hvsi.c +++ b/drivers/char/hvsi.c @@ -810,7 +810,6 @@ static int hvsi_open(struct tty_struct *tty, struct file *filp) hp = &hvsi_ports[line]; tty->driver_data = hp; - tty->low_latency = 1; /* avoid throttle/tty_flip_buffer_push race */ mb(); if (hp->state == HVSI_FSP_DIED) -- cgit v1.2.3 From d801cec70d69d2d4121e133edd5c3237fe0e0078 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Wed, 11 Mar 2009 10:45:17 +1100 Subject: radeonfb/aty128fb: Disable broken early resume hook for PowerBooks radeonfb and aty128fb have a special hook called by the PowerMac platform code very very early on resume from sleep to bring the screen back. This is useful for debugging wakup problems, but unfortunately, this also became a source of problems of its own. The hook is called extremely early, with interrupts still off, and the code path involved with that code nowadays rely on things like taking mutexes, GFP_KERNEL allocations, etc... In addition, the driver now relies on the PCI core to restore the standard config space before calling resume which doesn't happen with this early code path. I'm keeping the code in but commented out along with a fixup call to pci_restore_state(). The reason is that I still want to make it easy to re-enable temporarily to track wake up problems, and it's possible that I can revive it at some stage if we make sleeping things save to call in early resume using a system state. In the meantime, this should fix several reported regressions. Signed-off-by: Benjamin Herrenschmidt --- drivers/video/aty/aty128fb.c | 10 +++++++++- drivers/video/aty/radeon_pm.c | 10 +++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/video/aty/aty128fb.c b/drivers/video/aty/aty128fb.c index 2181ce4d7eb..35e8eb02b9e 100644 --- a/drivers/video/aty/aty128fb.c +++ b/drivers/video/aty/aty128fb.c @@ -1853,13 +1853,14 @@ static void aty128_bl_exit(struct backlight_device *bd) * Initialisation */ -#ifdef CONFIG_PPC_PMAC +#ifdef CONFIG_PPC_PMAC__disabled static void aty128_early_resume(void *data) { struct aty128fb_par *par = data; if (try_acquire_console_sem()) return; + pci_restore_state(par->pdev); aty128_do_resume(par->pdev); release_console_sem(); } @@ -1907,7 +1908,14 @@ static int __devinit aty128_init(struct pci_dev *pdev, const struct pci_device_i /* Indicate sleep capability */ if (par->chip_gen == rage_M3) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, NULL, 0, 1); +#if 0 /* Disable the early video resume hack for now as it's causing problems, among + * others we now rely on the PCI core restoring the config space for us, which + * isn't the case with that hack, and that code path causes various things to + * be called with interrupts off while they shouldn't. I'm leaving the code in + * as it can be useful for debugging purposes + */ pmac_set_early_video_resume(aty128_early_resume, par); +#endif } /* Find default mode */ diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index ca5f0dc2854..81603f85e17 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2762,12 +2762,13 @@ int radeonfb_pci_resume(struct pci_dev *pdev) return rc; } -#ifdef CONFIG_PPC_OF +#ifdef CONFIG_PPC_OF__disabled static void radeonfb_early_resume(void *data) { struct radeonfb_info *rinfo = data; rinfo->no_schedule = 1; + pci_restore_state(rinfo->pdev); radeonfb_pci_resume(rinfo->pdev); rinfo->no_schedule = 0; } @@ -2834,7 +2835,14 @@ void radeonfb_pm_init(struct radeonfb_info *rinfo, int dynclk, int ignore_devlis */ if (rinfo->pm_mode != radeon_pm_none) { pmac_call_feature(PMAC_FTR_DEVICE_CAN_WAKE, rinfo->of_node, 0, 1); +#if 0 /* Disable the early video resume hack for now as it's causing problems, among + * others we now rely on the PCI core restoring the config space for us, which + * isn't the case with that hack, and that code path causes various things to + * be called with interrupts off while they shouldn't. I'm leaving the code in + * as it can be useful for debugging purposes + */ pmac_set_early_video_resume(radeonfb_early_resume, rinfo); +#endif } #if 0 -- cgit v1.2.3 From 9b2412f9ad0a3913baa40c270d6e1fa3c6d50067 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Feb 2009 14:26:44 +0000 Subject: drm/i915: First recheck for an empty fence register. If we wait upon a request and successfully unbind a buffer occupying a fence register, then that slot will be freed and cause a NULL derefrence upon rescanning. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index c94069b28a4..6497c1ad02d 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1580,6 +1580,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) } /* First try to find a free reg */ +try_again: for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { reg = &dev_priv->fence_regs[i]; if (!reg->obj) @@ -1591,7 +1592,6 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) struct drm_i915_gem_object *old_obj_priv = NULL; loff_t offset; -try_again: /* Could try to use LRU here instead... */ for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { -- cgit v1.2.3 From 22c344e9a03beeb7071a588a973012749f84a830 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Feb 2009 14:26:45 +0000 Subject: drm/i915: Check fence status on every pin. As we may steal the fence register of an unpinned buffer for another, every time we repin the buffer we need to recheck whether it needs to be allocated a fence. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 6497c1ad02d..12c7d78d924 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -2730,14 +2730,21 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment) DRM_ERROR("Failure to bind: %d\n", ret); return ret; } - /* - * Pre-965 chips need a fence register set up in order to - * properly handle tiled surfaces. - */ - if (!IS_I965G(dev) && - obj_priv->fence_reg == I915_FENCE_REG_NONE && - obj_priv->tiling_mode != I915_TILING_NONE) - i915_gem_object_get_fence_reg(obj, true); + } + /* + * Pre-965 chips need a fence register set up in order to + * properly handle tiled surfaces. + */ + if (!IS_I965G(dev) && + obj_priv->fence_reg == I915_FENCE_REG_NONE && + obj_priv->tiling_mode != I915_TILING_NONE) { + ret = i915_gem_object_get_fence_reg(obj, true); + if (ret != 0) { + if (ret != -EBUSY && ret != -ERESTARTSYS) + DRM_ERROR("Failure to install fence: %d\n", + ret); + return ret; + } } obj_priv->pin_count++; -- cgit v1.2.3 From fc7170ba281c041852eeda52d4faf5db720c99ce Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Feb 2009 14:26:46 +0000 Subject: drm/i915: Check to see if we've pinned all available fences We need to check and report if there are no available fences - or else we spin endlessly waiting for a buffer to magically unpin itself. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 12c7d78d924..2b5c7ad9e64 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1557,7 +1557,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) struct drm_i915_private *dev_priv = dev->dev_private; struct drm_i915_gem_object *obj_priv = obj->driver_private; struct drm_i915_fence_reg *reg = NULL; - int i, ret; + struct drm_i915_gem_object *old_obj_priv = NULL; + int i, ret, avail; switch (obj_priv->tiling_mode) { case I915_TILING_NONE: @@ -1581,17 +1582,24 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write) /* First try to find a free reg */ try_again: + avail = 0; for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { reg = &dev_priv->fence_regs[i]; if (!reg->obj) break; + + old_obj_priv = reg->obj->driver_private; + if (!old_obj_priv->pin_count) + avail++; } /* None available, try to steal one or wait for a user to finish */ if (i == dev_priv->num_fence_regs) { - struct drm_i915_gem_object *old_obj_priv = NULL; loff_t offset; + if (avail == 0) + return -ENOMEM; + /* Could try to use LRU here instead... */ for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { -- cgit v1.2.3 From 49976927de5c52c415d4809c7d56700cc8ff4215 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Wed, 11 Mar 2009 08:04:23 +0000 Subject: input: sh_keysc suspend can use to_platform_device() This patch changes sh_keysc to use to_platform_device() for suspend. Thanks to Trilok Soni for this suggestion. Signed-off-by: Magnus Damm Reviewed-by: Trilok Soni Signed-off-by: Paul Mundt --- drivers/input/keyboard/sh_keysc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/sh_keysc.c b/drivers/input/keyboard/sh_keysc.c index bf92178644a..e1480fb11de 100644 --- a/drivers/input/keyboard/sh_keysc.c +++ b/drivers/input/keyboard/sh_keysc.c @@ -257,13 +257,10 @@ static int __devexit sh_keysc_remove(struct platform_device *pdev) static int sh_keysc_suspend(struct device *dev) { - struct platform_device *pdev; - struct sh_keysc_priv *priv; + struct platform_device *pdev = to_platform_device(dev); + struct sh_keysc_priv *priv = platform_get_drvdata(pdev); unsigned short value; - pdev = container_of(dev, struct platform_device, dev); - priv = platform_get_drvdata(pdev); - value = ioread16(priv->iomem_base + KYCR1_OFFS); if (device_may_wakeup(dev)) -- cgit v1.2.3 From d7619c4b9c95cc9a2e7f0f4f7ae21165ab5cb1e7 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Wed, 11 Feb 2009 14:26:47 +0000 Subject: drm/i915: Protect active fences on i915 The i915 also uses the fence registers for GPU access to tiled buffers so we cannot reallocate one whilst it is on the active list. By performing a LRU scan of the fenced buffers we also avoid waiting the possibility of waiting on a pinned, or otherwise unusable, buffer. Signed-off-by: Chris Wilson Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 2b5c7ad9e64..b0ff5c44e61 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1595,18 +1595,32 @@ try_again: /* None available, try to steal one or wait for a user to finish */ if (i == dev_priv->num_fence_regs) { + uint32_t seqno = dev_priv->mm.next_gem_seqno; loff_t offset; if (avail == 0) return -ENOMEM; - /* Could try to use LRU here instead... */ for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) { + uint32_t this_seqno; + reg = &dev_priv->fence_regs[i]; old_obj_priv = reg->obj->driver_private; - if (!old_obj_priv->pin_count) + + if (old_obj_priv->pin_count) + continue; + + /* i915 uses fences for GPU access to tiled buffers */ + if (IS_I965G(dev) || !old_obj_priv->active) break; + + /* find the seqno of the first available fence */ + this_seqno = old_obj_priv->last_rendering_seqno; + if (this_seqno != 0 && + reg->obj->write_domain == 0 && + i915_seqno_passed(seqno, this_seqno)) + seqno = this_seqno; } /* @@ -1614,15 +1628,25 @@ try_again: * objects to finish before trying again. */ if (i == dev_priv->num_fence_regs) { - ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0); - if (ret) { - WARN(ret != -ERESTARTSYS, - "switch to GTT domain failed: %d\n", ret); - return ret; + if (seqno == dev_priv->mm.next_gem_seqno) { + i915_gem_flush(dev, + I915_GEM_GPU_DOMAINS, + I915_GEM_GPU_DOMAINS); + seqno = i915_add_request(dev, + I915_GEM_GPU_DOMAINS); + if (seqno == 0) + return -ENOMEM; } + + ret = i915_wait_request(dev, seqno); + if (ret) + return ret; goto try_again; } + BUG_ON(old_obj_priv->active || + (reg->obj->write_domain & I915_GEM_GPU_DOMAINS)); + /* * Zap this virtual mapping so we can set up a fence again * for this object next time we need it. -- cgit v1.2.3 From dc529a4fe1ae4667c819437a94185e8581e1e680 Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Tue, 10 Mar 2009 22:34:49 -0700 Subject: drm/i915: fix 945 fence register writes for fence 8 and above. The last 8 fence registers sit at a different offset, so when we went to set fence number 8 in the lower offset, we instead set PGETBL_CTL, and the GPU got all sorts of angry at us. fd.o bug #20567. Easily reproducible by running glxgears and killing it about 6 times. Signed-off-by: Eric Anholt --- drivers/gpu/drm/i915/i915_gem.c | 21 +++++++++++++++++---- drivers/gpu/drm/i915/i915_reg.h | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index b0ff5c44e61..37427e4016c 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c @@ -1476,7 +1476,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) struct drm_i915_gem_object *obj_priv = obj->driver_private; int regnum = obj_priv->fence_reg; int tile_width; - uint32_t val; + uint32_t fence_reg, val; uint32_t pitch_val; if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || @@ -1503,7 +1503,11 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg) val |= pitch_val << I830_FENCE_PITCH_SHIFT; val |= I830_FENCE_REG_VALID; - I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); + if (regnum < 8) + fence_reg = FENCE_REG_830_0 + (regnum * 4); + else + fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4); + I915_WRITE(fence_reg, val); } static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) @@ -1687,8 +1691,17 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj) if (IS_I965G(dev)) I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); - else - I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0); + else { + uint32_t fence_reg; + + if (obj_priv->fence_reg < 8) + fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; + else + fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - + 8) * 4; + + I915_WRITE(fence_reg, 0); + } dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; obj_priv->fence_reg = I915_FENCE_REG_NONE; diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9d6539a868b..90600d89941 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h @@ -184,6 +184,7 @@ * Fence registers */ #define FENCE_REG_830_0 0x2000 +#define FENCE_REG_945_8 0x3000 #define I830_FENCE_START_MASK 0x07f80000 #define I830_FENCE_TILING_Y_SHIFT 12 #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) -- cgit v1.2.3 From 3bb9db79235e19dbb18ba6f4a428a97c69115319 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 12 Mar 2009 13:36:38 +0100 Subject: hwmon: (abituguru3) Fix I/O error handling Fix a logic bug reported by Roel Kluin, by rewriting the error handling code in a clearer way. Signed-off-by: Jean Delvare Cc: Roel Kluin Acked-by: Alistair John Strachan Acked-by: Hans de Goede --- drivers/hwmon/abituguru3.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index e52b38806d0..ad2b3431b72 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -760,8 +760,11 @@ static int abituguru3_read_increment_offset(struct abituguru3_data *data, for (i = 0; i < offset_count; i++) if ((x = abituguru3_read(data, bank, offset + i, count, - buf + i * count)) != count) - return i * count + (i && (x < 0)) ? 0 : x; + buf + i * count)) != count) { + if (x < 0) + return x; + return i * count + x; + } return i * count; } -- cgit v1.2.3 From 1a51e068c900eb6ea23ce597361ebf3b19a57b23 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Thu, 12 Mar 2009 13:36:38 +0100 Subject: hwmon: (lm90) Document support for the MAX6648/6692 chips Update documentation to prevent further confusion/duplication. Signed-off-by: Darrick J. Wong Signed-off-by: Jean Delvare --- drivers/hwmon/Kconfig | 4 ++-- drivers/hwmon/lm90.c | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index b84bf066879..b4eea0292c1 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -543,8 +543,8 @@ config SENSORS_LM90 help If you say yes here you get support for National Semiconductor LM90, LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, and Maxim - MAX6646, MAX6647, MAX6649, MAX6657, MAX6658, MAX6659, MAX6680 and - MAX6681 sensor chips. + MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, + MAX6680, MAX6681 and MAX6692 sensor chips. This driver can also be built as a module. If so, the module will be called lm90. diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c index 96a70186672..1aff7575799 100644 --- a/drivers/hwmon/lm90.c +++ b/drivers/hwmon/lm90.c @@ -32,10 +32,10 @@ * supported by this driver. These chips lack the remote temperature * offset feature. * - * This driver also supports the MAX6646, MAX6647 and MAX6649 chips - * made by Maxim. These are again similar to the LM86, but they use - * unsigned temperature values and can report temperatures from 0 to - * 145 degrees. + * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and + * MAX6692 chips made by Maxim. These are again similar to the LM86, + * but they use unsigned temperature values and can report temperatures + * from 0 to 145 degrees. * * This driver also supports the MAX6680 and MAX6681, two other sensor * chips made by Maxim. These are quite similar to the other Maxim -- cgit v1.2.3 From e267d25005c861fe6afda343f044536342c9f8b4 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 12 Mar 2009 13:36:39 +0100 Subject: hwmon: (it87) Properly decode -128 degrees C temperature The it87 driver is reporting -128 degrees C as +128 degrees C. That's not a terribly likely temperature value but let's still get it right, especially when it simplifies the code. Signed-off-by: Jean Delvare --- drivers/hwmon/it87.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c index 95a99c590da..9157247fed8 100644 --- a/drivers/hwmon/it87.c +++ b/drivers/hwmon/it87.c @@ -213,7 +213,7 @@ static inline u16 FAN16_TO_REG(long rpm) #define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-500)/1000):\ ((val)+500)/1000),-128,127)) -#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*1000) +#define TEMP_FROM_REG(val) ((val) * 1000) #define PWM_TO_REG(val) ((val) >> 1) #define PWM_FROM_REG(val) (((val)&0x7f) << 1) @@ -267,9 +267,9 @@ struct it87_data { u8 has_fan; /* Bitfield, fans enabled */ u16 fan[5]; /* Register values, possibly combined */ u16 fan_min[5]; /* Register values, possibly combined */ - u8 temp[3]; /* Register value */ - u8 temp_high[3]; /* Register value */ - u8 temp_low[3]; /* Register value */ + s8 temp[3]; /* Register value */ + s8 temp_high[3]; /* Register value */ + s8 temp_low[3]; /* Register value */ u8 sensor; /* Register value */ u8 fan_div[3]; /* Register encoding, shifted right */ u8 vid; /* Register encoding, combined */ -- cgit v1.2.3 From 51b3e2700177b89fdb0d985926ce777a7ad52b15 Mon Sep 17 00:00:00 2001 From: Andrew Klossner Date: Thu, 12 Mar 2009 13:36:39 +0100 Subject: hwmon: (f75375s) Remove unnecessary and confusing initialization f75375_probe calls i2c_get_clientdata to initialize the data pointer, but there isn't yet any client data to get, and the value is never used before the variable is assigned a new value seven lines later. The call doesn't hurt anything and wastes only a couple of cycles. The reason to fix it is because this module serves as an example to hackers writing new hwmon drivers, and this part of the example is confusing. Signed-off-by: Andrew Klossner Signed-off-by: Jean Delvare --- drivers/hwmon/f75375s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index 1692de36996..18a1ba88816 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -617,7 +617,7 @@ static void f75375_init(struct i2c_client *client, struct f75375_data *data, static int f75375_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct f75375_data *data = i2c_get_clientdata(client); + struct f75375_data *data; struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data; int err; -- cgit v1.2.3 From 649426efcfbc67a8b033497151816cbac9fd0cfa Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Thu, 5 Mar 2009 13:57:28 -0500 Subject: PCI: Add PCI quirk to disable L0s ASPM state for 82575 and 82598 This patch is intended to disable L0s ASPM link state for 82598 (ixgbe) parts due to the fact that it is possible to corrupt TX data when coming back out of L0s on some systems. The workaround had been added for 82575 (igb) previously, but did not use the ASPM api. This quirk uses the ASPM api to prevent the ASPM subsystem from re-enabling the L0s state. Instead of adding the fix in igb to the ixgbe driver as well it was decided to move it into a pci quirk. It is necessary to move the fix out of the driver and into a pci quirk in order to prevent the issue from occuring prior to driver load to handle the possibility of the device being passed to a VM via direct assignment. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher CC: Jesse Barnes Signed-off-by: Matthew Wilcox --- drivers/pci/quirks.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index f20d55368ed..1a7c48d71dc 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "pci.h" int isa_dma_bridge_buggy; @@ -1749,6 +1750,30 @@ static void __devinit quirk_e100_interrupt(struct pci_dev *dev) } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_e100_interrupt); +/* + * The 82575 and 82598 may experience data corruption issues when transitioning + * out of L0S. To prevent this we need to disable L0S on the pci-e link + */ +static void __devinit quirk_disable_aspm_l0s(struct pci_dev *dev) +{ + dev_info(&dev->dev, "Disabling L0s\n"); + pci_disable_link_state(dev, PCIE_LINK_STATE_L0S); +} +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10a7, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10a9, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10b6, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c6, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c7, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10c8, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10d6, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10db, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10dd, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10e1, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10ec, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f1, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x10f4, quirk_disable_aspm_l0s); +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x1508, quirk_disable_aspm_l0s); + static void __devinit fixup_rev1_53c810(struct pci_dev* dev) { /* rev 1 ncr53c810 chips don't set the class at all which means -- cgit v1.2.3 From cb4cb4ac7338c28b047760be187355ed9c783e72 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Thu, 5 Mar 2009 19:28:40 -0700 Subject: PCIe: AER: during disable, check subordinate before walking Commit 47a8b0cc (Enable PCIe AER only after checking firmware support) wants to walk the PCI bus in the remove path to disable AER, and calls pci_walk_bus for downstream bridges. Unfortunately, in the remove path, we remove devices and bridges in a depth-first manner, starting with the furthest downstream bridge and working our way backwards. The furthest downstream bridges will not have a dev->subordinate, and we hit a NULL deref in pci_walk_bus. Check for dev->subordinate first before attempting to walk the PCI hierarchy below us. Acked-by: Andrew Patterson Signed-off-by: Alex Chiang Signed-off-by: Matthew Wilcox --- drivers/pci/pcie/aer/aerdrv_core.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index d0c97368586..38257500738 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c @@ -133,6 +133,9 @@ static void set_downstream_devices_error_reporting(struct pci_dev *dev, bool enable) { set_device_error_reporting(dev, &enable); + + if (!dev->subordinate) + return; pci_walk_bus(dev->subordinate, set_device_error_reporting, &enable); } -- cgit v1.2.3 From 3f3b902ed8147c42a4a9764014c758e6b3f42f51 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Fri, 6 Mar 2009 14:39:14 +1100 Subject: powerpc/pseries: The RPA PCI hotplug driver depends on EEH The RPA PCI hotplug driver calls EEH routines, so should depend on EEH. Also PPC_PSERIES implies PPC64, so remove that. Signed-off-by: Michael Ellerman Signed-off-by: Matthew Wilcox --- drivers/pci/hotplug/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig index eacfb13998b..9aa4fe100a0 100644 --- a/drivers/pci/hotplug/Kconfig +++ b/drivers/pci/hotplug/Kconfig @@ -143,7 +143,7 @@ config HOTPLUG_PCI_SHPC config HOTPLUG_PCI_RPA tristate "RPA PCI Hotplug driver" - depends on PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE + depends on PPC_PSERIES && EEH && !HOTPLUG_PCI_FAKE help Say Y here if you have a RPA system that supports PCI Hotplug. -- cgit v1.2.3 From 7726c3308a92b4a4c3bd059059498fca0e6f8e48 Mon Sep 17 00:00:00 2001 From: Prakash Punnoor Date: Fri, 6 Mar 2009 00:45:12 +0100 Subject: pci: don't disable too many HT MSI mapping Prakash's system needs MSI disabled on some bridges, but not all. This seems to be the minimal fix for 2.6.29, but should be replaced during 2.6.30. Signed-off-by: Prakash Punnoor Signed-off-by: Matthew Wilcox --- drivers/pci/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 1a7c48d71dc..9104671e4b7 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2166,6 +2166,10 @@ static void __devinit nv_msi_ht_cap_quirk(struct pci_dev *dev) int pos; int found; + /* Enabling HT MSI mapping on this device breaks MCP51 */ + if (dev->device == 0x270) + return; + /* check if there is HT MSI cap or enabled on this device */ found = ht_check_msi_mapping(dev); -- cgit v1.2.3 From 6a958d5b28e4a180458e0d319d2e4bb5c4b7da3e Mon Sep 17 00:00:00 2001 From: Prakash Punnoor Date: Fri, 6 Mar 2009 10:10:35 +0100 Subject: pci: Fix typo in message while disabling HT MSI mapping "Enabling" should read "Disabling" Signed-off-by: Prakash Punnoor Signed-off-by: Matthew Wilcox --- drivers/pci/quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c index 9104671e4b7..92b9efe9bca 100644 --- a/drivers/pci/quirks.c +++ b/drivers/pci/quirks.c @@ -2122,7 +2122,7 @@ static void __devinit ht_disable_msi_mapping(struct pci_dev *dev) if (pci_read_config_byte(dev, pos + HT_MSI_FLAGS, &flags) == 0) { - dev_info(&dev->dev, "Enabling HT MSI Mapping\n"); + dev_info(&dev->dev, "Disabling HT MSI Mapping\n"); pci_write_config_byte(dev, pos + HT_MSI_FLAGS, flags & ~HT_MSI_FLAGS_ENABLE); -- cgit v1.2.3 From d89987193631bf23d1735c55d13a06d4b8d0e9bd Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Sat, 7 Mar 2009 19:35:47 -0700 Subject: PCIe: portdrv: call pci_disable_device during remove The PCIe port driver calls pci_enable_device() during probe but never calls pci_disable_device() during remove. Cc: stable@kernel.org Signed-off-by: Alex Chiang Signed-off-by: Matthew Wilcox --- drivers/pci/pcie/portdrv_pci.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c index 248b4db9155..5ea566e20b3 100644 --- a/drivers/pci/pcie/portdrv_pci.c +++ b/drivers/pci/pcie/portdrv_pci.c @@ -103,6 +103,7 @@ static int __devinit pcie_portdrv_probe (struct pci_dev *dev, static void pcie_portdrv_remove (struct pci_dev *dev) { pcie_port_device_remove(dev); + pci_disable_device(dev); kfree(pci_get_drvdata(dev)); } -- cgit v1.2.3 From 8d0df7a3d1ecbaf5d5602a59055c8ca993855bed Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 12 Mar 2009 14:31:25 -0700 Subject: drivers/w1/masters/w1-gpio.c: fix read_bit() W1 master implementations are expected to return 0 or 1 from their read_bit() function. However, not all platforms do return these values from gpio_get_value() - namely PXAs won't. Hence the w1 gpio-master needs to break the result down to 0 or 1 itself. Signed-off-by: Daniel Mack Cc: Ville Syrjala Cc: Evgeniy Polyakov Cc: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/w1/masters/w1-gpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index 9e1138a75e8..a411702413d 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c @@ -39,7 +39,7 @@ static u8 w1_gpio_read_bit(void *data) { struct w1_gpio_platform_data *pdata = data; - return gpio_get_value(pdata->pin); + return gpio_get_value(pdata->pin) ? 1 : 0; } static int __init w1_gpio_probe(struct platform_device *pdev) -- cgit v1.2.3 From a4e3f91b98d86ae0b5c816fe45190bb29ac32f71 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Thu, 12 Mar 2009 14:31:30 -0700 Subject: ds2760_battery.c: fix division by zero The 'battery remaining capacity' calculation in drivers/power/ds2760_battery.c lacks a parameter check to a division operation which causes the kernel to oops on my board. [ 21.233750] Division by zero in kernel. [ 21.237646] [] (__div0+0x0/0x20) from [] (Ldiv0+0x8/0x10) [ 21.244816] [] (ds2760_battery_read_status+0x0/0x2a4) from [] (ds2760_battery_get_property+0x30/0xdc) [ 21.255803] r8:c03a22c0 r7:c7886100 r6:00000009 r5:c782fe7c r4:c7886084 [ 21.262518] [] (ds2760_battery_get_property+0x0/0xdc) from [] (power_supply_show_property+0x48/0x114) [ 21.273480] r6:c7996000 r5:00000009 r4:00000000 [ 21.278111] [] (power_supply_show_property+0x0/0x114) from [] (power_supply_uevent+0x188/0x280) [ 21.288537] r8:00000001 r7:c7886100 r6:c7996000 r5:000000b4 r4:00000000 [ 21.295222] [] (power_supply_uevent+0x0/0x280) from [] (dev_uevent+0xd4/0x10c) [ 21.304199] [] (dev_uevent+0x0/0x10c) from [] (kobject_uevent_env+0x180/0x390) [ 21.313170] r5:00000000 r4:c78860ac [ 21.316725] [] (kobject_uevent_env+0x0/0x390) from [] (kobject_uevent+0x14/0x18) [ 21.325850] [] (kobject_uevent+0x0/0x18) from [] (power_supply_changed_work+0x5c/0x70) [ 21.335506] [] (power_supply_changed_work+0x0/0x70) from [] (run_workqueue+0xbc/0x144) [ 21.345167] r4:c7812040 [ 21.347716] [] (run_workqueue+0x0/0x144) from [] (worker_thread+0xa8/0xbc) [ 21.356296] r7:c7812040 r6:c7820b00 r5:c782ffa4 r4:c7812048 [ 21.361957] [] (worker_thread+0x0/0xbc) from [] (kthread+0x5c/0x94) [ 21.369971] r7:00000000 r6:c004d8a4 r5:c7812040 r4:c782e000 [ 21.375612] [] (kthread+0x0/0x94) from [] (do_exit+0x0/0x688) Signed-off-by: Daniel Mack Cc: Szabolcs Gyurko Acked-by: Matt Reimer Acked-by: Anton Vorontsov Cc: David Woodhouse Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/power/ds2760_battery.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c index 1d768928e0b..a52d4a11652 100644 --- a/drivers/power/ds2760_battery.c +++ b/drivers/power/ds2760_battery.c @@ -180,10 +180,13 @@ static int ds2760_battery_read_status(struct ds2760_device_info *di) di->empty_uAh = battery_interpolate(scale, di->temp_C / 10); di->empty_uAh *= 1000; /* convert to µAh */ - /* From Maxim Application Note 131: remaining capacity = - * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */ - di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) / - (di->full_active_uAh - di->empty_uAh); + if (di->full_active_uAh == di->empty_uAh) + di->rem_capacity = 0; + else + /* From Maxim Application Note 131: remaining capacity = + * ((ICA - Empty Value) / (Full Value - Empty Value)) x 100% */ + di->rem_capacity = ((di->accum_current_uAh - di->empty_uAh) * 100L) / + (di->full_active_uAh - di->empty_uAh); if (di->rem_capacity < 0) di->rem_capacity = 0; -- cgit v1.2.3 From 7c48ed3383bfb2106694807361ec187fe8a4333d Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 12 Mar 2009 14:31:33 -0700 Subject: mmc: s3cmci: fix s3c2410_dma_config() arguments. The s3cmci driver is calling s3c2410_dma_config with incorrect data for the DCON register. The S3C2410_DCON_HWTRIG is implicit in the channel configuration and the device selection of S3C2410_DCON_CH0_SDI is incorrect as the DMA system may not select channel 0. Signed-off-by: Ben Dooks Acked-by: Pierre Ossman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mmc/host/s3cmci.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/s3cmci.c b/drivers/mmc/host/s3cmci.c index f4a67c65d30..2db166b7096 100644 --- a/drivers/mmc/host/s3cmci.c +++ b/drivers/mmc/host/s3cmci.c @@ -793,8 +793,7 @@ static void s3cmci_dma_setup(struct s3cmci_host *host, host->mem->start + host->sdidata); if (!setup_ok) { - s3c2410_dma_config(host->dma, 4, - (S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI)); + s3c2410_dma_config(host->dma, 4, 0); s3c2410_dma_set_buffdone_fn(host->dma, s3cmci_dma_done_callback); s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART); -- cgit v1.2.3 From 1ba869ec581fd9078b684c56c399ffe3d2345e27 Mon Sep 17 00:00:00 2001 From: Michael Spang Date: Thu, 12 Mar 2009 14:31:34 -0700 Subject: acer-wmi: fix regression in backlight detection Currently we disable the Acer WMI backlight device if there is no ACPI backlight device. As a result, we end up with no backlight device at all. We should instead disable it if there is an ACPI device, as the other laptop drivers do. This regression was introduced in febf2d9 ("Acer-WMI: fingers off backlight if video.ko is serving this functionality"). Each laptop driver with backlight support got a similar change around febf2d9. The changes to the other drivers look correct; see e.g. a598c82f for a similar but correct change. The regression is also in 2.6.28. Signed-off-by: Michael Spang Acked-by: Thomas Renninger Cc: Zhang Rui Cc: Andi Kleen Cc: Carlos Corbacho Cc: Len Brown Cc: "Rafael J. Wysocki" Cc: [2.6.28.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/platform/x86/acer-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 94c9f911824..6bcca616a70 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1297,7 +1297,7 @@ static int __init acer_wmi_init(void) set_quirks(); - if (!acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { + if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) { interface->capability &= ~ACER_CAP_BRIGHTNESS; printk(ACER_INFO "Brightness must be controlled by " "generic video driver\n"); -- cgit v1.2.3 From 02d46e07e538c285accb5c000a7db3a97eff1fbf Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Thu, 12 Mar 2009 14:31:36 -0700 Subject: mfd: add support for WM8351 revision B No software visible difference from revision A. Signed-off-by: Mark Brown Cc: Samuel Ortiz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/mfd/wm8350-core.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index 84d5ea1ec17..b457a05b28d 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c @@ -1383,6 +1383,11 @@ int wm8350_device_init(struct wm8350 *wm8350, int irq, wm8350->power.rev_g_coeff = 1; break; + case 1: + dev_info(wm8350->dev, "WM8351 Rev B\n"); + wm8350->power.rev_g_coeff = 1; + break; + default: dev_err(wm8350->dev, "Unknown WM8351 CHIP_REV\n"); ret = -ENODEV; -- cgit v1.2.3 From c12e56ef6951f4fce1afe9ef6aab9243ea9a9b04 Mon Sep 17 00:00:00 2001 From: Faisal Latif Date: Thu, 12 Mar 2009 14:34:59 -0700 Subject: RDMA/nes: Don't allow userspace QPs to use STag zero STag zero is a special STag that allows consumers to access any bus address without registering memory. The nes driver unfortunately allows STag zero to be used even with QPs created by unprivileged userspace consumers, which means that any process with direct verbs access to the nes device can read and write any memory accessible to the underlying PCI device (usually any memory in the system). Such access is usually given for cluster software such as MPI to use, so this is a local privilege escalation bug on most systems running this driver. The driver was using STag zero to receive the last streaming mode data; to allow STag zero to be disabled for unprivileged QPs, the driver now registers a special MR for this data. Cc: Signed-off-by: Faisal Latif Signed-off-by: Roland Dreier Signed-off-by: Linus Torvalds --- drivers/infiniband/hw/nes/nes_cm.c | 39 ++++++++++++++++++++++++++++++----- drivers/infiniband/hw/nes/nes_verbs.c | 2 ++ drivers/infiniband/hw/nes/nes_verbs.h | 1 + 3 files changed, 37 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/nes/nes_cm.c b/drivers/infiniband/hw/nes/nes_cm.c index a01b4488208..4a65b96db2c 100644 --- a/drivers/infiniband/hw/nes/nes_cm.c +++ b/drivers/infiniband/hw/nes/nes_cm.c @@ -2490,12 +2490,14 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt) int ret = 0; struct nes_vnic *nesvnic; struct nes_device *nesdev; + struct nes_ib_device *nesibdev; nesvnic = to_nesvnic(nesqp->ibqp.device); if (!nesvnic) return -EINVAL; nesdev = nesvnic->nesdev; + nesibdev = nesvnic->nesibdev; nes_debug(NES_DBG_CM, "netdev refcnt = %u.\n", atomic_read(&nesvnic->netdev->refcnt)); @@ -2507,6 +2509,8 @@ static int nes_disconnect(struct nes_qp *nesqp, int abrupt) } else { /* Need to free the Last Streaming Mode Message */ if (nesqp->ietf_frame) { + if (nesqp->lsmm_mr) + nesibdev->ibdev.dereg_mr(nesqp->lsmm_mr); pci_free_consistent(nesdev->pcidev, nesqp->private_data_len+sizeof(struct ietf_mpa_frame), nesqp->ietf_frame, nesqp->ietf_frame_pbase); @@ -2543,6 +2547,12 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) u32 crc_value; int ret; int passive_state; + struct nes_ib_device *nesibdev; + struct ib_mr *ibmr = NULL; + struct ib_phys_buf ibphysbuf; + struct nes_pd *nespd; + + ibqp = nes_get_qp(cm_id->device, conn_param->qpn); if (!ibqp) @@ -2601,6 +2611,26 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) if (cm_id->remote_addr.sin_addr.s_addr != cm_id->local_addr.sin_addr.s_addr) { u64temp = (unsigned long)nesqp; + nesibdev = nesvnic->nesibdev; + nespd = nesqp->nespd; + ibphysbuf.addr = nesqp->ietf_frame_pbase; + ibphysbuf.size = conn_param->private_data_len + + sizeof(struct ietf_mpa_frame); + ibmr = nesibdev->ibdev.reg_phys_mr((struct ib_pd *)nespd, + &ibphysbuf, 1, + IB_ACCESS_LOCAL_WRITE, + (u64 *)&nesqp->ietf_frame); + if (!ibmr) { + nes_debug(NES_DBG_CM, "Unable to register memory region" + "for lSMM for cm_node = %p \n", + cm_node); + return -ENOMEM; + } + + ibmr->pd = &nespd->ibpd; + ibmr->device = nespd->ibpd.device; + nesqp->lsmm_mr = ibmr; + u64temp |= NES_SW_CONTEXT_ALIGN>>1; set_wqe_64bit_value(wqe->wqe_words, NES_IWARP_SQ_WQE_COMP_CTX_LOW_IDX, @@ -2611,14 +2641,13 @@ int nes_accept(struct iw_cm_id *cm_id, struct iw_cm_conn_param *conn_param) wqe->wqe_words[NES_IWARP_SQ_WQE_TOTAL_PAYLOAD_IDX] = cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_LOW_IDX] = - cpu_to_le32((u32)nesqp->ietf_frame_pbase); - wqe->wqe_words[NES_IWARP_SQ_WQE_FRAG0_HIGH_IDX] = - cpu_to_le32((u32)((u64)nesqp->ietf_frame_pbase >> 32)); + set_wqe_64bit_value(wqe->wqe_words, + NES_IWARP_SQ_WQE_FRAG0_LOW_IDX, + (u64)nesqp->ietf_frame); wqe->wqe_words[NES_IWARP_SQ_WQE_LENGTH0_IDX] = cpu_to_le32(conn_param->private_data_len + sizeof(struct ietf_mpa_frame)); - wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = 0; + wqe->wqe_words[NES_IWARP_SQ_WQE_STAG0_IDX] = ibmr->lkey; nesqp->nesqp_context->ird_ord_sizes |= cpu_to_le32(NES_QPCONTEXT_ORDIRD_LSMM_PRESENT | diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 4fdb72454f9..d93a6562817 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1360,8 +1360,10 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, NES_QPCONTEXT_MISC_RQ_SIZE_SHIFT); nesqp->nesqp_context->misc |= cpu_to_le32((u32)nesqp->hwqp.sq_encoded_size << NES_QPCONTEXT_MISC_SQ_SIZE_SHIFT); + if (!udata) { nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_PRIV_EN); nesqp->nesqp_context->misc |= cpu_to_le32(NES_QPCONTEXT_MISC_FAST_REGISTER_EN); + } nesqp->nesqp_context->cqs = cpu_to_le32(nesqp->nesscq->hw_cq.cq_number + ((u32)nesqp->nesrcq->hw_cq.cq_number << 16)); u64temp = (u64)nesqp->hwqp.sq_pbase; diff --git a/drivers/infiniband/hw/nes/nes_verbs.h b/drivers/infiniband/hw/nes/nes_verbs.h index 6c6b4da5184..ae0ca9bc83b 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.h +++ b/drivers/infiniband/hw/nes/nes_verbs.h @@ -134,6 +134,7 @@ struct nes_qp { struct ietf_mpa_frame *ietf_frame; dma_addr_t ietf_frame_pbase; wait_queue_head_t state_waitq; + struct ib_mr *lsmm_mr; unsigned long socket; struct nes_hw_qp hwqp; struct work_struct work; -- cgit v1.2.3 From 5f77af93266e107bd46c010c51d772c0fb003232 Mon Sep 17 00:00:00 2001 From: Antti Palosaari Date: Tue, 10 Mar 2009 13:06:40 -0300 Subject: V4L/DVB (10972): zl10353: i2c_gate_ctrl bug fix zl10353 i2c-gate was always closed and due to that devices having tuner behind i2c-gate were broken. Add module configuration which allows disabling i2c-gate only when really needed. Signed-off-by: Antti Palosaari Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/zl10353.c | 2 +- drivers/media/dvb/frontends/zl10353.h | 3 +++ drivers/media/video/saa7134/saa7134-dvb.c | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/zl10353.c b/drivers/media/dvb/frontends/zl10353.c index 170720b0281..b150ed30669 100644 --- a/drivers/media/dvb/frontends/zl10353.c +++ b/drivers/media/dvb/frontends/zl10353.c @@ -590,7 +590,7 @@ static int zl10353_i2c_gate_ctrl(struct dvb_frontend* fe, int enable) struct zl10353_state *state = fe->demodulator_priv; u8 val = 0x0a; - if (state->config.no_tuner) { + if (state->config.disable_i2c_gate_ctrl) { /* No tuner attached to the internal I2C bus */ /* If set enable I2C bridge, the main I2C bus stopped hardly */ return 0; diff --git a/drivers/media/dvb/frontends/zl10353.h b/drivers/media/dvb/frontends/zl10353.h index fdbb88ff75f..2287bac4624 100644 --- a/drivers/media/dvb/frontends/zl10353.h +++ b/drivers/media/dvb/frontends/zl10353.h @@ -38,6 +38,9 @@ struct zl10353_config /* set if parallel ts output is required */ int parallel_ts; + + /* set if i2c_gate_ctrl disable is required */ + u8 disable_i2c_gate_ctrl:1; }; #if defined(CONFIG_DVB_ZL10353) || (defined(CONFIG_DVB_ZL10353_MODULE) && defined(MODULE)) diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 0776ecf56d2..b5370b3e1a3 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -860,6 +860,7 @@ static struct zl10353_config behold_h6_config = { .demod_address = 0x1e>>1, .no_tuner = 1, .parallel_ts = 1, + .disable_i2c_gate_ctrl = 1, }; /* ================================================================== -- cgit v1.2.3 From f507cd22035fdadd5dbb476dd05e9e7ee21c3b84 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 6 Mar 2009 02:54:09 +0000 Subject: ps3/block: Replace mtd/ps3vram by block/ps3vram Convert the PS3 Video RAM Storage Driver from an MTD driver to a plain block device driver. The ps3vram driver exposes unused video RAM on the PS3 as a block device suitable for storage or swap. Fast data transfer is achieved using a local cache in system RAM and DMA transfers via the GPU. The new driver is ca. 50% faster for reading, and ca. 10% for writing. Signed-off-by: Geert Uytterhoeven Acked-by: Geoff Levand Signed-off-by: Benjamin Herrenschmidt --- drivers/block/Makefile | 1 + drivers/block/ps3vram.c | 865 ++++++++++++++++++++++++++++++++++++++++++ drivers/mtd/devices/Kconfig | 7 - drivers/mtd/devices/Makefile | 1 - drivers/mtd/devices/ps3vram.c | 768 ------------------------------------- 5 files changed, 866 insertions(+), 776 deletions(-) create mode 100644 drivers/block/ps3vram.c delete mode 100644 drivers/mtd/devices/ps3vram.c (limited to 'drivers') diff --git a/drivers/block/Makefile b/drivers/block/Makefile index 204332b2957..87e120e0a79 100644 --- a/drivers/block/Makefile +++ b/drivers/block/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_MAC_FLOPPY) += swim3.o obj-$(CONFIG_BLK_DEV_FD) += floppy.o obj-$(CONFIG_AMIGA_FLOPPY) += amiflop.o obj-$(CONFIG_PS3_DISK) += ps3disk.o +obj-$(CONFIG_PS3_VRAM) += ps3vram.o obj-$(CONFIG_ATARI_FLOPPY) += ataflop.o obj-$(CONFIG_AMIGA_Z2RAM) += z2ram.o obj-$(CONFIG_BLK_DEV_RAM) += brd.o diff --git a/drivers/block/ps3vram.c b/drivers/block/ps3vram.c new file mode 100644 index 00000000000..393ed6760d7 --- /dev/null +++ b/drivers/block/ps3vram.c @@ -0,0 +1,865 @@ +/* + * ps3vram - Use extra PS3 video ram as MTD block device. + * + * Copyright 2009 Sony Corporation + * + * Based on the MTD ps3vram driver, which is + * Copyright (c) 2007-2008 Jim Paris + * Added support RSX DMA Vivien Chappelier + */ + +#include +#include +#include +#include + +#include +#include +#include + + +#define DEVICE_NAME "ps3vram" + + +#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */ +#define XDR_IOIF 0x0c000000 + +#define FIFO_BASE XDR_IOIF +#define FIFO_SIZE (64 * 1024) + +#define DMA_PAGE_SIZE (4 * 1024) + +#define CACHE_PAGE_SIZE (256 * 1024) +#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE) + +#define CACHE_OFFSET CACHE_PAGE_SIZE +#define FIFO_OFFSET 0 + +#define CTRL_PUT 0x10 +#define CTRL_GET 0x11 +#define CTRL_TOP 0x15 + +#define UPLOAD_SUBCH 1 +#define DOWNLOAD_SUBCH 2 + +#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c +#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 + +#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 + +#define CACHE_PAGE_PRESENT 1 +#define CACHE_PAGE_DIRTY 2 + +struct ps3vram_tag { + unsigned int address; + unsigned int flags; +}; + +struct ps3vram_cache { + unsigned int page_count; + unsigned int page_size; + struct ps3vram_tag *tags; + unsigned int hit; + unsigned int miss; +}; + +struct ps3vram_priv { + struct request_queue *queue; + struct gendisk *gendisk; + + u64 size; + + u64 memory_handle; + u64 context_handle; + u32 *ctrl; + u32 *reports; + u8 __iomem *ddr_base; + u8 *xdr_buf; + + u32 *fifo_base; + u32 *fifo_ptr; + + struct ps3vram_cache cache; + + /* Used to serialize cache/DMA operations */ + struct mutex lock; +}; + + +static int ps3vram_major; + + +static struct block_device_operations ps3vram_fops = { + .owner = THIS_MODULE, +}; + + +#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */ +#define DMA_NOTIFIER_OFFSET_BASE 0x1000 /* first DMA notifier offset */ +#define DMA_NOTIFIER_SIZE 0x40 +#define NOTIFIER 7 /* notifier used for completion report */ + +static char *size = "256M"; +module_param(size, charp, 0); +MODULE_PARM_DESC(size, "memory size"); + +static u32 *ps3vram_get_notifier(u32 *reports, int notifier) +{ + return (void *)reports + DMA_NOTIFIER_OFFSET_BASE + + DMA_NOTIFIER_SIZE * notifier; +} + +static void ps3vram_notifier_reset(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); + int i; + + for (i = 0; i < 4; i++) + notify[i] = 0xffffffff; +} + +static int ps3vram_notifier_wait(struct ps3_system_bus_device *dev, + unsigned int timeout_ms) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); + + do { + if (!notify[3]) + return 0; + msleep(1); + } while (time_before(jiffies, timeout)); + + return -ETIMEDOUT; +} + +static void ps3vram_init_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; + priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET; +} + +static int ps3vram_wait_ring(struct ps3_system_bus_device *dev, + unsigned int timeout_ms) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); + + do { + if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET]) + return 0; + msleep(1); + } while (time_before(jiffies, timeout)); + + dev_warn(&dev->core, "FIFO timeout (%08x/%08x/%08x)\n", + priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET], + priv->ctrl[CTRL_TOP]); + + return -ETIMEDOUT; +} + +static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data) +{ + *(priv->fifo_ptr)++ = data; +} + +static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, u32 tag, + u32 size) +{ + ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); +} + +static void ps3vram_rewind_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + int status; + + ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET)); + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; + + /* asking the HV for a blit will kick the FIFO */ + status = lv1_gpu_context_attribute(priv->context_handle, + L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0, + 0, 0, 0); + if (status) + dev_err(&dev->core, + "%s: lv1_gpu_context_attribute failed %d\n", __func__, + status); + + priv->fifo_ptr = priv->fifo_base; +} + +static void ps3vram_fire_ring(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + int status; + + mutex_lock(&ps3_gpu_mutex); + + priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET + + (priv->fifo_ptr - priv->fifo_base) * sizeof(u32); + + /* asking the HV for a blit will kick the FIFO */ + status = lv1_gpu_context_attribute(priv->context_handle, + L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, 0, + 0, 0, 0); + if (status) + dev_err(&dev->core, + "%s: lv1_gpu_context_attribute failed %d\n", __func__, + status); + + if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > + FIFO_SIZE - 1024) { + dev_dbg(&dev->core, "FIFO full, rewinding\n"); + ps3vram_wait_ring(dev, 200); + ps3vram_rewind_ring(dev); + } + + mutex_unlock(&ps3_gpu_mutex); +} + +static void ps3vram_bind(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1); + ps3vram_out_ring(priv, 0x31337303); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3); + ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); + ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ + ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ + + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1); + ps3vram_out_ring(priv, 0x3137c0de); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3); + ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); + ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ + ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ + + ps3vram_fire_ring(dev); +} + +static int ps3vram_upload(struct ps3_system_bus_device *dev, + unsigned int src_offset, unsigned int dst_offset, + int len, int count) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, UPLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + ps3vram_out_ring(priv, XDR_IOIF + src_offset); + ps3vram_out_ring(priv, dst_offset); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, count); + ps3vram_out_ring(priv, (1 << 8) | 1); + ps3vram_out_ring(priv, 0); + + ps3vram_notifier_reset(dev); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); + ps3vram_out_ring(priv, 0); + ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1); + ps3vram_out_ring(priv, 0); + ps3vram_fire_ring(dev); + if (ps3vram_notifier_wait(dev, 200) < 0) { + dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); + return -1; + } + + return 0; +} + +static int ps3vram_download(struct ps3_system_bus_device *dev, + unsigned int src_offset, unsigned int dst_offset, + int len, int count) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); + ps3vram_out_ring(priv, src_offset); + ps3vram_out_ring(priv, XDR_IOIF + dst_offset); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, len); + ps3vram_out_ring(priv, count); + ps3vram_out_ring(priv, (1 << 8) | 1); + ps3vram_out_ring(priv, 0); + + ps3vram_notifier_reset(dev); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, + NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); + ps3vram_out_ring(priv, 0); + ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1); + ps3vram_out_ring(priv, 0); + ps3vram_fire_ring(dev); + if (ps3vram_notifier_wait(dev, 200) < 0) { + dev_warn(&dev->core, "%s: Notifier timeout\n", __func__); + return -1; + } + + return 0; +} + +static void ps3vram_cache_evict(struct ps3_system_bus_device *dev, int entry) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + + if (!(cache->tags[entry].flags & CACHE_PAGE_DIRTY)) + return; + + dev_dbg(&dev->core, "Flushing %d: 0x%08x\n", entry, + cache->tags[entry].address); + if (ps3vram_upload(dev, CACHE_OFFSET + entry * cache->page_size, + cache->tags[entry].address, DMA_PAGE_SIZE, + cache->page_size / DMA_PAGE_SIZE) < 0) { + dev_err(&dev->core, + "Failed to upload from 0x%x to " "0x%x size 0x%x\n", + entry * cache->page_size, cache->tags[entry].address, + cache->page_size); + } + cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; +} + +static void ps3vram_cache_load(struct ps3_system_bus_device *dev, int entry, + unsigned int address) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + + dev_dbg(&dev->core, "Fetching %d: 0x%08x\n", entry, address); + if (ps3vram_download(dev, address, + CACHE_OFFSET + entry * cache->page_size, + DMA_PAGE_SIZE, + cache->page_size / DMA_PAGE_SIZE) < 0) { + dev_err(&dev->core, + "Failed to download from 0x%x to 0x%x size 0x%x\n", + address, entry * cache->page_size, cache->page_size); + } + + cache->tags[entry].address = address; + cache->tags[entry].flags |= CACHE_PAGE_PRESENT; +} + + +static void ps3vram_cache_flush(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + int i; + + dev_dbg(&dev->core, "FLUSH\n"); + for (i = 0; i < cache->page_count; i++) { + ps3vram_cache_evict(dev, i); + cache->tags[i].flags = 0; + } +} + +static unsigned int ps3vram_cache_match(struct ps3_system_bus_device *dev, + loff_t address) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct ps3vram_cache *cache = &priv->cache; + unsigned int base; + unsigned int offset; + int i; + static int counter; + + offset = (unsigned int) (address & (cache->page_size - 1)); + base = (unsigned int) (address - offset); + + /* fully associative check */ + for (i = 0; i < cache->page_count; i++) { + if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && + cache->tags[i].address == base) { + cache->hit++; + dev_dbg(&dev->core, "Found entry %d: 0x%08x\n", i, + cache->tags[i].address); + return i; + } + } + + /* choose a random entry */ + i = (jiffies + (counter++)) % cache->page_count; + dev_dbg(&dev->core, "Using entry %d\n", i); + + ps3vram_cache_evict(dev, i); + ps3vram_cache_load(dev, i, base); + + cache->miss++; + return i; +} + +static int ps3vram_cache_init(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + priv->cache.page_count = CACHE_PAGE_COUNT; + priv->cache.page_size = CACHE_PAGE_SIZE; + priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) * + CACHE_PAGE_COUNT, GFP_KERNEL); + if (priv->cache.tags == NULL) { + dev_err(&dev->core, "Could not allocate cache tags\n"); + return -ENOMEM; + } + + dev_info(&dev->core, "Created ram cache: %d entries, %d KiB each\n", + CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024); + + return 0; +} + +static void ps3vram_cache_cleanup(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + ps3vram_cache_flush(dev); + kfree(priv->cache.tags); +} + +static int ps3vram_read(struct ps3_system_bus_device *dev, loff_t from, + size_t len, size_t *retlen, u_char *buf) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned int cached, count; + + dev_dbg(&dev->core, "%s: from=0x%08x len=0x%zx\n", __func__, + (unsigned int)from, len); + + if (from >= priv->size) + return -EIO; + + if (len > priv->size - from) + len = priv->size - from; + + /* Copy from vram to buf */ + count = len; + while (count) { + unsigned int offset, avail; + unsigned int entry; + + offset = (unsigned int) (from & (priv->cache.page_size - 1)); + avail = priv->cache.page_size - offset; + + mutex_lock(&priv->lock); + + entry = ps3vram_cache_match(dev, from); + cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; + + dev_dbg(&dev->core, "%s: from=%08x cached=%08x offset=%08x " + "avail=%08x count=%08x\n", __func__, + (unsigned int)from, cached, offset, avail, count); + + if (avail > count) + avail = count; + memcpy(buf, priv->xdr_buf + cached, avail); + + mutex_unlock(&priv->lock); + + buf += avail; + count -= avail; + from += avail; + } + + *retlen = len; + return 0; +} + +static int ps3vram_write(struct ps3_system_bus_device *dev, loff_t to, + size_t len, size_t *retlen, const u_char *buf) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + unsigned int cached, count; + + if (to >= priv->size) + return -EIO; + + if (len > priv->size - to) + len = priv->size - to; + + /* Copy from buf to vram */ + count = len; + while (count) { + unsigned int offset, avail; + unsigned int entry; + + offset = (unsigned int) (to & (priv->cache.page_size - 1)); + avail = priv->cache.page_size - offset; + + mutex_lock(&priv->lock); + + entry = ps3vram_cache_match(dev, to); + cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; + + dev_dbg(&dev->core, "%s: to=%08x cached=%08x offset=%08x " + "avail=%08x count=%08x\n", __func__, (unsigned int)to, + cached, offset, avail, count); + + if (avail > count) + avail = count; + memcpy(priv->xdr_buf + cached, buf, avail); + + priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; + + mutex_unlock(&priv->lock); + + buf += avail; + count -= avail; + to += avail; + } + + *retlen = len; + return 0; +} + +static int ps3vram_proc_show(struct seq_file *m, void *v) +{ + struct ps3vram_priv *priv = m->private; + + seq_printf(m, "hit:%u\nmiss:%u\n", priv->cache.hit, priv->cache.miss); + return 0; +} + +static int ps3vram_proc_open(struct inode *inode, struct file *file) +{ + return single_open(file, ps3vram_proc_show, PDE(inode)->data); +} + +static const struct file_operations ps3vram_proc_fops = { + .owner = THIS_MODULE, + .open = ps3vram_proc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; + +static void __devinit ps3vram_proc_init(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + struct proc_dir_entry *pde; + + pde = proc_create(DEVICE_NAME, 0444, NULL, &ps3vram_proc_fops); + if (!pde) { + dev_warn(&dev->core, "failed to create /proc entry\n"); + return; + } + + pde->owner = THIS_MODULE; + pde->data = priv; +} + +static int ps3vram_make_request(struct request_queue *q, struct bio *bio) +{ + struct ps3_system_bus_device *dev = q->queuedata; + int write = bio_data_dir(bio) == WRITE; + const char *op = write ? "write" : "read"; + loff_t offset = bio->bi_sector << 9; + int error = 0; + struct bio_vec *bvec; + unsigned int i; + + dev_dbg(&dev->core, "%s\n", __func__); + + bio_for_each_segment(bvec, bio, i) { + /* PS3 is ppc64, so we don't handle highmem */ + char *ptr = page_address(bvec->bv_page) + bvec->bv_offset; + size_t len = bvec->bv_len, retlen; + + dev_dbg(&dev->core, " %s %zu bytes at offset %llu\n", op, + len, offset); + if (write) + error = ps3vram_write(dev, offset, len, &retlen, ptr); + else + error = ps3vram_read(dev, offset, len, &retlen, ptr); + + if (error) { + dev_err(&dev->core, "%s failed\n", op); + goto out; + } + + if (retlen != len) { + dev_err(&dev->core, "Short %s\n", op); + goto out; + } + + offset += len; + } + + dev_dbg(&dev->core, "%s completed\n", op); + +out: + bio_endio(bio, error); + return 0; +} + +static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv; + int error, status; + struct request_queue *queue; + struct gendisk *gendisk; + u64 ddr_lpar, ctrl_lpar, info_lpar, reports_lpar, ddr_size, + reports_size; + char *rest; + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + error = -ENOMEM; + goto fail; + } + + mutex_init(&priv->lock); + dev->core.driver_data = priv; + + priv = dev->core.driver_data; + + /* Allocate XDR buffer (1MiB aligned) */ + priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, + get_order(XDR_BUF_SIZE)); + if (priv->xdr_buf == NULL) { + dev_err(&dev->core, "Could not allocate XDR buffer\n"); + error = -ENOMEM; + goto fail_free_priv; + } + + /* Put FIFO at begginning of XDR buffer */ + priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); + priv->fifo_ptr = priv->fifo_base; + + /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */ + if (ps3_open_hv_device(dev)) { + dev_err(&dev->core, "ps3_open_hv_device failed\n"); + error = -EAGAIN; + goto out_close_gpu; + } + + /* Request memory */ + status = -1; + ddr_size = ALIGN(memparse(size, &rest), 1024*1024); + if (!ddr_size) { + dev_err(&dev->core, "Specified size is too small\n"); + error = -EINVAL; + goto out_close_gpu; + } + + while (ddr_size > 0) { + status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0, + &priv->memory_handle, + &ddr_lpar); + if (!status) + break; + ddr_size -= 1024*1024; + } + if (status) { + dev_err(&dev->core, "lv1_gpu_memory_allocate failed %d\n", + status); + error = -ENOMEM; + goto out_free_xdr_buf; + } + + /* Request context */ + status = lv1_gpu_context_allocate(priv->memory_handle, 0, + &priv->context_handle, &ctrl_lpar, + &info_lpar, &reports_lpar, + &reports_size); + if (status) { + dev_err(&dev->core, "lv1_gpu_context_allocate failed %d\n", + status); + error = -ENOMEM; + goto out_free_memory; + } + + /* Map XDR buffer to RSX */ + status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, + ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), + XDR_BUF_SIZE, 0); + if (status) { + dev_err(&dev->core, "lv1_gpu_context_iomap failed %d\n", + status); + error = -ENOMEM; + goto out_free_context; + } + + priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE); + + if (!priv->ddr_base) { + dev_err(&dev->core, "ioremap DDR failed\n"); + error = -ENOMEM; + goto out_free_context; + } + + priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); + if (!priv->ctrl) { + dev_err(&dev->core, "ioremap CTRL failed\n"); + error = -ENOMEM; + goto out_unmap_vram; + } + + priv->reports = ioremap(reports_lpar, reports_size); + if (!priv->reports) { + dev_err(&dev->core, "ioremap REPORTS failed\n"); + error = -ENOMEM; + goto out_unmap_ctrl; + } + + mutex_lock(&ps3_gpu_mutex); + ps3vram_init_ring(dev); + mutex_unlock(&ps3_gpu_mutex); + + priv->size = ddr_size; + + ps3vram_bind(dev); + + mutex_lock(&ps3_gpu_mutex); + error = ps3vram_wait_ring(dev, 100); + mutex_unlock(&ps3_gpu_mutex); + if (error < 0) { + dev_err(&dev->core, "Failed to initialize channels\n"); + error = -ETIMEDOUT; + goto out_unmap_reports; + } + + ps3vram_cache_init(dev); + ps3vram_proc_init(dev); + + queue = blk_alloc_queue(GFP_KERNEL); + if (!queue) { + dev_err(&dev->core, "blk_alloc_queue failed\n"); + error = -ENOMEM; + goto out_cache_cleanup; + } + + priv->queue = queue; + queue->queuedata = dev; + blk_queue_make_request(queue, ps3vram_make_request); + blk_queue_max_phys_segments(queue, MAX_PHYS_SEGMENTS); + blk_queue_max_hw_segments(queue, MAX_HW_SEGMENTS); + blk_queue_max_segment_size(queue, MAX_SEGMENT_SIZE); + blk_queue_max_sectors(queue, SAFE_MAX_SECTORS); + + gendisk = alloc_disk(1); + if (!gendisk) { + dev_err(&dev->core, "alloc_disk failed\n"); + error = -ENOMEM; + goto fail_cleanup_queue; + } + + priv->gendisk = gendisk; + gendisk->major = ps3vram_major; + gendisk->first_minor = 0; + gendisk->fops = &ps3vram_fops; + gendisk->queue = queue; + gendisk->private_data = dev; + gendisk->driverfs_dev = &dev->core; + strlcpy(gendisk->disk_name, DEVICE_NAME, sizeof(gendisk->disk_name)); + set_capacity(gendisk, priv->size >> 9); + + dev_info(&dev->core, "%s: Using %lu MiB of GPU memory\n", + gendisk->disk_name, get_capacity(gendisk) >> 11); + + add_disk(gendisk); + return 0; + +fail_cleanup_queue: + blk_cleanup_queue(queue); +out_cache_cleanup: + remove_proc_entry(DEVICE_NAME, NULL); + ps3vram_cache_cleanup(dev); +out_unmap_reports: + iounmap(priv->reports); +out_unmap_ctrl: + iounmap(priv->ctrl); +out_unmap_vram: + iounmap(priv->ddr_base); +out_free_context: + lv1_gpu_context_free(priv->context_handle); +out_free_memory: + lv1_gpu_memory_free(priv->memory_handle); +out_close_gpu: + ps3_close_hv_device(dev); +out_free_xdr_buf: + free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); +fail_free_priv: + kfree(priv); + dev->core.driver_data = NULL; +fail: + return error; +} + +static int ps3vram_remove(struct ps3_system_bus_device *dev) +{ + struct ps3vram_priv *priv = dev->core.driver_data; + + del_gendisk(priv->gendisk); + put_disk(priv->gendisk); + blk_cleanup_queue(priv->queue); + remove_proc_entry(DEVICE_NAME, NULL); + ps3vram_cache_cleanup(dev); + iounmap(priv->reports); + iounmap(priv->ctrl); + iounmap(priv->ddr_base); + lv1_gpu_context_free(priv->context_handle); + lv1_gpu_memory_free(priv->memory_handle); + ps3_close_hv_device(dev); + free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); + kfree(priv); + dev->core.driver_data = NULL; + return 0; +} + +static struct ps3_system_bus_driver ps3vram = { + .match_id = PS3_MATCH_ID_GPU, + .match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK, + .core.name = DEVICE_NAME, + .core.owner = THIS_MODULE, + .probe = ps3vram_probe, + .remove = ps3vram_remove, + .shutdown = ps3vram_remove, +}; + + +static int __init ps3vram_init(void) +{ + int error; + + if (!firmware_has_feature(FW_FEATURE_PS3_LV1)) + return -ENODEV; + + error = register_blkdev(0, DEVICE_NAME); + if (error <= 0) { + pr_err("%s: register_blkdev failed %d\n", DEVICE_NAME, error); + return error; + } + ps3vram_major = error; + + pr_info("%s: registered block device major %d\n", DEVICE_NAME, + ps3vram_major); + + error = ps3_system_bus_driver_register(&ps3vram); + if (error) + unregister_blkdev(ps3vram_major, DEVICE_NAME); + + return error; +} + +static void __exit ps3vram_exit(void) +{ + ps3_system_bus_driver_unregister(&ps3vram); + unregister_blkdev(ps3vram_major, DEVICE_NAME); +} + +module_init(ps3vram_init); +module_exit(ps3vram_exit); + +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("PS3 Video RAM Storage Driver"); +MODULE_AUTHOR("Sony Corporation"); +MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK); diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index bc33200535f..6fde0a2e356 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig @@ -120,13 +120,6 @@ config MTD_PHRAM doesn't have access to, memory beyond the mem=xxx limit, nvram, memory on the video card, etc... -config MTD_PS3VRAM - tristate "PS3 video RAM" - depends on FB_PS3 - help - This driver allows you to use excess PS3 video RAM as volatile - storage or system swap. - config MTD_LART tristate "28F160xx flash driver for LART" depends on SA1100_LART diff --git a/drivers/mtd/devices/Makefile b/drivers/mtd/devices/Makefile index e51521df4e4..0993d5cf392 100644 --- a/drivers/mtd/devices/Makefile +++ b/drivers/mtd/devices/Makefile @@ -16,4 +16,3 @@ obj-$(CONFIG_MTD_LART) += lart.o obj-$(CONFIG_MTD_BLOCK2MTD) += block2mtd.o obj-$(CONFIG_MTD_DATAFLASH) += mtd_dataflash.o obj-$(CONFIG_MTD_M25P80) += m25p80.o -obj-$(CONFIG_MTD_PS3VRAM) += ps3vram.o diff --git a/drivers/mtd/devices/ps3vram.c b/drivers/mtd/devices/ps3vram.c deleted file mode 100644 index d21e9beb7ed..00000000000 --- a/drivers/mtd/devices/ps3vram.c +++ /dev/null @@ -1,768 +0,0 @@ -/** - * ps3vram - Use extra PS3 video ram as MTD block device. - * - * Copyright (c) 2007-2008 Jim Paris - * Added support RSX DMA Vivien Chappelier - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define DEVICE_NAME "ps3vram" - -#define XDR_BUF_SIZE (2 * 1024 * 1024) /* XDR buffer (must be 1MiB aligned) */ -#define XDR_IOIF 0x0c000000 - -#define FIFO_BASE XDR_IOIF -#define FIFO_SIZE (64 * 1024) - -#define DMA_PAGE_SIZE (4 * 1024) - -#define CACHE_PAGE_SIZE (256 * 1024) -#define CACHE_PAGE_COUNT ((XDR_BUF_SIZE - FIFO_SIZE) / CACHE_PAGE_SIZE) - -#define CACHE_OFFSET CACHE_PAGE_SIZE -#define FIFO_OFFSET 0 - -#define CTRL_PUT 0x10 -#define CTRL_GET 0x11 -#define CTRL_TOP 0x15 - -#define UPLOAD_SUBCH 1 -#define DOWNLOAD_SUBCH 2 - -#define NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN 0x0000030c -#define NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY 0x00000104 - -#define L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT 0x601 - -struct mtd_info ps3vram_mtd; - -#define CACHE_PAGE_PRESENT 1 -#define CACHE_PAGE_DIRTY 2 - -struct ps3vram_tag { - unsigned int address; - unsigned int flags; -}; - -struct ps3vram_cache { - unsigned int page_count; - unsigned int page_size; - struct ps3vram_tag *tags; -}; - -struct ps3vram_priv { - u64 memory_handle; - u64 context_handle; - u32 *ctrl; - u32 *reports; - u8 __iomem *ddr_base; - u8 *xdr_buf; - - u32 *fifo_base; - u32 *fifo_ptr; - - struct device *dev; - struct ps3vram_cache cache; - - /* Used to serialize cache/DMA operations */ - struct mutex lock; -}; - -#define DMA_NOTIFIER_HANDLE_BASE 0x66604200 /* first DMA notifier handle */ -#define DMA_NOTIFIER_OFFSET_BASE 0x1000 /* first DMA notifier offset */ -#define DMA_NOTIFIER_SIZE 0x40 -#define NOTIFIER 7 /* notifier used for completion report */ - -/* A trailing '-' means to subtract off ps3fb_videomemory.size */ -char *size = "256M-"; -module_param(size, charp, 0); -MODULE_PARM_DESC(size, "memory size"); - -static u32 *ps3vram_get_notifier(u32 *reports, int notifier) -{ - return (void *) reports + - DMA_NOTIFIER_OFFSET_BASE + - DMA_NOTIFIER_SIZE * notifier; -} - -static void ps3vram_notifier_reset(struct mtd_info *mtd) -{ - int i; - - struct ps3vram_priv *priv = mtd->priv; - u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); - for (i = 0; i < 4; i++) - notify[i] = 0xffffffff; -} - -static int ps3vram_notifier_wait(struct mtd_info *mtd, unsigned int timeout_ms) -{ - struct ps3vram_priv *priv = mtd->priv; - u32 *notify = ps3vram_get_notifier(priv->reports, NOTIFIER); - unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); - - do { - if (!notify[3]) - return 0; - msleep(1); - } while (time_before(jiffies, timeout)); - - return -ETIMEDOUT; -} - -static void ps3vram_init_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; - priv->ctrl[CTRL_GET] = FIFO_BASE + FIFO_OFFSET; -} - -static int ps3vram_wait_ring(struct mtd_info *mtd, unsigned int timeout_ms) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned long timeout = jiffies + msecs_to_jiffies(timeout_ms); - - do { - if (priv->ctrl[CTRL_PUT] == priv->ctrl[CTRL_GET]) - return 0; - msleep(1); - } while (time_before(jiffies, timeout)); - - dev_dbg(priv->dev, "%s:%d: FIFO timeout (%08x/%08x/%08x)\n", __func__, - __LINE__, priv->ctrl[CTRL_PUT], priv->ctrl[CTRL_GET], - priv->ctrl[CTRL_TOP]); - - return -ETIMEDOUT; -} - -static void ps3vram_out_ring(struct ps3vram_priv *priv, u32 data) -{ - *(priv->fifo_ptr)++ = data; -} - -static void ps3vram_begin_ring(struct ps3vram_priv *priv, u32 chan, - u32 tag, u32 size) -{ - ps3vram_out_ring(priv, (size << 18) | (chan << 13) | tag); -} - -static void ps3vram_rewind_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - u64 status; - - ps3vram_out_ring(priv, 0x20000000 | (FIFO_BASE + FIFO_OFFSET)); - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET; - - /* asking the HV for a blit will kick the fifo */ - status = lv1_gpu_context_attribute(priv->context_handle, - L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, - 0, 0, 0, 0); - if (status) - dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n", - __func__, __LINE__); - - priv->fifo_ptr = priv->fifo_base; -} - -static void ps3vram_fire_ring(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - u64 status; - - mutex_lock(&ps3_gpu_mutex); - - priv->ctrl[CTRL_PUT] = FIFO_BASE + FIFO_OFFSET + - (priv->fifo_ptr - priv->fifo_base) * sizeof(u32); - - /* asking the HV for a blit will kick the fifo */ - status = lv1_gpu_context_attribute(priv->context_handle, - L1GPU_CONTEXT_ATTRIBUTE_FB_BLIT, - 0, 0, 0, 0); - if (status) - dev_err(priv->dev, "%s:%d: lv1_gpu_context_attribute failed\n", - __func__, __LINE__); - - if ((priv->fifo_ptr - priv->fifo_base) * sizeof(u32) > - FIFO_SIZE - 1024) { - dev_dbg(priv->dev, "%s:%d: fifo full, rewinding\n", __func__, - __LINE__); - ps3vram_wait_ring(mtd, 200); - ps3vram_rewind_ring(mtd); - } - - mutex_unlock(&ps3_gpu_mutex); -} - -static void ps3vram_bind(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0, 1); - ps3vram_out_ring(priv, 0x31337303); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x180, 3); - ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); - ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ - ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ - - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0, 1); - ps3vram_out_ring(priv, 0x3137c0de); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x180, 3); - ps3vram_out_ring(priv, DMA_NOTIFIER_HANDLE_BASE + NOTIFIER); - ps3vram_out_ring(priv, 0xfeed0000); /* DMA video RAM instance */ - ps3vram_out_ring(priv, 0xfeed0001); /* DMA system RAM instance */ - - ps3vram_fire_ring(mtd); -} - -static int ps3vram_upload(struct mtd_info *mtd, unsigned int src_offset, - unsigned int dst_offset, int len, int count) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, UPLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - ps3vram_out_ring(priv, XDR_IOIF + src_offset); - ps3vram_out_ring(priv, dst_offset); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, count); - ps3vram_out_ring(priv, (1 << 8) | 1); - ps3vram_out_ring(priv, 0); - - ps3vram_notifier_reset(mtd); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); - ps3vram_out_ring(priv, 0); - ps3vram_begin_ring(priv, UPLOAD_SUBCH, 0x100, 1); - ps3vram_out_ring(priv, 0); - ps3vram_fire_ring(mtd); - if (ps3vram_notifier_wait(mtd, 200) < 0) { - dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__, - __LINE__); - return -1; - } - - return 0; -} - -static int ps3vram_download(struct mtd_info *mtd, unsigned int src_offset, - unsigned int dst_offset, int len, int count) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN, 8); - ps3vram_out_ring(priv, src_offset); - ps3vram_out_ring(priv, XDR_IOIF + dst_offset); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, len); - ps3vram_out_ring(priv, count); - ps3vram_out_ring(priv, (1 << 8) | 1); - ps3vram_out_ring(priv, 0); - - ps3vram_notifier_reset(mtd); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, - NV_MEMORY_TO_MEMORY_FORMAT_NOTIFY, 1); - ps3vram_out_ring(priv, 0); - ps3vram_begin_ring(priv, DOWNLOAD_SUBCH, 0x100, 1); - ps3vram_out_ring(priv, 0); - ps3vram_fire_ring(mtd); - if (ps3vram_notifier_wait(mtd, 200) < 0) { - dev_dbg(priv->dev, "%s:%d: notifier timeout\n", __func__, - __LINE__); - return -1; - } - - return 0; -} - -static void ps3vram_cache_evict(struct mtd_info *mtd, int entry) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - - if (cache->tags[entry].flags & CACHE_PAGE_DIRTY) { - dev_dbg(priv->dev, "%s:%d: flushing %d : 0x%08x\n", __func__, - __LINE__, entry, cache->tags[entry].address); - if (ps3vram_upload(mtd, - CACHE_OFFSET + entry * cache->page_size, - cache->tags[entry].address, - DMA_PAGE_SIZE, - cache->page_size / DMA_PAGE_SIZE) < 0) { - dev_dbg(priv->dev, "%s:%d: failed to upload from " - "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, - entry * cache->page_size, - cache->tags[entry].address, cache->page_size); - } - cache->tags[entry].flags &= ~CACHE_PAGE_DIRTY; - } -} - -static void ps3vram_cache_load(struct mtd_info *mtd, int entry, - unsigned int address) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - - dev_dbg(priv->dev, "%s:%d: fetching %d : 0x%08x\n", __func__, __LINE__, - entry, address); - if (ps3vram_download(mtd, - address, - CACHE_OFFSET + entry * cache->page_size, - DMA_PAGE_SIZE, - cache->page_size / DMA_PAGE_SIZE) < 0) { - dev_err(priv->dev, "%s:%d: failed to download from " - "0x%x to 0x%x size 0x%x\n", __func__, __LINE__, address, - entry * cache->page_size, cache->page_size); - } - - cache->tags[entry].address = address; - cache->tags[entry].flags |= CACHE_PAGE_PRESENT; -} - - -static void ps3vram_cache_flush(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - int i; - - dev_dbg(priv->dev, "%s:%d: FLUSH\n", __func__, __LINE__); - for (i = 0; i < cache->page_count; i++) { - ps3vram_cache_evict(mtd, i); - cache->tags[i].flags = 0; - } -} - -static unsigned int ps3vram_cache_match(struct mtd_info *mtd, loff_t address) -{ - struct ps3vram_priv *priv = mtd->priv; - struct ps3vram_cache *cache = &priv->cache; - unsigned int base; - unsigned int offset; - int i; - static int counter; - - offset = (unsigned int) (address & (cache->page_size - 1)); - base = (unsigned int) (address - offset); - - /* fully associative check */ - for (i = 0; i < cache->page_count; i++) { - if ((cache->tags[i].flags & CACHE_PAGE_PRESENT) && - cache->tags[i].address == base) { - dev_dbg(priv->dev, "%s:%d: found entry %d : 0x%08x\n", - __func__, __LINE__, i, cache->tags[i].address); - return i; - } - } - - /* choose a random entry */ - i = (jiffies + (counter++)) % cache->page_count; - dev_dbg(priv->dev, "%s:%d: using entry %d\n", __func__, __LINE__, i); - - ps3vram_cache_evict(mtd, i); - ps3vram_cache_load(mtd, i, base); - - return i; -} - -static int ps3vram_cache_init(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - priv->cache.page_count = CACHE_PAGE_COUNT; - priv->cache.page_size = CACHE_PAGE_SIZE; - priv->cache.tags = kzalloc(sizeof(struct ps3vram_tag) * - CACHE_PAGE_COUNT, GFP_KERNEL); - if (priv->cache.tags == NULL) { - dev_err(priv->dev, "%s:%d: could not allocate cache tags\n", - __func__, __LINE__); - return -ENOMEM; - } - - dev_info(priv->dev, "created ram cache: %d entries, %d KiB each\n", - CACHE_PAGE_COUNT, CACHE_PAGE_SIZE / 1024); - - return 0; -} - -static void ps3vram_cache_cleanup(struct mtd_info *mtd) -{ - struct ps3vram_priv *priv = mtd->priv; - - ps3vram_cache_flush(mtd); - kfree(priv->cache.tags); -} - -static int ps3vram_erase(struct mtd_info *mtd, struct erase_info *instr) -{ - struct ps3vram_priv *priv = mtd->priv; - - if (instr->addr + instr->len > mtd->size) - return -EINVAL; - - mutex_lock(&priv->lock); - - ps3vram_cache_flush(mtd); - - /* Set bytes to 0xFF */ - memset_io(priv->ddr_base + instr->addr, 0xFF, instr->len); - - mutex_unlock(&priv->lock); - - instr->state = MTD_ERASE_DONE; - mtd_erase_callback(instr); - - return 0; -} - -static int ps3vram_read(struct mtd_info *mtd, loff_t from, size_t len, - size_t *retlen, u_char *buf) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned int cached, count; - - dev_dbg(priv->dev, "%s:%d: from=0x%08x len=0x%zx\n", __func__, __LINE__, - (unsigned int)from, len); - - if (from >= mtd->size) - return -EINVAL; - - if (len > mtd->size - from) - len = mtd->size - from; - - /* Copy from vram to buf */ - count = len; - while (count) { - unsigned int offset, avail; - unsigned int entry; - - offset = (unsigned int) (from & (priv->cache.page_size - 1)); - avail = priv->cache.page_size - offset; - - mutex_lock(&priv->lock); - - entry = ps3vram_cache_match(mtd, from); - cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; - - dev_dbg(priv->dev, "%s:%d: from=%08x cached=%08x offset=%08x " - "avail=%08x count=%08x\n", __func__, __LINE__, - (unsigned int)from, cached, offset, avail, count); - - if (avail > count) - avail = count; - memcpy(buf, priv->xdr_buf + cached, avail); - - mutex_unlock(&priv->lock); - - buf += avail; - count -= avail; - from += avail; - } - - *retlen = len; - return 0; -} - -static int ps3vram_write(struct mtd_info *mtd, loff_t to, size_t len, - size_t *retlen, const u_char *buf) -{ - struct ps3vram_priv *priv = mtd->priv; - unsigned int cached, count; - - if (to >= mtd->size) - return -EINVAL; - - if (len > mtd->size - to) - len = mtd->size - to; - - /* Copy from buf to vram */ - count = len; - while (count) { - unsigned int offset, avail; - unsigned int entry; - - offset = (unsigned int) (to & (priv->cache.page_size - 1)); - avail = priv->cache.page_size - offset; - - mutex_lock(&priv->lock); - - entry = ps3vram_cache_match(mtd, to); - cached = CACHE_OFFSET + entry * priv->cache.page_size + offset; - - dev_dbg(priv->dev, "%s:%d: to=%08x cached=%08x offset=%08x " - "avail=%08x count=%08x\n", __func__, __LINE__, - (unsigned int)to, cached, offset, avail, count); - - if (avail > count) - avail = count; - memcpy(priv->xdr_buf + cached, buf, avail); - - priv->cache.tags[entry].flags |= CACHE_PAGE_DIRTY; - - mutex_unlock(&priv->lock); - - buf += avail; - count -= avail; - to += avail; - } - - *retlen = len; - return 0; -} - -static int __devinit ps3vram_probe(struct ps3_system_bus_device *dev) -{ - struct ps3vram_priv *priv; - int status; - u64 ddr_lpar; - u64 ctrl_lpar; - u64 info_lpar; - u64 reports_lpar; - u64 ddr_size; - u64 reports_size; - int ret = -ENOMEM; - char *rest; - - ret = -EIO; - ps3vram_mtd.priv = kzalloc(sizeof(struct ps3vram_priv), GFP_KERNEL); - if (!ps3vram_mtd.priv) - goto out; - priv = ps3vram_mtd.priv; - - mutex_init(&priv->lock); - priv->dev = &dev->core; - - /* Allocate XDR buffer (1MiB aligned) */ - priv->xdr_buf = (void *)__get_free_pages(GFP_KERNEL, - get_order(XDR_BUF_SIZE)); - if (priv->xdr_buf == NULL) { - dev_dbg(&dev->core, "%s:%d: could not allocate XDR buffer\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_priv; - } - - /* Put FIFO at begginning of XDR buffer */ - priv->fifo_base = (u32 *) (priv->xdr_buf + FIFO_OFFSET); - priv->fifo_ptr = priv->fifo_base; - - /* XXX: Need to open GPU, in case ps3fb or snd_ps3 aren't loaded */ - if (ps3_open_hv_device(dev)) { - dev_err(&dev->core, "%s:%d: ps3_open_hv_device failed\n", - __func__, __LINE__); - ret = -EAGAIN; - goto out_close_gpu; - } - - /* Request memory */ - status = -1; - ddr_size = memparse(size, &rest); - if (*rest == '-') - ddr_size -= ps3fb_videomemory.size; - ddr_size = ALIGN(ddr_size, 1024*1024); - if (ddr_size <= 0) { - dev_err(&dev->core, "%s:%d: specified size is too small\n", - __func__, __LINE__); - ret = -EINVAL; - goto out_close_gpu; - } - - while (ddr_size > 0) { - status = lv1_gpu_memory_allocate(ddr_size, 0, 0, 0, 0, - &priv->memory_handle, - &ddr_lpar); - if (!status) - break; - ddr_size -= 1024*1024; - } - if (status || ddr_size <= 0) { - dev_err(&dev->core, "%s:%d: lv1_gpu_memory_allocate failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_xdr_buf; - } - - /* Request context */ - status = lv1_gpu_context_allocate(priv->memory_handle, - 0, - &priv->context_handle, - &ctrl_lpar, - &info_lpar, - &reports_lpar, - &reports_size); - if (status) { - dev_err(&dev->core, "%s:%d: lv1_gpu_context_allocate failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_memory; - } - - /* Map XDR buffer to RSX */ - status = lv1_gpu_context_iomap(priv->context_handle, XDR_IOIF, - ps3_mm_phys_to_lpar(__pa(priv->xdr_buf)), - XDR_BUF_SIZE, 0); - if (status) { - dev_err(&dev->core, "%s:%d: lv1_gpu_context_iomap failed\n", - __func__, __LINE__); - ret = -ENOMEM; - goto out_free_context; - } - - priv->ddr_base = ioremap_flags(ddr_lpar, ddr_size, _PAGE_NO_CACHE); - - if (!priv->ddr_base) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_free_context; - } - - priv->ctrl = ioremap(ctrl_lpar, 64 * 1024); - if (!priv->ctrl) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_unmap_vram; - } - - priv->reports = ioremap(reports_lpar, reports_size); - if (!priv->reports) { - dev_err(&dev->core, "%s:%d: ioremap failed\n", __func__, - __LINE__); - ret = -ENOMEM; - goto out_unmap_ctrl; - } - - mutex_lock(&ps3_gpu_mutex); - ps3vram_init_ring(&ps3vram_mtd); - mutex_unlock(&ps3_gpu_mutex); - - ps3vram_mtd.name = "ps3vram"; - ps3vram_mtd.size = ddr_size; - ps3vram_mtd.flags = MTD_CAP_RAM; - ps3vram_mtd.erase = ps3vram_erase; - ps3vram_mtd.point = NULL; - ps3vram_mtd.unpoint = NULL; - ps3vram_mtd.read = ps3vram_read; - ps3vram_mtd.write = ps3vram_write; - ps3vram_mtd.owner = THIS_MODULE; - ps3vram_mtd.type = MTD_RAM; - ps3vram_mtd.erasesize = CACHE_PAGE_SIZE; - ps3vram_mtd.writesize = 1; - - ps3vram_bind(&ps3vram_mtd); - - mutex_lock(&ps3_gpu_mutex); - ret = ps3vram_wait_ring(&ps3vram_mtd, 100); - mutex_unlock(&ps3_gpu_mutex); - if (ret < 0) { - dev_err(&dev->core, "%s:%d: failed to initialize channels\n", - __func__, __LINE__); - ret = -ETIMEDOUT; - goto out_unmap_reports; - } - - ps3vram_cache_init(&ps3vram_mtd); - - if (add_mtd_device(&ps3vram_mtd)) { - dev_err(&dev->core, "%s:%d: add_mtd_device failed\n", - __func__, __LINE__); - ret = -EAGAIN; - goto out_cache_cleanup; - } - - dev_info(&dev->core, "reserved %u MiB of gpu memory\n", - (unsigned int)(ddr_size / 1024 / 1024)); - - return 0; - -out_cache_cleanup: - ps3vram_cache_cleanup(&ps3vram_mtd); -out_unmap_reports: - iounmap(priv->reports); -out_unmap_ctrl: - iounmap(priv->ctrl); -out_unmap_vram: - iounmap(priv->ddr_base); -out_free_context: - lv1_gpu_context_free(priv->context_handle); -out_free_memory: - lv1_gpu_memory_free(priv->memory_handle); -out_close_gpu: - ps3_close_hv_device(dev); -out_free_xdr_buf: - free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); -out_free_priv: - kfree(ps3vram_mtd.priv); - ps3vram_mtd.priv = NULL; -out: - return ret; -} - -static int ps3vram_shutdown(struct ps3_system_bus_device *dev) -{ - struct ps3vram_priv *priv; - - priv = ps3vram_mtd.priv; - - del_mtd_device(&ps3vram_mtd); - ps3vram_cache_cleanup(&ps3vram_mtd); - iounmap(priv->reports); - iounmap(priv->ctrl); - iounmap(priv->ddr_base); - lv1_gpu_context_free(priv->context_handle); - lv1_gpu_memory_free(priv->memory_handle); - ps3_close_hv_device(dev); - free_pages((unsigned long) priv->xdr_buf, get_order(XDR_BUF_SIZE)); - kfree(priv); - return 0; -} - -static struct ps3_system_bus_driver ps3vram_driver = { - .match_id = PS3_MATCH_ID_GPU, - .match_sub_id = PS3_MATCH_SUB_ID_GPU_RAMDISK, - .core.name = DEVICE_NAME, - .core.owner = THIS_MODULE, - .probe = ps3vram_probe, - .remove = ps3vram_shutdown, - .shutdown = ps3vram_shutdown, -}; - -static int __init ps3vram_init(void) -{ - return ps3_system_bus_driver_register(&ps3vram_driver); -} - -static void __exit ps3vram_exit(void) -{ - ps3_system_bus_driver_unregister(&ps3vram_driver); -} - -module_init(ps3vram_init); -module_exit(ps3vram_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Jim Paris "); -MODULE_DESCRIPTION("MTD driver for PS3 video RAM"); -MODULE_ALIAS(PS3_MODULE_ALIAS_GPU_RAMDISK); -- cgit v1.2.3 From bfe4f4f800ccbb499a1120735016a20d3feacd4f Mon Sep 17 00:00:00 2001 From: James Bottomley Date: Fri, 9 Jan 2009 18:57:06 -0600 Subject: parisc: remove klist iterators commit 11c3b5c3e08f4d855cbef52883c266b9ab9df879 Author: Greg Kroah-Hartman Date: Tue Dec 16 12:24:56 2008 -0800 driver core: move klist_children into private structure Broke our parisc build pretty badly because we touch the klists directly in three cases (AGP, SBA and GSC). Although GregKH will revert this patch, there's no reason we should be using the iterators directly, we can just move to the standard device_for_each_child() API. Signed-off-by: James Bottomley Tested-by: Helge Deller Tested-by: Kyle McMartin Signed-off-by: Kyle McMartin --- drivers/char/agp/parisc-agp.c | 23 ++++++++-------- drivers/parisc/gsc.c | 39 +++++++++++++++------------ drivers/parisc/sba_iommu.c | 61 +++++++++++++++++++++++++------------------ 3 files changed, 68 insertions(+), 55 deletions(-) (limited to 'drivers') diff --git a/drivers/char/agp/parisc-agp.c b/drivers/char/agp/parisc-agp.c index db60539bf67..699e3422ad9 100644 --- a/drivers/char/agp/parisc-agp.c +++ b/drivers/char/agp/parisc-agp.c @@ -359,9 +359,16 @@ fail: return error; } -static struct device *next_device(struct klist_iter *i) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; +static int +find_quicksilver(struct device *dev, void *data) +{ + struct parisc_device **lba = data; + struct parisc_device *padev = to_parisc_device(dev); + + if (IS_QUICKSILVER(padev)) + *lba = padev; + + return 0; } static int @@ -372,8 +379,6 @@ parisc_agp_init(void) int err = -1; struct parisc_device *sba = NULL, *lba = NULL; struct lba_device *lbadev = NULL; - struct device *dev = NULL; - struct klist_iter i; if (!sba_list) goto out; @@ -386,13 +391,7 @@ parisc_agp_init(void) } /* Now search our Pluto for our precious AGP device... */ - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *padev = to_parisc_device(dev); - if (IS_QUICKSILVER(padev)) - lba = padev; - } - klist_iter_exit(&i); + device_for_each_child(&sba->dev, &lba, find_quicksilver); if (!lba) { printk(KERN_INFO DRVPFX "No AGP devices found.\n"); diff --git a/drivers/parisc/gsc.c b/drivers/parisc/gsc.c index e76db9e4d50..d3363291769 100644 --- a/drivers/parisc/gsc.c +++ b/drivers/parisc/gsc.c @@ -186,29 +186,34 @@ void gsc_asic_assign_irq(struct gsc_asic *asic, int local_irq, int *irqp) *irqp = irq; } -static struct device *next_device(struct klist_iter *i) +struct gsc_fixup_struct { + void (*choose_irq)(struct parisc_device *, void *); + void *ctrl; +}; + +static int gsc_fixup_irqs_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + struct parisc_device *padev = to_parisc_device(dev); + struct gsc_fixup_struct *gf = data; + + /* work-around for 715/64 and others which have parent + at path [5] and children at path [5/0/x] */ + if (padev->id.hw_type == HPHW_FAULTY) + gsc_fixup_irqs(padev, gf->ctrl, gf->choose_irq); + gf->choose_irq(padev, gf->ctrl); + + return 0; } void gsc_fixup_irqs(struct parisc_device *parent, void *ctrl, void (*choose_irq)(struct parisc_device *, void *)) { - struct device *dev; - struct klist_iter i; - - klist_iter_init(&parent->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *padev = to_parisc_device(dev); - - /* work-around for 715/64 and others which have parent - at path [5] and children at path [5/0/x] */ - if (padev->id.hw_type == HPHW_FAULTY) - return gsc_fixup_irqs(padev, ctrl, choose_irq); - choose_irq(padev, ctrl); - } - klist_iter_exit(&i); + struct gsc_fixup_struct data = { + .choose_irq = choose_irq, + .ctrl = ctrl, + }; + + device_for_each_child(&parent->dev, &data, gsc_fixup_irqs_callback); } int gsc_common_setup(struct parisc_device *parent, struct gsc_asic *gsc_asic) diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index a70cf16ee1a..6aad8546fd2 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1206,31 +1206,49 @@ sba_alloc_pdir(unsigned int pdir_size) return (void *) pdir_base; } -static struct device *next_device(struct klist_iter *i) +struct ibase_data_struct { + struct ioc *ioc; + int ioc_num; +}; + +static int setup_ibase_imask_callback(struct device *dev, void *data) { - struct klist_node * n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ + extern void lba_set_iregs(struct parisc_device *, u32, u32); + struct parisc_device *lba = to_parisc_device(dev); + struct ibase_data_struct *ibd = data; + int rope_num = (lba->hpa.start >> 13) & 0xf; + if (rope_num >> 3 == ibd->ioc_num) + lba_set_iregs(lba, ibd->ioc->ibase, ibd->ioc->imask); + return 0; } /* setup Mercury or Elroy IBASE/IMASK registers. */ static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { - /* lba_set_iregs() is in drivers/parisc/lba_pci.c */ - extern void lba_set_iregs(struct parisc_device *, u32, u32); - struct device *dev; - struct klist_iter i; - - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *lba = to_parisc_device(dev); - int rope_num = (lba->hpa.start >> 13) & 0xf; - if (rope_num >> 3 == ioc_num) - lba_set_iregs(lba, ioc->ibase, ioc->imask); - } - klist_iter_exit(&i); + struct ibase_data_struct ibase_data = { + .ioc = ioc, + .ioc_num = ioc_num, + }; + + device_for_each_child(&sba->dev, &ibase_data, + setup_ibase_imask_callback); } +#ifdef SBA_AGP_SUPPORT +static int +sba_ioc_find_quicksilver(struct device *dev, void *data) +{ + int *agp_found = data; + struct parisc_device *lba = to_parisc_device(dev); + + if (IS_QUICKSILVER(lba)) + *agp_found = 1; + return 0; +} +#endif + static void sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) { @@ -1332,9 +1350,6 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) WRITE_REG(ioc->ibase | 31, ioc->ioc_hpa + IOC_PCOM); #ifdef SBA_AGP_SUPPORT -{ - struct klist_iter i; - struct device *dev = NULL; /* ** If an AGP device is present, only use half of the IOV space @@ -1344,13 +1359,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ** We program the next pdir index after we stop w/ a key for ** the GART code to handshake on. */ - klist_iter_init(&sba->dev.klist_children, &i); - while ((dev = next_device(&i))) { - struct parisc_device *lba = to_parisc_device(dev); - if (IS_QUICKSILVER(lba)) - agp_found = 1; - } - klist_iter_exit(&i); + device_for_each_child(&sba->dev, &agp_found, sba_ioc_find_quicksilver); if (agp_found && sba_reserve_agpgart) { printk(KERN_INFO "%s: reserving %dMb of IOVA space for agpgart\n", -- cgit v1.2.3 From 7f384ce780c6091968fc848b14f17b45cb849e14 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 13 Jan 2009 21:14:51 +0100 Subject: parisc: fix dev_printk() compile warnings for accessing a device struct Fix compile warnings: drivers/scsi/zalon.c: In function `zalon_probe': drivers/scsi/zalon.c:140: warning: passing arg 1 of `dev_driver_string' from incompatible pointer type drivers/scsi/zalon.c:140: warning: passing arg 1 of `dev_name' from incompatible pointer type Signed-off-by: Helge Deller Signed-off-by: Kyle McMartin --- drivers/scsi/lasi700.c | 2 +- drivers/scsi/zalon.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/lasi700.c b/drivers/scsi/lasi700.c index 4a4e6954ec7..f23c4ca9a2e 100644 --- a/drivers/scsi/lasi700.c +++ b/drivers/scsi/lasi700.c @@ -103,7 +103,7 @@ lasi700_probe(struct parisc_device *dev) hostdata = kzalloc(sizeof(*hostdata), GFP_KERNEL); if (!hostdata) { - dev_printk(KERN_ERR, dev, "Failed to allocate host data\n"); + dev_printk(KERN_ERR, &dev->dev, "Failed to allocate host data\n"); return -ENOMEM; } diff --git a/drivers/scsi/zalon.c b/drivers/scsi/zalon.c index a8d61a62522..97f3158fa7b 100644 --- a/drivers/scsi/zalon.c +++ b/drivers/scsi/zalon.c @@ -137,7 +137,7 @@ zalon_probe(struct parisc_device *dev) goto fail; if (request_irq(dev->irq, ncr53c8xx_intr, IRQF_SHARED, "zalon", host)) { - dev_printk(KERN_ERR, dev, "irq problem with %d, detaching\n ", + dev_printk(KERN_ERR, &dev->dev, "irq problem with %d, detaching\n ", dev->irq); goto fail; } -- cgit v1.2.3 From 9785d646c10b0707412516ffe56b71b9eb18861f Mon Sep 17 00:00:00 2001 From: Grant Grundler Date: Wed, 28 Jan 2009 22:30:55 -0700 Subject: parisc: fix wrong assumption about bus->self Kenji Kaneshige posted a patch series to linux-pci to fix a wrong assumption about pci_bus->self==NULL for all PCI host bus controllers. While PARISC platforms to not behave this way, I prefer to have the code consistent across architectures. The following patch replaces pci_bus->self with pci_bus->parent when used as a test to check for "root bus controller". Signed-off-by: Grant Grundler Signed-off-by: Kyle McMartin --- drivers/parisc/dino.c | 2 +- drivers/parisc/iosapic.c | 9 ++++----- drivers/parisc/lba_pci.c | 4 ++-- 3 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index d539d9df88e..f79266cd00e 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -587,7 +587,7 @@ dino_fixup_bus(struct pci_bus *bus) bus->resource[i+1] = &res[i]; } - } else if(bus->self) { + } else if (bus->parent) { int i; pci_read_bridge_bases(bus); diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 0797659ee01..1cdfdea5d7e 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -487,7 +487,7 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) } /* Check if pcidev behind a PPB */ - if (NULL != pcidev->bus->self) { + if (pcidev->bus->parent) { /* Convert pcidev INTR_PIN into something we ** can lookup in the IRT. */ @@ -523,10 +523,9 @@ iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev) #endif /* PCI_BRIDGE_FUNCS */ /* - ** Locate the host slot the PPB nearest the Host bus - ** adapter. - */ - while (NULL != p->parent->self) + * Locate the host slot of the PPB. + */ + while (p->parent->parent) p = p->parent; intr_slot = PCI_SLOT(p->self->devfn); diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c index d8233de8c75..59fbbf12836 100644 --- a/drivers/parisc/lba_pci.c +++ b/drivers/parisc/lba_pci.c @@ -644,7 +644,7 @@ lba_fixup_bus(struct pci_bus *bus) ** Properly Setup MMIO resources for this bus. ** pci_alloc_primary_bus() mangles this. */ - if (bus->self) { + if (bus->parent) { int i; /* PCI-PCI Bridge */ pci_read_bridge_bases(bus); @@ -802,7 +802,7 @@ lba_fixup_bus(struct pci_bus *bus) ** Can't fixup here anyway....garr... */ if (fbb_enable) { - if (bus->self) { + if (bus->parent) { u8 control; /* enable on PPB */ (void) pci_read_config_byte(bus->self, PCI_BRIDGE_CONTROL, &control); -- cgit v1.2.3 From 8b6649c575e0d8312f62fe643ae43558892da2e1 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Mon, 16 Feb 2009 03:20:54 -0500 Subject: parisc: convert cpu_check_affinity to new cpumask api cpumask arg to the affinity function is now const, sort that out through the irq_desc implementations. Signed-off-by: Kyle McMartin --- drivers/parisc/iosapic.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 1cdfdea5d7e..501aaf1f253 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c @@ -708,11 +708,14 @@ static void iosapic_set_affinity_irq(unsigned int irq, struct vector_info *vi = iosapic_get_vector(irq); u32 d0, d1, dummy_d0; unsigned long flags; + int dest_cpu; - if (cpu_check_affinity(irq, dest)) + dest_cpu = cpu_check_affinity(irq, dest); + if (dest_cpu < 0) return; - vi->txn_addr = txn_affinity_addr(irq, cpumask_first(dest)); + irq_desc[irq].affinity = cpumask_of_cpu(dest_cpu); + vi->txn_addr = txn_affinity_addr(irq, dest_cpu); spin_lock_irqsave(&iosapic_lock, flags); /* d1 contains the destination CPU, so only want to set that -- cgit v1.2.3 From d4995244bd4c02eb7bea3c63aee81a2f2b64910e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 26 Jan 2009 03:53:16 +0000 Subject: parisc: dino: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers Signed-off-by: Kyle McMartin --- drivers/parisc/dino.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c index f79266cd00e..bb5a1c9597c 100644 --- a/drivers/parisc/dino.c +++ b/drivers/parisc/dino.c @@ -479,7 +479,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) res = &dino_dev->hba.lmmio_space; res->flags = IORESOURCE_MEM; size = scnprintf(name, sizeof(name), "Dino LMMIO (%s)", - bus->bridge->bus_id); + dev_name(bus->bridge)); res->name = kmalloc(size+1, GFP_KERNEL); if(res->name) strcpy((char *)res->name, name); @@ -493,7 +493,7 @@ dino_card_setup(struct pci_bus *bus, void __iomem *base_addr) struct list_head *ln, *tmp_ln; printk(KERN_ERR "Dino: cannot attach bus %s\n", - bus->bridge->bus_id); + dev_name(bus->bridge)); /* kill the bus, we can't do anything with it */ list_for_each_safe(ln, tmp_ln, &bus->devices) { struct pci_dev *dev = pci_dev_b(ln); @@ -611,12 +611,12 @@ dino_fixup_bus(struct pci_bus *bus) } DBG("DEBUG %s assigning %d [0x%lx,0x%lx]\n", - bus->self->dev.bus_id, i, + dev_name(&bus->self->dev), i, bus->self->resource[i].start, bus->self->resource[i].end); pci_assign_resource(bus->self, i); DBG("DEBUG %s after assign %d [0x%lx,0x%lx]\n", - bus->self->dev.bus_id, i, + dev_name(&bus->self->dev), i, bus->self->resource[i].start, bus->self->resource[i].end); } @@ -1026,7 +1026,8 @@ static int __init dino_probe(struct parisc_device *dev) dino_current_bus = bus->subordinate + 1; pci_bus_assign_resources(bus); } else { - printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", dev->dev.bus_id, dino_current_bus); + printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", + dev_name(&dev->dev), dino_current_bus); /* increment the bus number in case of duplicates */ dino_current_bus++; } -- cgit v1.2.3 From d284e4f71dd42826fb60df33846ba310310c6c51 Mon Sep 17 00:00:00 2001 From: Sigmund Augdal Date: Mon, 26 Jan 2009 19:08:48 -0300 Subject: V4L/DVB (10974): Use Diseqc 3/3 mode to send data Signed-off-by: Sigmund Augdal Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb0899_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/stb0899_drv.c b/drivers/media/dvb/frontends/stb0899_drv.c index 10613acf18f..a04c782fff8 100644 --- a/drivers/media/dvb/frontends/stb0899_drv.c +++ b/drivers/media/dvb/frontends/stb0899_drv.c @@ -794,7 +794,7 @@ static int stb0899_send_diseqc_burst(struct dvb_frontend *fe, fe_sec_mini_cmd_t reg = stb0899_read_reg(state, STB0899_DISCNTRL1); old_state = reg; /* set to burst mode */ - STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x02); + STB0899_SETFIELD_VAL(DISEQCMODE, reg, 0x03); STB0899_SETFIELD_VAL(DISPRECHARGE, reg, 0x01); stb0899_write_reg(state, STB0899_DISCNTRL1, reg); switch (burst) { -- cgit v1.2.3 From b5d067b8e331ce78f4a81eb220965ffa36069d3f Mon Sep 17 00:00:00 2001 From: Manu Abraham Date: Tue, 27 Jan 2009 11:03:16 -0300 Subject: V4L/DVB (10975): Bug: Use signed types, Offsets and range can be negative Code simplification: use in kernel macros Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb0899_algo.c | 14 +++++++------- drivers/media/dvb/frontends/stb0899_priv.h | 12 ++++-------- 2 files changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/stb0899_algo.c b/drivers/media/dvb/frontends/stb0899_algo.c index a67d1775a43..2da55ec2039 100644 --- a/drivers/media/dvb/frontends/stb0899_algo.c +++ b/drivers/media/dvb/frontends/stb0899_algo.c @@ -156,7 +156,7 @@ static void stb0899_first_subrange(struct stb0899_state *state) } if (range > 0) - internal->sub_range = MIN(internal->srch_range, range); + internal->sub_range = min(internal->srch_range, range); else internal->sub_range = 0; @@ -185,7 +185,7 @@ static enum stb0899_status stb0899_check_tmg(struct stb0899_state *state) timing = stb0899_read_reg(state, STB0899_RTF); if (lock >= 42) { - if ((lock > 48) && (ABS(timing) >= 110)) { + if ((lock > 48) && (abs(timing) >= 110)) { internal->status = ANALOGCARRIER; dprintk(state->verbose, FE_DEBUG, 1, "-->ANALOG Carrier !"); } else { @@ -222,7 +222,7 @@ static enum stb0899_status stb0899_search_tmg(struct stb0899_state *state) index++; derot_freq += index * internal->direction * derot_step; /* next derot zig zag position */ - if (ABS(derot_freq) > derot_limit) + if (abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -298,7 +298,7 @@ static enum stb0899_status stb0899_search_carrier(struct stb0899_state *state) last_derot_freq = derot_freq; derot_freq += index * internal->direction * internal->derot_step; /* next zig zag derotator position */ - if(ABS(derot_freq) > derot_limit) + if(abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -400,7 +400,7 @@ static enum stb0899_status stb0899_search_data(struct stb0899_state *state) if ((internal->status != CARRIEROK) || (stb0899_check_data(state) != DATAOK)) { derot_freq += index * internal->direction * derot_step; /* next zig zag derotator position */ - if (ABS(derot_freq) > derot_limit) + if (abs(derot_freq) > derot_limit) next_loop--; if (next_loop) { @@ -467,7 +467,7 @@ static void next_sub_range(struct stb0899_state *state) if (internal->sub_dir > 0) { old_sub_range = internal->sub_range; - internal->sub_range = MIN((internal->srch_range / 2) - + internal->sub_range = min((internal->srch_range / 2) - (internal->tuner_offst + internal->sub_range / 2), internal->sub_range); @@ -771,7 +771,7 @@ static long Log2Int(int number) int i; i = 0; - while ((1 << i) <= ABS(number)) + while ((1 << i) <= abs(number)) i++; if (number == 0) diff --git a/drivers/media/dvb/frontends/stb0899_priv.h b/drivers/media/dvb/frontends/stb0899_priv.h index 24619e3689d..82395b91281 100644 --- a/drivers/media/dvb/frontends/stb0899_priv.h +++ b/drivers/media/dvb/frontends/stb0899_priv.h @@ -59,10 +59,6 @@ #define MAKEWORD32(a, b, c, d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d)) #define MAKEWORD16(a, b) (((a) << 8) | (b)) -#define MIN(x, y) ((x) <= (y) ? (x) : (y)) -#define MAX(x, y) ((x) >= (y) ? (x) : (y)) -#define ABS(x) ((x) >= 0 ? (x) : -(x)) - #define LSB(x) ((x & 0xff)) #define MSB(y) ((y >> 8) & 0xff) @@ -168,10 +164,10 @@ struct stb0899_internal { u32 freq; /* Demod internal Frequency */ u32 srate; /* Demod internal Symbol rate */ enum stb0899_fec fecrate; /* Demod internal FEC rate */ - u32 srch_range; /* Demod internal Search Range */ - u32 sub_range; /* Demod current sub range (Hz) */ - u32 tuner_step; /* Tuner step (Hz) */ - u32 tuner_offst; /* Relative offset to carrier (Hz) */ + s32 srch_range; /* Demod internal Search Range */ + s32 sub_range; /* Demod current sub range (Hz) */ + s32 tuner_step; /* Tuner step (Hz) */ + s32 tuner_offst; /* Relative offset to carrier (Hz) */ u32 tuner_bw; /* Current bandwidth of the tuner (Hz) */ s32 mclk; /* Masterclock Divider factor (binary) */ -- cgit v1.2.3 From 1d06059c13fc64b67027334507f734ec0f2f4b6c Mon Sep 17 00:00:00 2001 From: "Igor M. Liplianin" Date: Sun, 9 Nov 2008 11:35:13 -0300 Subject: V4L/DVB (10976): Bug fix: For legacy applications stv0899 performs search only first time after insmod. For legacy applications stv0899 performs search only first time after insmod due to not set DVBFE_ALGO_SEARCH_AGAIN bit Signed-off-by: Igor M. Liplianin Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/dvb-core/dvb_frontend.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/dvb-core/dvb_frontend.c b/drivers/media/dvb/dvb-core/dvb_frontend.c index 84340778508..8dcb3fbf7ac 100644 --- a/drivers/media/dvb/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb/dvb-core/dvb_frontend.c @@ -1290,9 +1290,6 @@ static int dtv_property_process_set(struct dvb_frontend *fe, dprintk("%s() Finalised property cache\n", __func__); dtv_property_cache_submit(fe); - /* Request the search algorithm to search */ - fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; - r |= dvb_frontend_ioctl_legacy(inode, file, FE_SET_FRONTEND, &fepriv->parameters); break; @@ -1717,6 +1714,10 @@ static int dvb_frontend_ioctl_legacy(struct inode *inode, struct file *file, fepriv->min_delay = (dvb_override_tune_delay * HZ) / 1000; fepriv->state = FESTATE_RETUNE; + + /* Request the search algorithm to search */ + fepriv->algo_status |= DVBFE_ALGO_SEARCH_AGAIN; + dvb_frontend_wakeup(fe); dvb_frontend_add_event(fe, 0); fepriv->status = 0; -- cgit v1.2.3 From 26f26fa8e3a0822aa43ee0a80bd0196fa2554c42 Mon Sep 17 00:00:00 2001 From: Hans Werner Date: Tue, 27 Jan 2009 16:09:12 -0300 Subject: V4L/DVB (10977): STB6100 init fix, the call to stb6100_set_bandwidth needs an argument in Hz not kHz, and a comment incorrectly says MHz instead of Hz. I don't know if this caused real problems anywhere Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/frontends/stb6100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/dvb/frontends/stb6100.c b/drivers/media/dvb/frontends/stb6100.c index ff39275ab49..1ed5a7db4c5 100644 --- a/drivers/media/dvb/frontends/stb6100.c +++ b/drivers/media/dvb/frontends/stb6100.c @@ -427,11 +427,11 @@ static int stb6100_init(struct dvb_frontend *fe) status->refclock = 27000000; /* Hz */ status->iqsense = 1; status->bandwidth = 36000; /* kHz */ - state->bandwidth = status->bandwidth * 1000; /* MHz */ + state->bandwidth = status->bandwidth * 1000; /* Hz */ state->reference = status->refclock / 1000; /* kHz */ /* Set default bandwidth. */ - return stb6100_set_bandwidth(fe, status->bandwidth); + return stb6100_set_bandwidth(fe, state->bandwidth); } static int stb6100_get_state(struct dvb_frontend *fe, -- cgit v1.2.3 From a00d0bb86b20a86a72f4df9d6e31dda94c02b4fa Mon Sep 17 00:00:00 2001 From: Matthias Schwarzzot Date: Tue, 27 Jan 2009 16:29:44 -0300 Subject: V4L/DVB (10978): Report tuning algorith correctly Signed-off-by: Manu Abraham Signed-off-by: Mauro Carvalho Chehab --- drivers/media/dvb/bt8xx/dst.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/media/dvb/bt8xx/dst.c b/drivers/media/dvb/bt8xx/dst.c index 29e8f1546ab..fec1d77fa85 100644 --- a/drivers/media/dvb/bt8xx/dst.c +++ b/drivers/media/dvb/bt8xx/dst.c @@ -1683,7 +1683,7 @@ static int dst_tune_frontend(struct dvb_frontend* fe, static int dst_get_tuning_algo(struct dvb_frontend *fe) { - return dst_algo; + return dst_algo ? DVBFE_ALGO_HW : DVBFE_ALGO_SW; } static int dst_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *p) -- cgit v1.2.3 From 9d51af7bd2f1d730cb6eeeb9ff837e3441ad4e07 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Tue, 10 Mar 2009 16:28:51 -0400 Subject: sata_mv: fix MSI irq race condition Fix a (rare) race condition in mv_interrupt() when using MSI. The value of hpriv->main_irq_mask_addr can change on on the fly, and without this patch we could end up writing back a stale copy to the hardware. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 7007edd2d45..74b1080d116 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -2218,12 +2218,13 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) else handled = mv_host_intr(host, pending_irqs); } - spin_unlock(&host->lock); /* for MSI: unmask; interrupt cause bits will retrigger now */ if (using_msi) writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr); + spin_unlock(&host->lock); + return IRQ_RETVAL(handled); } -- cgit v1.2.3 From e3e4385f6181f434c0d786998ad1d0eef4e21c9b Mon Sep 17 00:00:00 2001 From: Stuart MENEFY Date: Tue, 10 Mar 2009 11:38:13 +0000 Subject: libata: Keep shadow last_ctl up to date during resets libata keeps a shadow copy of the ATA CTL register (which is write only), and only writes to the hardware when the required value doesn't match the shadow. However this copy wasn't being maintained when performing reset functions. This could cause problems for the first operation after a reset when the correct value might not be written to the CTL register. This problem was observed when hotplugging a drive: the identify command was being issued with interrupts enabled, when they should have been disabled. Signed-off-by: Stuart Menefy Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 714cb046b59..f93dc029dfd 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -2066,6 +2066,7 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask, iowrite8(ap->ctl | ATA_SRST, ioaddr->ctl_addr); udelay(20); /* FIXME: flush */ iowrite8(ap->ctl, ioaddr->ctl_addr); + ap->last_ctl = ap->ctl; /* wait the port to become ready */ return ata_sff_wait_after_reset(&ap->link, devmask, deadline); @@ -2190,8 +2191,10 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes) } /* set up device control */ - if (ap->ioaddr.ctl_addr) + if (ap->ioaddr.ctl_addr) { iowrite8(ap->ctl, ap->ioaddr.ctl_addr); + ap->last_ctl = ap->ctl; + } } EXPORT_SYMBOL_GPL(ata_sff_postreset); @@ -2534,6 +2537,7 @@ void ata_bus_reset(struct ata_port *ap) if (ap->flags & (ATA_FLAG_SATA_RESET | ATA_FLAG_SRST)) { /* set up device control for ATA_FLAG_SATA_RESET */ iowrite8(ap->ctl, ioaddr->ctl_addr); + ap->last_ctl = ap->ctl; } DPRINTK("EXIT\n"); -- cgit v1.2.3 From e9c1670c2a14ef9cc20d86b24b829f3947aad34e Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Tue, 3 Mar 2009 13:52:16 +0900 Subject: ata_piix: add workaround for Samsung DB-P70 Samsung DB-P70 somehow botched the first ICH9 SATA port. The board doesn't expose the first port but somehow SStatus reports link online while failing SRST protocol leading to repeated probe failures and thus long boot delay. Because the BIOS doesn't carry any identifying DMI information, the port can't be blacklisted safely. Fortunately, the controller does have subsystem vendor and ID set. It's unclear whether the subsystem IDs are used only for the board but it can be safely worked around by disabling SIDPR access and just using SRST works around the problem. Even when the workaround is triggered on an unaffected board the only side effect will be missing SCR access. Signed-off-by: Tejun Heo Reported-by: Joseph Jang Reported-by: Jonghyon Sohn Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index 54961c0b2c7..ef8b30d577b 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -1289,6 +1289,39 @@ static const int *__devinit piix_init_sata_map(struct pci_dev *pdev, return map; } +static bool piix_no_sidpr(struct ata_host *host) +{ + struct pci_dev *pdev = to_pci_dev(host->dev); + + /* + * Samsung DB-P70 only has three ATA ports exposed and + * curiously the unconnected first port reports link online + * while not responding to SRST protocol causing excessive + * detection delay. + * + * Unfortunately, the system doesn't carry enough DMI + * information to identify the machine but does have subsystem + * vendor and device set. As it's unclear whether the + * subsystem vendor/device is used only for this specific + * board, the port can't be disabled solely with the + * information; however, turning off SIDPR access works around + * the problem. Turn it off. + * + * This problem is reported in bnc#441240. + * + * https://bugzilla.novell.com/show_bug.cgi?id=441420 + */ + if (pdev->vendor == PCI_VENDOR_ID_INTEL && pdev->device == 0x2920 && + pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG && + pdev->subsystem_device == 0xb049) { + dev_printk(KERN_WARNING, host->dev, + "Samsung DB-P70 detected, disabling SIDPR\n"); + return true; + } + + return false; +} + static int __devinit piix_init_sidpr(struct ata_host *host) { struct pci_dev *pdev = to_pci_dev(host->dev); @@ -1302,6 +1335,10 @@ static int __devinit piix_init_sidpr(struct ata_host *host) if (hpriv->map[i] == IDE) return 0; + /* is it blacklisted? */ + if (piix_no_sidpr(host)) + return 0; + if (!(host->ports[0]->flags & PIIX_FLAG_SIDPR)) return 0; -- cgit v1.2.3 From 3eb76c1ccde496c3c0bfda23d1c803e40b762ce6 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Fri, 13 Mar 2009 21:16:12 +0100 Subject: ide-floppy: do not map dataless cmds to an sg since it fails the virt_to_page() translation check with DEBUG_VIRTUAL enabled. Signed-off-by: Borislav Petkov [bart: backport to Linus' tree] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 12 ++++++++++++ drivers/ide/ide-floppy.c | 6 ++++-- 2 files changed, 16 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index e96c0126059..e9d042dba0e 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -140,6 +140,12 @@ static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, rq->cmd_flags |= REQ_PREEMPT; rq->buffer = (char *)pc; rq->rq_disk = disk; + + if (pc->req_xfer) { + rq->data = pc->buf; + rq->data_len = pc->req_xfer; + } + memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; @@ -159,6 +165,12 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, rq = blk_get_request(drive->queue, READ, __GFP_WAIT); rq->cmd_type = REQ_TYPE_SPECIAL; rq->buffer = (char *)pc; + + if (pc->req_xfer) { + rq->data = pc->buf; + rq->data_len = pc->req_xfer; + } + memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 3eab1c6c9b3..317ec62c33d 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -327,8 +327,10 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, return ide_stopped; } - ide_init_sg_cmd(drive, rq); - ide_map_sg(drive, rq); + if (blk_fs_request(rq) || pc->req_xfer) { + ide_init_sg_cmd(drive, rq); + ide_map_sg(drive, rq); + } pc->sg = hwif->sg_table; pc->sg_cnt = hwif->sg_nents; -- cgit v1.2.3 From 5d82720a7f41f0c877e026c7d17e3bf20ccdbae0 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Fri, 13 Mar 2009 21:16:13 +0100 Subject: ide: save the returned value of dma_map_sg dma_map_sg could return a value different to 'nents' argument of dma_map_sg so the ide stack needs to save it for the later usage (e.g. for_each_sg). The ide stack also needs to save the original sg_nents value for pci_unmap_sg. Signed-off-by: FUJITA Tomonori [bart: backport to Linus' tree] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-dma.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 72ebab0bc75..059c90bb5ad 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -128,6 +128,7 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) { ide_hwif_t *hwif = drive->hwif; struct scatterlist *sg = hwif->sg_table; + int i; ide_map_sg(drive, rq); @@ -136,8 +137,13 @@ int ide_build_sglist(ide_drive_t *drive, struct request *rq) else hwif->sg_dma_direction = DMA_TO_DEVICE; - return dma_map_sg(hwif->dev, sg, hwif->sg_nents, - hwif->sg_dma_direction); + i = dma_map_sg(hwif->dev, sg, hwif->sg_nents, hwif->sg_dma_direction); + if (i) { + hwif->orig_sg_nents = hwif->sg_nents; + hwif->sg_nents = i; + } + + return i; } EXPORT_SYMBOL_GPL(ide_build_sglist); @@ -156,7 +162,7 @@ void ide_destroy_dmatable(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; - dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->sg_nents, + dma_unmap_sg(hwif->dev, hwif->sg_table, hwif->orig_sg_nents, hwif->sg_dma_direction); } EXPORT_SYMBOL_GPL(ide_destroy_dmatable); -- cgit v1.2.3 From 1c339eb183bb48095feaa46057ac4f4f0603dbf9 Mon Sep 17 00:00:00 2001 From: Scott James Remnant Date: Fri, 13 Mar 2009 14:30:08 -0700 Subject: sbus: Auto-load openprom module when device opened. The openprom module is missing the char-major-10-139 alias that would cause it to be auto-loaded when a device of that type is opened. This patch adds the alias. Signed-off-by: Scott James Remnant Signed-off-by: Tim Gardner Signed-off-by: David S. Miller --- drivers/sbus/char/openprom.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/sbus/char/openprom.c b/drivers/sbus/char/openprom.c index 29dc735e1a2..124f660a038 100644 --- a/drivers/sbus/char/openprom.c +++ b/drivers/sbus/char/openprom.c @@ -51,6 +51,7 @@ MODULE_AUTHOR("Thomas K. Dyas (tdyas@noc.rutgers.edu) and Eddie C. Dost (ecd@sk MODULE_DESCRIPTION("OPENPROM Configuration Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION("1.0"); +MODULE_ALIAS_MISCDEV(SUN_OPENPROM_MINOR); /* Private data kept by the driver for each descriptor. */ typedef struct openprom_private_data -- cgit v1.2.3 From bfbd442f69ec9c58590ffc6e93ac8d6809caa48b Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 9 Mar 2009 13:42:24 +0100 Subject: Fix Xilinx SystemACE driver to handle empty CF slot The SystemACE driver does not handle an empty CF slot gracefully. An empty CF slot ends up hanging the system. This patch adds a check for the CF state and stops trying to process requests if the slot is empty. Signed-off-by: Grant Likely Signed-off-by: Jens Axboe --- drivers/block/xsysace.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 381d686fc1a..119be3442f2 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c @@ -489,6 +489,28 @@ static void ace_fsm_dostate(struct ace_device *ace) ace->fsm_state, ace->id_req_count); #endif + /* Verify that there is actually a CF in the slot. If not, then + * bail out back to the idle state and wake up all the waiters */ + status = ace_in32(ace, ACE_STATUS); + if ((status & ACE_STATUS_CFDETECT) == 0) { + ace->fsm_state = ACE_FSM_STATE_IDLE; + ace->media_change = 1; + set_capacity(ace->gd, 0); + dev_info(ace->dev, "No CF in slot\n"); + + /* Drop all pending requests */ + while ((req = elv_next_request(ace->queue)) != NULL) + end_request(req, 0); + + /* Drop back to IDLE state and notify waiters */ + ace->fsm_state = ACE_FSM_STATE_IDLE; + ace->id_result = -EIO; + while (ace->id_req_count) { + complete(&ace->id_completion); + ace->id_req_count--; + } + } + switch (ace->fsm_state) { case ACE_FSM_STATE_IDLE: /* See if there is anything to do */ -- cgit v1.2.3 From 5bee17f18b595937e6beafeee5197868a3f74a06 Mon Sep 17 00:00:00 2001 From: Kyle McMartin Date: Sat, 14 Mar 2009 19:40:59 -0400 Subject: parisc: sba_iommu: fix build bug when CONFIG_PARISC_AGP=y CC drivers/parisc/sba_iommu.o drivers/parisc/sba_iommu.c:1373: error: expected identifier or '(' before '}' token make[2]: *** [drivers/parisc/sba_iommu.o] Error 1 make[1]: *** [drivers/parisc] Error 2 make: *** [drivers] Error 2 Don't know how this has gone missed for so long... clearly I need to do builds on my C8000 more often. Signed-off-by: Kyle McMartin Signed-off-by: Linus Torvalds --- drivers/parisc/sba_iommu.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/parisc/sba_iommu.c b/drivers/parisc/sba_iommu.c index 6aad8546fd2..e5999c4cedc 100644 --- a/drivers/parisc/sba_iommu.c +++ b/drivers/parisc/sba_iommu.c @@ -1367,9 +1367,7 @@ sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num) ioc->pdir_size /= 2; ioc->pdir_base[PDIR_INDEX(iova_space_size/2)] = SBA_AGPGART_COOKIE; } -} #endif /*SBA_AGP_SUPPORT*/ - } static void -- cgit v1.2.3 From a140449584522c3eea1bb381f746d40939e6f62a Mon Sep 17 00:00:00 2001 From: Andy Whitcroft Date: Wed, 11 Feb 2009 18:11:22 +0000 Subject: suspend: switch the Asus Pundit P1-AH2 to old ACPI sleep ordering Switch the Asus Pundit P1-AH2 (M2N8L motherboard) to the old ACPI 1.0 sleep ordering by default. Without this it will not suspend/resume correctly. Signed-off-by: Andy Whitcroft Tested-by: Dustin Kirkland Signed-off-by: Len Brown --- drivers/acpi/sleep.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 519266654f0..3ca98686f28 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -378,6 +378,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "Macmini1,1"), }, }, + { + .callback = init_old_suspend_ordering, + .ident = "Asus Pundit P1-AH2 (M2N8L motherboard)", + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), + DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- cgit v1.2.3 From 7b46ecd5fcebf381a7bde966db352d8fb1b8e944 Mon Sep 17 00:00:00 2001 From: Len Brown Date: Wed, 25 Feb 2009 18:00:18 -0500 Subject: Revert "ACPI: make some IO ports off-limits to AML" This reverts commit 5ec5d38a1c8af255ffc481c81eef13e9155524b3. because it caused spurious dmesg warmings. We'll implement the check for off-limit ports in a more clever way in the future. http://bugzilla.kernel.org/show_bug.cgi?id=12758 Signed-off-by: Len Brown --- drivers/acpi/osl.c | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index b3193ec0a2e..1e35f342957 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -1317,54 +1317,6 @@ acpi_os_validate_interface (char *interface) return AE_SUPPORT; } -#ifdef CONFIG_X86 - -struct aml_port_desc { - uint start; - uint end; - char* name; - char warned; -}; - -static struct aml_port_desc aml_invalid_port_list[] = { - {0x20, 0x21, "PIC0", 0}, - {0xA0, 0xA1, "PIC1", 0}, - {0x4D0, 0x4D1, "ELCR", 0} -}; - -/* - * valid_aml_io_address() - * - * if valid, return true - * else invalid, warn once, return false - */ -static bool valid_aml_io_address(uint address, uint length) -{ - int i; - int entries = sizeof(aml_invalid_port_list) / sizeof(struct aml_port_desc); - - for (i = 0; i < entries; ++i) { - if ((address >= aml_invalid_port_list[i].start && - address <= aml_invalid_port_list[i].end) || - (address + length >= aml_invalid_port_list[i].start && - address + length <= aml_invalid_port_list[i].end)) - { - if (!aml_invalid_port_list[i].warned) - { - printk(KERN_ERR "ACPI: Denied BIOS AML access" - " to invalid port 0x%x+0x%x (%s)\n", - address, length, - aml_invalid_port_list[i].name); - aml_invalid_port_list[i].warned = 1; - } - return false; /* invalid */ - } - } - return true; /* valid */ -} -#else -static inline bool valid_aml_io_address(uint address, uint length) { return true; } -#endif /****************************************************************************** * * FUNCTION: acpi_os_validate_address @@ -1394,8 +1346,6 @@ acpi_os_validate_address ( switch (space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: - if (!valid_aml_io_address(address, length)) - return AE_AML_ILLEGAL_ADDRESS; case ACPI_ADR_SPACE_SYSTEM_MEMORY: /* Only interference checks against SystemIO and SytemMemory are needed */ -- cgit v1.2.3 From 45e7798886af101c4a908a896bbba5a84ee5cc32 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Sun, 15 Mar 2009 22:13:44 -0400 Subject: ACPI suspend: Blacklist Toshiba Satellite L300 that requires to set SCI_EN directly on resume This is a supplement of commit 65df78473ffbf3bff5e2034df1638acc4f3ddd50. http://bugzilla.kernel.org/show_bug.cgi?id=12798 Signed-off-by: Zhang Rui Signed-off-by: Len Brown --- drivers/acpi/sleep.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 3ca98686f28..00456fccfa3 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -386,6 +386,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { DMI_MATCH(DMI_BOARD_NAME, "M2N8L"), }, }, + { + .callback = init_set_sci_en_on_resume, + .ident = "Toshiba Satellite L300", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"), + DMI_MATCH(DMI_PRODUCT_NAME, "Satellite L300"), + }, + }, {}, }; #endif /* CONFIG_SUSPEND */ -- cgit v1.2.3 From 176f9c1804df09f3e9b998c0642e212592ac6283 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 4 Mar 2009 11:55:27 -0800 Subject: ACPI: remove doubled status checking There was a misplaced status test (two consequent tests without a statement in between) in acpi_bus_init for ages. Remove it, since the function which should be checked (acpi_os_initialize1) has BUG_ONs on failure paths. Signed-off-by: Jiri Slaby Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/bus.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 765fd1c56cd..bee64b73c91 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c @@ -758,8 +758,7 @@ static int __init acpi_bus_init(void) acpi_status status = AE_OK; extern acpi_status acpi_os_initialize1(void); - - status = acpi_os_initialize1(); + acpi_os_initialize1(); status = acpi_enable_subsystem(ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE); @@ -769,12 +768,6 @@ static int __init acpi_bus_init(void) goto error1; } - if (ACPI_FAILURE(status)) { - printk(KERN_ERR PREFIX - "Unable to initialize ACPI OS objects\n"); - goto error1; - } - /* * ACPI 2.0 requires the EC driver to be loaded and work before * the EC device is found in the namespace (i.e. before acpi_initialize_objects() -- cgit v1.2.3 From 27ce34198345886854643b9572f9a06d2e7500d2 Mon Sep 17 00:00:00 2001 From: Cyrill Gorcunov Date: Wed, 4 Mar 2009 11:55:29 -0800 Subject: acpi: check for pxm_to_node_map overflow It is hardly (if ever) possible but in case of broken _PXM entry we could reach out of pxm_to_node_map array bounds in acpi_map_pxm_to_node() call. Signed-off-by: Cyrill Gorcunov Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/acpi/numa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c index c5e292aab0e..3a0d8ef25c7 100644 --- a/drivers/acpi/numa.c +++ b/drivers/acpi/numa.c @@ -277,7 +277,7 @@ int acpi_get_node(acpi_handle *handle) int pxm, node = -1; pxm = acpi_get_pxm(handle); - if (pxm >= 0) + if (pxm >= 0 && pxm < MAX_PXM_DOMAINS) node = acpi_map_pxm_to_node(pxm); return node; -- cgit v1.2.3 From 6050c8dd70b21a9d927983aeb6357fecffa7fb23 Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 15 Feb 2009 19:30:19 +0100 Subject: asus-laptop: restore acpi_generate_proc_event() Restore acpi_generate_proc_event() for backward compatibility with old acpi scripts. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/asus-laptop.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index 56af6cf385b..eeafc6c0160 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c @@ -815,6 +815,7 @@ static int asus_setkeycode(struct input_dev *dev, int scancode, int keycode) static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; + u16 count; /* TODO Find a better way to handle events count. */ if (!hotk) @@ -832,9 +833,11 @@ static void asus_hotk_notify(acpi_handle handle, u32 event, void *data) lcd_blank(FB_BLANK_POWERDOWN); } + count = hotk->event_count[event % 128]++; + acpi_bus_generate_proc_event(hotk->device, event, count); acpi_bus_generate_netlink_event(hotk->device->pnp.device_class, dev_name(&hotk->device->dev), event, - hotk->event_count[event % 128]++); + count); if (hotk->inputdev) { key = asus_get_entry_by_scancode(event); -- cgit v1.2.3 From 7950b71c3bd7b27b2874088a6c4efe3e13579f8b Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 15 Feb 2009 19:30:20 +0100 Subject: eeepc-laptop: restore acpi_generate_proc_event() Restore acpi_generate_proc_event() for backward compatibility with old acpi scripts. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/eeepc-laptop.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/eeepc-laptop.c b/drivers/platform/x86/eeepc-laptop.c index 786ed8661cb..6f54fd1757c 100644 --- a/drivers/platform/x86/eeepc-laptop.c +++ b/drivers/platform/x86/eeepc-laptop.c @@ -557,13 +557,17 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) static void eeepc_hotk_notify(acpi_handle handle, u32 event, void *data) { static struct key_entry *key; + u16 count; + if (!ehotk) return; if (event >= NOTIFY_BRN_MIN && event <= NOTIFY_BRN_MAX) notify_brn(); + count = ehotk->event_count[event % 128]++; + acpi_bus_generate_proc_event(ehotk->device, event, count); acpi_bus_generate_netlink_event(ehotk->device->pnp.device_class, dev_name(&ehotk->device->dev), event, - ehotk->event_count[event % 128]++); + count); if (ehotk->inputdev) { key = eepc_get_entry_by_scancode(event); if (key) { -- cgit v1.2.3 From e73e2c62f7646d54e30ef8863ac0be0b8e4ef0eb Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Sun, 15 Feb 2009 19:30:21 +0100 Subject: asus-laptop: use select instead of depends on Like thinkpad_acpi or eeepc-laptop, asus-laptop will now use "select" instead of "depends on" for LEDS_CLASS, NEW_LEDS and BACKLIGHT_CLASS_DEVICE Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index b3866ad5022..fede8f327bb 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -39,9 +39,9 @@ config ASUS_LAPTOP tristate "Asus Laptop Extras (EXPERIMENTAL)" depends on ACPI depends on EXPERIMENTAL && !ACPI_ASUS - depends on LEDS_CLASS - depends on NEW_LEDS - depends on BACKLIGHT_CLASS_DEVICE + select LEDS_CLASS + select NEW_LEDS + select BACKLIGHT_CLASS_DEVICE depends on INPUT ---help--- This is the new Linux driver for Asus laptops. It may also support some -- cgit v1.2.3 From d263da311ab403e3a84fa24920edc826147a550c Mon Sep 17 00:00:00 2001 From: Corentin Chary Date: Wed, 25 Feb 2009 09:37:09 +0100 Subject: platform/x86: depends instead of select for laptop platform drivers "I hate `select' and will gleefully leap on any s/select/depends/ patch, whether it works or not :)" Andrew Morton select INPUT is not needed here, because if someone doesn't want INPUT, he won't want these drivers either. Signed-off-by: Corentin Chary Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index fede8f327bb..f3ab40188e6 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -185,11 +185,11 @@ config SONYPI_COMPAT config THINKPAD_ACPI tristate "ThinkPad ACPI Laptop Extras" depends on ACPI + depends on INPUT select BACKLIGHT_LCD_SUPPORT select BACKLIGHT_CLASS_DEVICE select HWMON select NVRAM - select INPUT select NEW_LEDS select LEDS_CLASS select NET -- cgit v1.2.3 From 013d67fd4f0da8f6af60a376f1a254266ab658ef Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Sat, 14 Feb 2009 09:53:48 +0000 Subject: acer-wmi: double free in acer_rfkill_exit() This is acer_rfkill_exit() from drivers/platform/x86/acer-wmi.c. The code frees wireless_rfkill->data again instead of bluetooth_rfkill->data. This was found using a code checker (http://repo.or.cz/w/smatch.git/). Signed-off-by: Dan Carpenter Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/acer-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 6bcca616a70..a6a42e8c060 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c @@ -1026,7 +1026,7 @@ static void acer_rfkill_exit(void) kfree(wireless_rfkill->data); rfkill_unregister(wireless_rfkill); if (has_cap(ACER_CAP_BLUETOOTH)) { - kfree(wireless_rfkill->data); + kfree(bluetooth_rfkill->data); rfkill_unregister(bluetooth_rfkill); } return; -- cgit v1.2.3 From 5fcdd177d063f1d8d569d746ab1bf206b0dfb2e8 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sat, 14 Feb 2009 09:53:53 +0000 Subject: acpi-wmi: Unmark as 'experimental' ACPI-WMI isn't experimental anymore, and there are other drivers that now depend on it that aren't either. Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index f3ab40188e6..c2319d97f51 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -315,9 +315,8 @@ config EEEPC_LAPTOP config ACPI_WMI - tristate "WMI (EXPERIMENTAL)" + tristate "WMI" depends on ACPI - depends on EXPERIMENTAL help This driver adds support for the ACPI-WMI (Windows Management Instrumentation) mapper device (PNP0C14) found on some systems. -- cgit v1.2.3 From 54b1ec893e869c815d390afa42aacf1499858112 Mon Sep 17 00:00:00 2001 From: Carlos Corbacho Date: Sat, 14 Feb 2009 09:53:59 +0000 Subject: acer-wmi: Unmark as 'experimental' This driver has been around and used long enough that we can drop the 'experimental'. Signed-off-by: Carlos Corbacho Signed-off-by: Len Brown --- drivers/platform/x86/Kconfig | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig index c2319d97f51..3608081bc3e 100644 --- a/drivers/platform/x86/Kconfig +++ b/drivers/platform/x86/Kconfig @@ -15,8 +15,7 @@ menuconfig X86_PLATFORM_DEVICES if X86_PLATFORM_DEVICES config ACER_WMI - tristate "Acer WMI Laptop Extras (EXPERIMENTAL)" - depends on EXPERIMENTAL + tristate "Acer WMI Laptop Extras" depends on ACPI depends on LEDS_CLASS depends on NEW_LEDS -- cgit v1.2.3 From b36a50f92d1c4300a88f606b4d2bbdc4f442a2d7 Mon Sep 17 00:00:00 2001 From: Mathieu Chouquet-Stringer Date: Sat, 14 Mar 2009 16:35:26 +0100 Subject: thinkpad-acpi: fix module autoloading for older models Looking at the source, there seems to be a missing * to match my DMI string. I mean for newer IBM and Lenovo's laptops you match either one of the following: MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); While for older Thinkpads, you do this (for instance): IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); with IBM_BIOS_MODULE_ALIAS being MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") Note there's no * terminating the string. As result, udev doesn't load anything because modprobe cannot find anything matching this (my machine actually): udevtest: run: '/sbin/modprobe dmi:bvnIBM:bvr1IET71WW(2.10):bd06/16/2006:svnIBM:pn236621U:pvrNotAv Signed-off-by: Mathieu Chouquet-Stringer Acked-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- drivers/platform/x86/thinkpad_acpi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index bcbc05107ba..d2433204a40 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c @@ -7532,7 +7532,7 @@ MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); * if it is not there yet. */ #define IBM_BIOS_MODULE_ALIAS(__type) \ - MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW") + MODULE_ALIAS("dmi:bvnIBM:bvr" __type "ET??WW*") /* Non-ancient thinkpads */ MODULE_ALIAS("dmi:bvnIBM:*:svnIBM:*:pvrThinkPad*:rvnIBM:*"); @@ -7541,9 +7541,9 @@ MODULE_ALIAS("dmi:bvnLENOVO:*:svnLENOVO:*:pvrThinkPad*:rvnLENOVO:*"); /* Ancient thinkpad BIOSes have to be identified by * BIOS type or model number, and there are far less * BIOS types than model numbers... */ -IBM_BIOS_MODULE_ALIAS("I[B,D,H,I,M,N,O,T,W,V,Y,Z]"); -IBM_BIOS_MODULE_ALIAS("1[0,3,6,8,A-G,I,K,M-P,S,T]"); -IBM_BIOS_MODULE_ALIAS("K[U,X-Z]"); +IBM_BIOS_MODULE_ALIAS("I[BDHIMNOTWVYZ]"); +IBM_BIOS_MODULE_ALIAS("1[0368A-GIKM-PST]"); +IBM_BIOS_MODULE_ALIAS("K[UX-Z]"); MODULE_AUTHOR("Borislav Deianov, Henrique de Moraes Holschuh"); MODULE_DESCRIPTION(TPACPI_DESC); -- cgit v1.2.3 From da511997d2bbc09f5e39385e0ed209578db07c91 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Wed, 4 Mar 2009 11:55:30 -0800 Subject: acpi-wmi: unsigned cannot be less than 0 include/linux/pci-acpi.h:74: typedef u32 acpi_status; result is unsigned, so an error returned by acpi_bus_register_driver() will not be noticed. Signed-off-by: Roel Kluin Signed-off-by: Andrew Morton Signed-off-by: Len Brown --- drivers/platform/x86/wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 8a8b377712c..2f269e117b8 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -708,7 +708,7 @@ static int __init acpi_wmi_add(struct acpi_device *device) static int __init acpi_wmi_init(void) { - acpi_status result; + int result; INIT_LIST_HEAD(&wmi_blocks.list); -- cgit v1.2.3 From 4c3f450ba4e4c00df91f98664b58f9a98dc049fd Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 12 Mar 2009 08:40:15 +0000 Subject: sh: Add OHCI USB support for SH7786 Signed-off-by: Kuninori Morimoto Signed-off-by: Paul Mundt --- drivers/usb/Kconfig | 1 + drivers/usb/host/ohci-hcd.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 83babb0a1df..c6c816b7ecb 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig @@ -47,6 +47,7 @@ config USB_ARCH_HAS_OHCI default y if CPU_SUBTYPE_SH7720 default y if CPU_SUBTYPE_SH7721 default y if CPU_SUBTYPE_SH7763 + default y if CPU_SUBTYPE_SH7786 # more: default PCI diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5cf5f1eca4f..7658589edb1 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -1049,7 +1049,8 @@ MODULE_LICENSE ("GPL"); #if defined(CONFIG_CPU_SUBTYPE_SH7720) || \ defined(CONFIG_CPU_SUBTYPE_SH7721) || \ - defined(CONFIG_CPU_SUBTYPE_SH7763) + defined(CONFIG_CPU_SUBTYPE_SH7763) || \ + defined(CONFIG_CPU_SUBTYPE_SH7786) #include "ohci-sh.c" #define PLATFORM_DRIVER ohci_hcd_sh_driver #endif -- cgit v1.2.3 From 2feb075a33905c2f6ef6be484c75ba6a35f6d12d Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 13 Mar 2009 15:36:55 +0000 Subject: video: sh_mobile_lcdcfb suspend/resume support This patch adds suspend/resume support to the LCDC driver for SuperH Mobile - sh_mobile_lcdcfb. We simply stop hardware on suspend and start it again on resume. For RGB panels this is trivial, but for SYS panels in deferred io mode this becomes a bit more difficult - we need to wait for a frame end interrupt to make sure the clocks are balanced before stopping the actual hardware. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_lcdcfb.c | 66 +++++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 2c5d069e5f0..b433b8ac76d 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -33,6 +33,8 @@ struct sh_mobile_lcdc_chan { struct fb_info info; dma_addr_t dma_handle; struct fb_deferred_io defio; + unsigned long frame_end; + wait_queue_head_t frame_end_wait; }; struct sh_mobile_lcdc_priv { @@ -226,7 +228,10 @@ static void sh_mobile_lcdc_deferred_io_touch(struct fb_info *info) static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) { struct sh_mobile_lcdc_priv *priv = data; + struct sh_mobile_lcdc_chan *ch; unsigned long tmp; + int is_sub; + int k; /* acknowledge interrupt */ tmp = lcdc_read(priv, _LDINTR); @@ -234,8 +239,24 @@ static irqreturn_t sh_mobile_lcdc_irq(int irq, void *data) tmp |= 0x000000ff ^ LDINTR_FS; /* status in low 8 */ lcdc_write(priv, _LDINTR, tmp); - /* disable clocks */ - sh_mobile_lcdc_clk_off(priv); + /* figure out if this interrupt is for main or sub lcd */ + is_sub = (lcdc_read(priv, _LDSR) & (1 << 10)) ? 1 : 0; + + /* wake up channel and disable clocks*/ + for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { + ch = &priv->ch[k]; + + if (!ch->enabled) + continue; + + if (is_sub == lcdc_chan_is_sublcd(ch)) { + ch->frame_end = 1; + wake_up(&ch->frame_end_wait); + + sh_mobile_lcdc_clk_off(priv); + } + } + return IRQ_HANDLED; } @@ -448,18 +469,27 @@ static void sh_mobile_lcdc_stop(struct sh_mobile_lcdc_priv *priv) struct sh_mobile_lcdc_board_cfg *board_cfg; int k; - /* tell the board code to disable the panel */ + /* clean up deferred io and ask board code to disable panel */ for (k = 0; k < ARRAY_SIZE(priv->ch); k++) { ch = &priv->ch[k]; - board_cfg = &ch->cfg.board_cfg; - if (board_cfg->display_off) - board_cfg->display_off(board_cfg->board_data); - /* cleanup deferred io if enabled */ + /* deferred io mode: + * flush frame, and wait for frame end interrupt + * clean up deferred io and enable clock + */ if (ch->info.fbdefio) { + ch->frame_end = 0; + schedule_delayed_work(&ch->info.deferred_work, 0); + wait_event(ch->frame_end_wait, ch->frame_end); fb_deferred_io_cleanup(&ch->info); ch->info.fbdefio = NULL; + sh_mobile_lcdc_clk_on(priv); } + + board_cfg = &ch->cfg.board_cfg; + if (board_cfg->display_off) + board_cfg->display_off(board_cfg->board_data); + } /* stop the lcdc */ @@ -652,6 +682,26 @@ static int sh_mobile_lcdc_set_bpp(struct fb_var_screeninfo *var, int bpp) return 0; } +static int sh_mobile_lcdc_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + sh_mobile_lcdc_stop(platform_get_drvdata(pdev)); + return 0; +} + +static int sh_mobile_lcdc_resume(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + + return sh_mobile_lcdc_start(platform_get_drvdata(pdev)); +} + +static struct dev_pm_ops sh_mobile_lcdc_dev_pm_ops = { + .suspend = sh_mobile_lcdc_suspend, + .resume = sh_mobile_lcdc_resume, +}; + static int sh_mobile_lcdc_remove(struct platform_device *pdev); static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) @@ -707,6 +757,7 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) dev_err(&pdev->dev, "unsupported interface type\n"); goto err1; } + init_waitqueue_head(&priv->ch[i].frame_end_wait); switch (pdata->ch[i].chan) { case LCDC_CHAN_MAINLCD: @@ -860,6 +911,7 @@ static struct platform_driver sh_mobile_lcdc_driver = { .driver = { .name = "sh_mobile_lcdc_fb", .owner = THIS_MODULE, + .pm = &sh_mobile_lcdc_dev_pm_ops, }, .probe = sh_mobile_lcdc_probe, .remove = sh_mobile_lcdc_remove, -- cgit v1.2.3 From 8032b526d1a3bd91ad633dd3a3b5fdbc47ad54f1 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Mon, 16 Mar 2009 09:05:07 +1030 Subject: linux.conf.au 2009: Tuz Impact: help prevent extinction of species The Tasmanian Devil is a shy iconic Australian creature named for its spine-chilling screech. It is threatened with extinction due to a scientifically interesting but horrific transmissible facial cancer. This one is standing in for Tux for one release using the far less-known Devil Facial Tux Disguise. Save The Tasmanian Devil http://tassiedevil.com.au Signed-off-by: Linux.conf.au Hobart Team Signed-off-by: Rusty Russell Signed-off-by: Linus Torvalds --- drivers/video/logo/logo_linux_clut224.ppm | 4428 ++++++++++++++++++----------- drivers/video/logo/logo_linux_vga16.ppm | 4339 +++++++++++++++++----------- 2 files changed, 5563 insertions(+), 3204 deletions(-) (limited to 'drivers') diff --git a/drivers/video/logo/logo_linux_clut224.ppm b/drivers/video/logo/logo_linux_clut224.ppm index 3c14e43b82f..de93ff3fc1a 100644 --- a/drivers/video/logo/logo_linux_clut224.ppm +++ b/drivers/video/logo/logo_linux_clut224.ppm @@ -1,1604 +1,2828 @@ P3 -# Standard 224-color Linux logo -80 80 +145 113 255 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 6 6 6 10 10 10 10 10 10 - 10 10 10 6 6 6 6 6 6 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 22 22 22 26 26 26 30 30 30 34 34 34 - 30 30 30 30 30 30 26 26 26 18 18 18 - 14 14 14 10 10 10 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 26 26 26 42 42 42 - 54 54 54 66 66 66 78 78 78 78 78 78 - 78 78 78 74 74 74 66 66 66 54 54 54 - 42 42 42 26 26 26 18 18 18 10 10 10 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 22 22 22 42 42 42 66 66 66 86 86 86 - 66 66 66 38 38 38 38 38 38 22 22 22 - 26 26 26 34 34 34 54 54 54 66 66 66 - 86 86 86 70 70 70 46 46 46 26 26 26 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 26 26 26 - 50 50 50 82 82 82 58 58 58 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 54 54 54 86 86 86 66 66 66 - 38 38 38 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 22 22 22 50 50 50 - 78 78 78 34 34 34 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 70 70 70 - 78 78 78 46 46 46 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 42 42 42 82 82 82 - 26 26 26 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 46 46 46 34 34 34 6 6 6 2 2 6 - 42 42 42 78 78 78 42 42 42 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 30 30 30 66 66 66 58 58 58 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 86 86 86 101 101 101 46 46 46 10 10 10 - 2 2 6 58 58 58 70 70 70 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 42 42 42 86 86 86 10 10 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 30 30 30 - 94 94 94 94 94 94 58 58 58 26 26 26 - 2 2 6 6 6 6 78 78 78 54 54 54 - 22 22 22 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 62 62 62 62 62 62 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 26 26 26 - 54 54 54 38 38 38 18 18 18 10 10 10 - 2 2 6 2 2 6 34 34 34 82 82 82 - 38 38 38 14 14 14 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 30 30 30 78 78 78 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 10 10 10 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 50 50 50 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 14 14 14 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 54 54 54 - 66 66 66 26 26 26 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 82 82 82 2 2 6 2 2 6 - 2 2 6 6 6 6 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 6 6 6 - 14 14 14 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 18 18 18 - 82 82 82 34 34 34 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 6 6 6 6 6 6 22 22 22 34 34 34 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 34 34 34 - 10 10 10 50 50 50 22 22 22 2 2 6 - 2 2 6 2 2 6 2 2 6 10 10 10 - 86 86 86 42 42 42 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 2 2 6 - 38 38 38 116 116 116 94 94 94 22 22 22 - 22 22 22 2 2 6 2 2 6 2 2 6 - 14 14 14 86 86 86 138 138 138 162 162 162 -154 154 154 38 38 38 26 26 26 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 46 46 46 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 14 14 14 -134 134 134 198 198 198 195 195 195 116 116 116 - 10 10 10 2 2 6 2 2 6 6 6 6 -101 98 89 187 187 187 210 210 210 218 218 218 -214 214 214 134 134 134 14 14 14 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 86 86 86 50 50 50 18 18 18 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 86 86 86 2 2 6 54 54 54 -218 218 218 195 195 195 226 226 226 246 246 246 - 58 58 58 2 2 6 2 2 6 30 30 30 -210 210 210 253 253 253 174 174 174 123 123 123 -221 221 221 234 234 234 74 74 74 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 46 46 46 82 82 82 2 2 6 106 106 106 -170 170 170 26 26 26 86 86 86 226 226 226 -123 123 123 10 10 10 14 14 14 46 46 46 -231 231 231 190 190 190 6 6 6 70 70 70 - 90 90 90 238 238 238 158 158 158 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 1 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 86 86 86 6 6 6 116 116 116 -106 106 106 6 6 6 70 70 70 149 149 149 -128 128 128 18 18 18 38 38 38 54 54 54 -221 221 221 106 106 106 2 2 6 14 14 14 - 46 46 46 190 190 190 198 198 198 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 0 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 94 94 94 14 14 14 101 101 101 -128 128 128 2 2 6 18 18 18 116 116 116 -118 98 46 121 92 8 121 92 8 98 78 10 -162 162 162 106 106 106 2 2 6 2 2 6 - 2 2 6 195 195 195 195 195 195 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 62 62 62 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 1 0 0 1 - 0 0 1 0 0 0 0 0 1 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 90 90 90 14 14 14 58 58 58 -210 210 210 26 26 26 54 38 6 154 114 10 -226 170 11 236 186 11 225 175 15 184 144 12 -215 174 15 175 146 61 37 26 9 2 2 6 - 70 70 70 246 246 246 138 138 138 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 70 70 70 66 66 66 26 26 26 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 14 14 14 10 10 10 -195 195 195 188 164 115 192 133 9 225 175 15 -239 182 13 234 190 10 232 195 16 232 200 30 -245 207 45 241 208 19 232 195 16 184 144 12 -218 194 134 211 206 186 42 42 42 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 74 74 74 30 30 30 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 86 86 86 14 14 14 2 2 6 -121 87 25 192 133 9 219 162 10 239 182 13 -236 186 11 232 195 16 241 208 19 244 214 54 -246 218 60 246 218 38 246 215 20 241 208 19 -241 208 19 226 184 13 121 87 25 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 50 50 50 82 82 82 34 34 34 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 82 82 82 30 30 30 61 42 6 -180 123 7 206 145 10 230 174 11 239 182 13 -234 190 10 238 202 15 241 208 19 246 218 74 -246 218 38 246 215 20 246 215 20 246 215 20 -226 184 13 215 174 15 184 144 12 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 26 26 26 94 94 94 42 42 42 14 14 14 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 50 50 50 104 69 6 -192 133 9 216 158 10 236 178 12 236 186 11 -232 195 16 241 208 19 244 214 54 245 215 43 -246 215 20 246 215 20 241 208 19 198 155 10 -200 144 11 216 158 10 156 118 10 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 90 90 90 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 46 46 46 22 22 22 -137 92 6 210 162 10 239 182 13 238 190 10 -238 202 15 241 208 19 246 215 20 246 215 20 -241 208 19 203 166 17 185 133 11 210 150 10 -216 158 10 210 150 10 102 78 10 2 2 6 - 6 6 6 54 54 54 14 14 14 2 2 6 - 2 2 6 62 62 62 74 74 74 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 34 34 34 78 78 78 50 50 50 6 6 6 - 94 70 30 139 102 15 190 146 13 226 184 13 -232 200 30 232 195 16 215 174 15 190 146 13 -168 122 10 192 133 9 210 150 10 213 154 11 -202 150 34 182 157 106 101 98 89 2 2 6 - 2 2 6 78 78 78 116 116 116 58 58 58 - 2 2 6 22 22 22 90 90 90 46 46 46 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 86 86 86 50 50 50 6 6 6 -128 128 128 174 154 114 156 107 11 168 122 10 -198 155 10 184 144 12 197 138 11 200 144 11 -206 145 10 206 145 10 197 138 11 188 164 115 -195 195 195 198 198 198 174 174 174 14 14 14 - 2 2 6 22 22 22 116 116 116 116 116 116 - 22 22 22 2 2 6 74 74 74 70 70 70 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 101 101 101 26 26 26 10 10 10 -138 138 138 190 190 190 174 154 114 156 107 11 -197 138 11 200 144 11 197 138 11 192 133 9 -180 123 7 190 142 34 190 178 144 187 187 187 -202 202 202 221 221 221 214 214 214 66 66 66 - 2 2 6 2 2 6 50 50 50 62 62 62 - 6 6 6 2 2 6 10 10 10 90 90 90 - 50 50 50 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 34 34 34 - 74 74 74 74 74 74 2 2 6 6 6 6 -144 144 144 198 198 198 190 190 190 178 166 146 -154 121 60 156 107 11 156 107 11 168 124 44 -174 154 114 187 187 187 190 190 190 210 210 210 -246 246 246 253 253 253 253 253 253 182 182 182 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 62 62 62 - 74 74 74 34 34 34 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 10 10 10 22 22 22 54 54 54 - 94 94 94 18 18 18 2 2 6 46 46 46 -234 234 234 221 221 221 190 190 190 190 190 190 -190 190 190 187 187 187 187 187 187 190 190 190 -190 190 190 195 195 195 214 214 214 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 - 82 82 82 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 14 14 14 - 86 86 86 54 54 54 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 46 46 46 90 90 90 - 46 46 46 18 18 18 6 6 6 182 182 182 -253 253 253 246 246 246 206 206 206 190 190 190 -190 190 190 190 190 190 190 190 190 190 190 190 -206 206 206 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -202 202 202 14 14 14 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 86 86 86 42 42 42 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 14 14 14 38 38 38 74 74 74 66 66 66 - 2 2 6 6 6 6 90 90 90 250 250 250 -253 253 253 253 253 253 238 238 238 198 198 198 -190 190 190 190 190 190 195 195 195 221 221 221 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 82 82 82 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 78 78 78 70 70 70 34 34 34 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 34 34 34 66 66 66 78 78 78 6 6 6 - 2 2 6 18 18 18 218 218 218 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -226 226 226 231 231 231 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 178 178 178 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 18 18 18 90 90 90 62 62 62 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 26 26 26 - 58 58 58 90 90 90 18 18 18 2 2 6 - 2 2 6 110 110 110 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 18 18 18 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 94 94 94 - 54 54 54 26 26 26 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 22 22 22 50 50 50 - 90 90 90 26 26 26 2 2 6 2 2 6 - 14 14 14 195 195 195 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 242 242 242 54 54 54 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 86 86 86 50 50 50 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 38 38 38 82 82 82 - 34 34 34 2 2 6 2 2 6 2 2 6 - 42 42 42 195 195 195 246 246 246 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 242 242 242 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 246 246 246 238 238 238 -226 226 226 231 231 231 101 101 101 6 6 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 38 38 38 82 82 82 42 42 42 14 14 14 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 26 26 26 62 62 62 66 66 66 - 2 2 6 2 2 6 2 2 6 6 6 6 - 70 70 70 170 170 170 206 206 206 234 234 234 -246 246 246 250 250 250 250 250 250 238 238 238 -226 226 226 231 231 231 238 238 238 250 250 250 -250 250 250 250 250 250 246 246 246 231 231 231 -214 214 214 206 206 206 202 202 202 202 202 202 -198 198 198 202 202 202 182 182 182 18 18 18 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 62 62 62 66 66 66 30 30 30 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 42 42 42 82 82 82 18 18 18 - 2 2 6 2 2 6 2 2 6 10 10 10 - 94 94 94 182 182 182 218 218 218 242 242 242 -250 250 250 253 253 253 253 253 253 250 250 250 -234 234 234 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -238 238 238 226 226 226 210 210 210 202 202 202 -195 195 195 195 195 195 210 210 210 158 158 158 - 6 6 6 14 14 14 50 50 50 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 86 86 86 46 46 46 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 70 70 70 2 2 6 - 2 2 6 10 10 10 2 2 6 22 22 22 -166 166 166 231 231 231 250 250 250 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 246 246 -231 231 231 206 206 206 198 198 198 226 226 226 - 94 94 94 2 2 6 6 6 6 38 38 38 - 30 30 30 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 62 62 62 66 66 66 - 26 26 26 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 74 74 74 50 50 50 2 2 6 - 26 26 26 26 26 26 2 2 6 106 106 106 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 218 218 218 202 202 202 -210 210 210 14 14 14 2 2 6 2 2 6 - 30 30 30 22 22 22 2 2 6 2 2 6 - 2 2 6 2 2 6 18 18 18 86 86 86 - 42 42 42 14 14 14 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 42 42 42 90 90 90 22 22 22 2 2 6 - 42 42 42 2 2 6 18 18 18 218 218 218 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 221 221 221 -218 218 218 101 101 101 2 2 6 14 14 14 - 18 18 18 38 38 38 10 10 10 2 2 6 - 2 2 6 2 2 6 2 2 6 78 78 78 - 58 58 58 22 22 22 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 54 54 54 82 82 82 2 2 6 26 26 26 - 22 22 22 2 2 6 123 123 123 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -238 238 238 198 198 198 6 6 6 38 38 38 - 58 58 58 26 26 26 38 38 38 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 78 78 78 30 30 30 10 10 10 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 10 10 10 30 30 30 - 74 74 74 58 58 58 2 2 6 42 42 42 - 2 2 6 22 22 22 231 231 231 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 246 246 246 46 46 46 38 38 38 - 42 42 42 14 14 14 38 38 38 14 14 14 - 2 2 6 2 2 6 2 2 6 6 6 6 - 86 86 86 46 46 46 14 14 14 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 42 42 42 - 90 90 90 18 18 18 18 18 18 26 26 26 - 2 2 6 116 116 116 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 250 250 250 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 94 94 94 6 6 6 - 2 2 6 2 2 6 10 10 10 34 34 34 - 2 2 6 2 2 6 2 2 6 2 2 6 - 74 74 74 58 58 58 22 22 22 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 10 10 10 26 26 26 66 66 66 - 82 82 82 2 2 6 38 38 38 6 6 6 - 14 14 14 210 210 210 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 246 246 246 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 144 144 144 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 42 42 42 74 74 74 30 30 30 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 42 42 42 90 90 90 - 26 26 26 6 6 6 42 42 42 2 2 6 - 74 74 74 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 242 242 242 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 182 182 182 2 2 6 - 2 2 6 2 2 6 2 2 6 46 46 46 - 2 2 6 2 2 6 2 2 6 2 2 6 - 10 10 10 86 86 86 38 38 38 10 10 10 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 10 10 10 26 26 26 66 66 66 82 82 82 - 2 2 6 22 22 22 18 18 18 2 2 6 -149 149 149 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 2 2 6 2 2 6 2 2 6 38 38 38 - 2 2 6 2 2 6 2 2 6 2 2 6 - 6 6 6 86 86 86 46 46 46 14 14 14 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 18 18 18 46 46 46 86 86 86 18 18 18 - 2 2 6 34 34 34 10 10 10 6 6 6 -210 210 210 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 221 221 221 6 6 6 - 2 2 6 2 2 6 6 6 6 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 26 26 26 66 66 66 62 62 62 2 2 6 - 2 2 6 38 38 38 10 10 10 26 26 26 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 238 238 238 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 6 6 6 - 2 2 6 2 2 6 10 10 10 30 30 30 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 38 38 38 78 78 78 6 6 6 2 2 6 - 2 2 6 46 46 46 14 14 14 42 42 42 -246 246 246 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 10 10 10 - 2 2 6 2 2 6 22 22 22 14 14 14 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 74 74 74 2 2 6 2 2 6 - 14 14 14 70 70 70 34 34 34 62 62 62 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 14 14 14 - 2 2 6 2 2 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 62 62 62 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 54 54 54 62 62 62 2 2 6 2 2 6 - 2 2 6 30 30 30 46 46 46 70 70 70 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 226 226 226 10 10 10 - 2 2 6 6 6 6 30 30 30 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 66 66 66 58 58 58 22 22 22 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 58 58 58 62 62 62 2 2 6 2 2 6 - 2 2 6 2 2 6 30 30 30 78 78 78 -250 250 250 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 206 206 206 2 2 6 - 22 22 22 34 34 34 18 14 6 22 22 22 - 26 26 26 18 18 18 6 6 6 2 2 6 - 2 2 6 82 82 82 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 26 26 26 - 62 62 62 106 106 106 74 54 14 185 133 11 -210 162 10 121 92 8 6 6 6 62 62 62 -238 238 238 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 246 246 246 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 158 158 158 18 18 18 - 14 14 14 2 2 6 2 2 6 2 2 6 - 6 6 6 18 18 18 66 66 66 38 38 38 - 6 6 6 94 94 94 50 50 50 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 10 10 10 10 10 10 18 18 18 38 38 38 - 78 78 78 142 134 106 216 158 10 242 186 14 -246 190 14 246 190 14 156 118 10 10 10 10 - 90 90 90 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 246 230 190 -238 204 91 238 204 91 181 142 44 37 26 9 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 38 38 38 46 46 46 - 26 26 26 106 106 106 54 54 54 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 22 22 22 - 30 30 30 38 38 38 50 50 50 70 70 70 -106 106 106 190 142 34 226 170 11 242 186 14 -246 190 14 246 190 14 246 190 14 154 114 10 - 6 6 6 74 74 74 226 226 226 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 231 231 231 250 250 250 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 228 184 62 -241 196 14 241 208 19 232 195 16 38 30 10 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 30 30 30 26 26 26 -203 166 17 154 142 90 66 66 66 26 26 26 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 38 38 38 58 58 58 - 78 78 78 86 86 86 101 101 101 123 123 123 -175 146 61 210 150 10 234 174 13 246 186 14 -246 190 14 246 190 14 246 190 14 238 190 10 -102 78 10 2 2 6 46 46 46 198 198 198 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 234 234 234 242 242 242 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 224 178 62 -242 186 14 241 196 14 210 166 10 22 18 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 6 6 6 121 92 8 -238 202 15 232 195 16 82 82 82 34 34 34 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 14 14 14 38 38 38 70 70 70 154 122 46 -190 142 34 200 144 11 197 138 11 197 138 11 -213 154 11 226 170 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -225 175 15 46 32 6 2 2 6 22 22 22 -158 158 158 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 242 242 242 224 178 62 -239 182 13 236 186 11 213 154 11 46 32 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 225 175 15 -238 190 10 236 186 11 112 100 78 42 42 42 - 14 14 14 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 22 22 22 54 54 54 154 122 46 213 154 11 -226 170 11 230 174 11 226 170 11 226 170 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 184 144 12 10 10 10 2 2 6 - 6 6 6 116 116 116 242 242 242 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 231 231 231 198 198 198 214 170 54 -236 178 12 236 178 12 210 150 10 137 92 6 - 18 14 6 2 2 6 2 2 6 2 2 6 - 6 6 6 70 47 6 200 144 11 236 178 12 -239 182 13 239 182 13 124 112 88 58 58 58 - 22 22 22 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 70 70 70 180 133 36 226 170 11 -239 182 13 242 186 14 242 186 14 246 186 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 98 70 6 2 2 6 - 2 2 6 2 2 6 66 66 66 221 221 221 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 206 206 206 198 198 198 214 166 58 -230 174 11 230 174 11 216 158 10 192 133 9 -163 110 8 116 81 8 102 78 10 116 81 8 -167 114 7 197 138 11 226 170 11 239 182 13 -242 186 14 242 186 14 162 146 94 78 78 78 - 34 34 34 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 30 30 30 78 78 78 190 142 34 226 170 11 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 241 196 14 203 166 17 22 18 6 - 2 2 6 2 2 6 2 2 6 38 38 38 -218 218 218 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 206 206 206 198 198 198 202 162 69 -226 170 11 236 178 12 224 166 10 210 150 10 -200 144 11 197 138 11 192 133 9 197 138 11 -210 150 10 226 170 11 242 186 14 246 190 14 -246 190 14 246 186 14 225 175 15 124 112 88 - 62 62 62 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 174 135 50 224 166 10 -239 182 13 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 139 102 15 - 2 2 6 2 2 6 2 2 6 2 2 6 - 78 78 78 250 250 250 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -250 250 250 214 214 214 198 198 198 190 150 46 -219 162 10 236 178 12 234 174 13 224 166 10 -216 158 10 213 154 11 213 154 11 216 158 10 -226 170 11 239 182 13 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 206 162 42 -101 101 101 58 58 58 30 30 30 14 14 14 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 74 74 74 174 135 50 216 158 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 241 196 14 226 184 13 - 61 42 6 2 2 6 2 2 6 2 2 6 - 22 22 22 238 238 238 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 226 226 226 187 187 187 180 133 36 -216 158 10 236 178 12 239 182 13 236 178 12 -230 174 11 226 170 11 226 170 11 230 174 11 -236 178 12 242 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 186 14 239 182 13 -206 162 42 106 106 106 66 66 66 34 34 34 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 26 26 26 70 70 70 163 133 67 213 154 11 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 241 196 14 -190 146 13 18 14 6 2 2 6 2 2 6 - 46 46 46 246 246 246 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 221 221 221 86 86 86 156 107 11 -216 158 10 236 178 12 242 186 14 246 186 14 -242 186 14 239 182 13 239 182 13 242 186 14 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 225 175 15 142 122 72 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 26 26 26 70 70 70 163 133 67 210 150 10 -236 178 12 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -232 195 16 121 92 8 34 34 34 106 106 106 -221 221 221 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -242 242 242 82 82 82 18 14 6 163 110 8 -216 158 10 236 178 12 242 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 242 186 14 163 133 67 - 46 46 46 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 10 10 10 - 30 30 30 78 78 78 163 133 67 210 150 10 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -241 196 14 215 174 15 190 178 144 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 218 218 218 - 58 58 58 2 2 6 22 18 6 167 114 7 -216 158 10 236 178 12 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 186 14 242 186 14 190 150 46 - 54 54 54 22 22 22 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 38 38 38 86 86 86 180 133 36 213 154 11 -236 178 12 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 232 195 16 190 146 13 214 214 214 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 250 250 250 170 170 170 26 26 26 - 2 2 6 2 2 6 37 26 9 163 110 8 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 224 166 10 142 122 72 - 46 46 46 18 18 18 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 109 106 95 192 133 9 224 166 10 -242 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -242 186 14 226 184 13 210 162 10 142 110 46 -226 226 226 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -253 253 253 253 253 253 253 253 253 253 253 253 -198 198 198 66 66 66 2 2 6 2 2 6 - 2 2 6 2 2 6 50 34 6 156 107 11 -219 162 10 239 182 13 246 186 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 242 186 14 -234 174 13 213 154 11 154 122 46 66 66 66 - 30 30 30 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 58 58 58 154 121 60 206 145 10 234 174 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 236 178 12 210 162 10 163 110 8 - 61 42 6 138 138 138 218 218 218 250 250 250 -253 253 253 253 253 253 253 253 253 250 250 250 -242 242 242 210 210 210 144 144 144 66 66 66 - 6 6 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 61 42 6 163 110 8 -216 158 10 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 239 182 13 230 174 11 216 158 10 -190 142 34 124 112 88 70 70 70 38 38 38 - 18 18 18 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 22 22 22 - 62 62 62 168 124 44 206 145 10 224 166 10 -236 178 12 239 182 13 242 186 14 242 186 14 -246 186 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 236 178 12 216 158 10 175 118 6 - 80 54 7 2 2 6 6 6 6 30 30 30 - 54 54 54 62 62 62 50 50 50 38 38 38 - 14 14 14 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 167 114 7 -213 154 11 236 178 12 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 190 14 242 186 14 239 182 13 239 182 13 -230 174 11 210 150 10 174 135 50 124 112 88 - 82 82 82 54 54 54 34 34 34 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 18 18 18 - 50 50 50 158 118 36 192 133 9 200 144 11 -216 158 10 219 162 10 224 166 10 226 170 11 -230 174 11 236 178 12 239 182 13 239 182 13 -242 186 14 246 186 14 246 190 14 246 190 14 -246 190 14 246 190 14 246 190 14 246 190 14 -246 186 14 230 174 11 210 150 10 163 110 8 -104 69 6 10 10 10 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 91 60 6 167 114 7 -206 145 10 230 174 11 242 186 14 246 190 14 -246 190 14 246 190 14 246 186 14 242 186 14 -239 182 13 230 174 11 224 166 10 213 154 11 -180 133 36 124 112 88 86 86 86 58 58 58 - 38 38 38 22 22 22 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 14 14 14 - 34 34 34 70 70 70 138 110 50 158 118 36 -167 114 7 180 123 7 192 133 9 197 138 11 -200 144 11 206 145 10 213 154 11 219 162 10 -224 166 10 230 174 11 239 182 13 242 186 14 -246 186 14 246 186 14 246 186 14 246 186 14 -239 182 13 216 158 10 185 133 11 152 99 6 -104 69 6 18 14 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 2 2 6 2 2 6 2 2 6 - 2 2 6 6 6 6 80 54 7 152 99 6 -192 133 9 219 162 10 236 178 12 239 182 13 -246 186 14 242 186 14 239 182 13 236 178 12 -224 166 10 206 145 10 192 133 9 154 121 60 - 94 94 94 62 62 62 42 42 42 22 22 22 - 14 14 14 6 6 6 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 18 18 18 34 34 34 58 58 58 78 78 78 -101 98 89 124 112 88 142 110 46 156 107 11 -163 110 8 167 114 7 175 118 6 180 123 7 -185 133 11 197 138 11 210 150 10 219 162 10 -226 170 11 236 178 12 236 178 12 234 174 13 -219 162 10 197 138 11 163 110 8 130 83 6 - 91 60 6 10 10 10 2 2 6 2 2 6 - 18 18 18 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 38 38 38 38 38 38 - 38 38 38 38 38 38 26 26 26 2 2 6 - 2 2 6 6 6 6 70 47 6 137 92 6 -175 118 6 200 144 11 219 162 10 230 174 11 -234 174 13 230 174 11 219 162 10 210 150 10 -192 133 9 163 110 8 124 112 88 82 82 82 - 50 50 50 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 14 14 14 22 22 22 34 34 34 - 42 42 42 58 58 58 74 74 74 86 86 86 -101 98 89 122 102 70 130 98 46 121 87 25 -137 92 6 152 99 6 163 110 8 180 123 7 -185 133 11 197 138 11 206 145 10 200 144 11 -180 123 7 156 107 11 130 83 6 104 69 6 - 50 34 6 54 54 54 110 110 110 101 98 89 - 86 86 86 82 82 82 78 78 78 78 78 78 - 78 78 78 78 78 78 78 78 78 78 78 78 - 78 78 78 82 82 82 86 86 86 94 94 94 -106 106 106 101 101 101 86 66 34 124 80 6 -156 107 11 180 123 7 192 133 9 200 144 11 -206 145 10 200 144 11 192 133 9 175 118 6 -139 102 15 109 106 95 70 70 70 42 42 42 - 22 22 22 10 10 10 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 6 6 6 10 10 10 - 14 14 14 22 22 22 30 30 30 38 38 38 - 50 50 50 62 62 62 74 74 74 90 90 90 -101 98 89 112 100 78 121 87 25 124 80 6 -137 92 6 152 99 6 152 99 6 152 99 6 -138 86 6 124 80 6 98 70 6 86 66 30 -101 98 89 82 82 82 58 58 58 46 46 46 - 38 38 38 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 34 34 34 34 34 34 - 34 34 34 34 34 34 38 38 38 42 42 42 - 54 54 54 82 82 82 94 86 76 91 60 6 -134 86 6 156 107 11 167 114 7 175 118 6 -175 118 6 167 114 7 152 99 6 121 87 25 -101 98 89 62 62 62 34 34 34 18 18 18 - 6 6 6 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 6 6 6 10 10 10 - 18 18 18 22 22 22 30 30 30 42 42 42 - 50 50 50 66 66 66 86 86 86 101 98 89 -106 86 58 98 70 6 104 69 6 104 69 6 -104 69 6 91 60 6 82 62 34 90 90 90 - 62 62 62 38 38 38 22 22 22 14 14 14 - 10 10 10 10 10 10 10 10 10 10 10 10 - 10 10 10 10 10 10 6 6 6 10 10 10 - 10 10 10 10 10 10 10 10 10 14 14 14 - 22 22 22 42 42 42 70 70 70 89 81 66 - 80 54 7 104 69 6 124 80 6 137 92 6 -134 86 6 116 81 8 100 82 52 86 86 86 - 58 58 58 30 30 30 14 14 14 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 10 10 10 14 14 14 - 18 18 18 26 26 26 38 38 38 54 54 54 - 70 70 70 86 86 86 94 86 76 89 81 66 - 89 81 66 86 86 86 74 74 74 50 50 50 - 30 30 30 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 18 18 18 34 34 34 58 58 58 - 82 82 82 89 81 66 89 81 66 89 81 66 - 94 86 66 94 86 76 74 74 74 50 50 50 - 26 26 26 14 14 14 6 6 6 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 6 6 6 6 6 6 14 14 14 18 18 18 - 30 30 30 38 38 38 46 46 46 54 54 54 - 50 50 50 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 6 6 6 14 14 14 26 26 26 - 38 38 38 50 50 50 58 58 58 58 58 58 - 54 54 54 42 42 42 30 30 30 18 18 18 - 10 10 10 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 6 6 6 10 10 10 14 14 14 18 18 18 - 18 18 18 14 14 14 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 6 6 6 - 14 14 14 18 18 18 22 22 22 22 22 22 - 18 18 18 14 14 14 10 10 10 6 6 6 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 3 4 4 6 7 7 +8 10 10 8 10 10 6 8 8 6 7 7 3 4 4 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 4 5 5 17 18 17 +27 29 28 35 37 36 40 43 41 43 45 43 40 43 41 37 39 37 +32 34 33 27 30 29 23 25 24 17 21 21 15 18 18 12 15 15 +11 13 13 8 10 10 6 7 7 3 4 4 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 13 13 13 32 34 33 49 51 48 60 60 56 58 59 55 +55 57 54 55 56 53 49 51 48 43 45 43 39 40 39 33 37 35 +28 31 30 23 27 26 20 23 23 17 20 20 14 17 17 13 16 16 +11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 6 7 7 +2 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 6 7 7 12 15 15 +12 15 15 8 9 9 2 3 3 0 0 0 1 1 1 25 27 26 +55 56 53 68 70 65 65 66 61 65 66 61 63 64 60 63 64 60 +58 59 55 51 52 50 47 48 46 41 42 42 35 37 36 30 32 31 +26 28 27 20 24 24 18 22 22 16 19 19 14 17 17 13 16 16 +12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 +8 9 9 6 8 8 3 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 6 7 7 20 24 24 23 27 26 +23 27 26 18 22 22 11 13 13 23 24 24 61 63 57 72 73 67 +72 73 67 68 70 65 68 70 65 68 70 65 63 64 60 58 59 55 +55 56 53 47 48 46 41 42 42 35 37 36 30 32 31 26 28 27 +20 24 24 18 22 22 16 20 20 15 19 19 14 17 17 13 16 16 +12 15 15 12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 +8 10 10 8 9 9 7 9 9 6 7 7 1 2 2 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 4 5 5 5 6 5 4 5 5 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 15 19 19 40 41 39 53 55 47 +33 36 34 27 30 29 51 52 50 72 73 67 72 73 67 72 73 67 +72 73 67 68 70 65 68 70 65 63 64 60 58 59 55 51 52 50 +47 48 46 40 43 41 33 37 35 30 32 31 26 28 27 20 24 24 +18 22 22 17 21 21 16 19 19 14 18 18 14 17 17 13 17 17 +13 16 16 12 15 15 12 15 15 11 14 14 10 13 13 10 12 12 +9 11 11 8 10 10 8 9 9 7 9 9 6 8 8 3 4 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 2 2 6 8 8 10 12 12 10 12 12 10 12 12 10 12 12 +6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 20 23 23 71 71 57 131 127 93 +115 113 82 63 64 60 72 73 67 72 73 67 72 73 67 72 73 67 +68 70 65 65 66 61 61 63 57 55 57 54 49 51 48 43 45 43 +39 40 39 33 36 34 28 31 30 23 27 26 20 24 24 20 23 23 +17 21 21 16 20 20 15 19 19 15 18 18 14 18 18 14 17 17 +13 17 17 13 16 16 12 15 15 12 15 15 11 14 14 10 13 13 +10 12 12 9 11 11 8 10 10 7 9 9 7 9 9 6 8 8 +4 5 5 0 0 0 0 0 0 0 0 0 1 1 1 6 7 7 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +10 12 12 3 4 4 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 18 22 22 71 71 57 144 139 99 +84 83 72 68 70 65 72 73 67 72 73 67 68 70 65 65 66 61 +63 64 60 55 57 54 51 52 50 47 48 46 40 43 41 35 37 36 +30 32 31 27 29 28 23 27 26 20 24 24 18 22 22 17 21 21 +16 20 20 15 19 19 15 19 19 15 19 19 15 18 18 14 18 18 +14 17 17 13 17 17 13 16 16 12 15 15 12 15 15 11 14 14 +10 13 13 9 12 12 9 11 11 8 10 10 7 9 9 6 8 8 +6 8 8 3 4 4 0 0 0 2 2 2 8 10 10 10 12 12 +10 12 12 10 12 12 11 13 13 36 38 35 61 61 53 48 49 45 +10 12 12 7 9 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 15 19 19 61 61 53 84 83 72 +68 70 65 72 73 67 68 70 65 68 70 65 63 64 60 58 59 55 +51 52 50 47 48 46 41 42 42 37 39 37 32 35 33 28 31 30 +23 27 26 20 24 24 20 23 23 18 22 22 17 21 21 17 21 21 +17 21 21 17 21 21 17 20 20 16 20 20 16 20 20 16 19 19 +15 18 18 14 18 18 13 17 17 13 16 16 12 15 15 12 15 15 +11 14 14 10 13 13 9 12 12 9 11 11 8 10 10 7 9 9 +6 8 8 6 8 8 5 6 5 9 11 11 10 12 12 10 12 12 +19 20 18 82 81 62 149 145 103 160 154 106 142 137 94 96 95 69 +10 12 12 10 12 12 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 10 12 12 44 46 43 68 70 65 +72 73 67 68 70 65 68 70 65 63 64 60 55 57 54 49 51 48 +43 45 43 39 40 39 33 37 35 30 32 31 26 28 27 23 27 26 +20 24 24 18 22 22 18 22 22 18 22 22 18 22 22 20 23 23 +20 24 24 23 25 24 23 25 24 22 24 23 20 23 23 18 22 22 +17 20 20 15 19 19 15 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 11 13 13 10 12 12 9 11 11 8 10 10 8 9 9 +7 9 9 7 9 9 10 12 12 10 12 12 10 12 12 71 71 57 +164 159 111 186 182 128 186 182 128 171 165 117 151 147 98 96 95 69 +10 12 12 10 12 12 3 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 8 10 10 63 64 60 68 70 65 +72 73 67 68 70 65 63 64 60 55 57 54 47 48 46 40 43 41 +33 37 35 30 32 31 27 29 28 23 27 26 20 24 24 20 23 23 +18 22 22 18 22 22 20 23 22 21 25 23 23 27 26 27 29 28 +28 31 30 31 33 31 31 33 31 31 33 31 28 31 30 26 28 27 +23 25 24 20 23 22 16 20 20 15 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 10 13 13 10 12 12 9 11 11 8 10 10 +10 12 12 10 13 13 10 12 12 12 14 14 96 95 69 165 161 109 +186 182 128 192 187 134 192 187 134 176 171 126 160 154 106 103 101 77 +10 12 12 10 12 12 5 6 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 35 37 36 68 70 65 72 73 67 +68 70 65 65 66 61 58 59 55 49 51 48 40 43 41 33 37 35 +28 31 30 23 27 26 20 24 24 20 23 23 18 22 22 18 22 22 +18 22 22 20 23 23 23 27 26 27 30 29 32 35 33 37 39 37 +40 43 41 44 46 43 46 47 43 44 46 43 40 43 41 36 38 35 +31 33 31 27 29 28 22 24 23 17 21 21 15 18 18 14 17 17 +13 16 16 12 15 15 11 14 14 11 14 14 11 13 13 13 16 16 +13 16 16 11 14 14 10 12 12 79 78 62 142 137 94 164 159 111 +178 174 128 192 187 134 192 187 134 176 171 126 160 154 106 96 95 69 +10 12 12 10 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 55 57 54 68 70 65 72 73 67 +68 70 65 63 64 60 55 56 53 43 45 43 35 37 36 28 31 30 +23 27 26 20 24 24 18 22 22 17 21 21 17 21 21 17 21 21 +20 24 24 25 27 26 31 33 31 38 39 37 46 47 43 53 55 47 +61 61 53 66 65 55 66 65 55 66 65 55 61 61 53 53 55 47 +46 47 43 37 39 37 30 33 30 24 26 24 17 21 21 15 18 18 +13 17 17 12 15 15 12 15 15 13 16 16 14 18 18 14 18 18 +14 17 17 12 15 15 30 31 28 118 116 76 134 131 96 160 154 106 +174 170 121 178 174 128 178 174 128 171 165 117 151 147 98 96 95 69 +10 12 12 10 12 12 6 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 63 64 60 68 70 65 68 70 65 +65 66 61 58 59 55 49 51 48 39 40 39 30 32 31 23 27 26 +20 24 24 18 22 22 17 21 21 16 20 20 17 21 21 20 23 23 +25 27 26 32 35 33 43 44 41 53 55 47 66 65 55 75 75 61 +82 81 62 84 83 72 87 86 72 87 86 72 82 81 62 75 75 61 +66 65 55 53 55 47 40 41 39 31 33 31 23 25 24 17 20 20 +14 18 18 13 16 16 12 15 15 12 15 15 13 17 17 14 18 18 +14 18 18 13 16 16 46 47 43 96 95 69 125 122 87 142 137 94 +160 154 106 165 161 109 164 159 111 155 149 109 142 137 94 75 75 61 +10 12 12 10 12 12 6 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 60 60 56 68 70 65 68 70 65 +63 64 60 55 57 54 46 47 45 35 37 36 27 30 29 23 25 24 +18 22 22 17 21 21 16 20 20 17 21 21 18 22 22 23 27 26 +31 33 31 43 44 41 55 56 53 71 71 57 84 83 72 92 91 72 +103 101 77 92 91 72 82 81 62 82 81 62 87 86 72 92 91 72 +84 83 72 71 71 57 55 56 53 43 44 41 30 33 30 22 24 23 +16 19 19 14 17 17 12 15 15 12 15 15 13 16 16 14 18 18 +14 18 18 14 17 17 43 44 41 82 81 62 118 116 76 125 122 87 +142 137 94 144 139 99 144 139 99 134 131 96 118 116 76 53 55 47 +10 12 12 10 12 12 6 8 8 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 47 48 46 63 64 60 63 64 60 +55 57 54 49 51 48 40 43 41 32 34 33 26 28 27 20 24 24 +18 22 22 16 20 20 16 20 20 17 21 21 20 24 24 28 31 30 +40 41 39 53 55 47 75 75 61 90 89 73 87 86 72 48 49 45 +14 14 13 2 2 2 1 2 2 1 1 1 1 1 1 2 2 2 +19 20 18 43 44 41 66 65 55 53 55 47 38 39 37 26 28 27 +18 22 22 14 18 18 13 16 16 12 15 15 12 15 15 13 17 17 +14 18 18 14 18 18 30 31 28 66 65 55 96 95 69 103 101 77 +118 116 76 118 116 76 118 116 76 118 116 76 103 101 77 36 38 35 +10 12 12 10 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 28 31 30 55 57 54 51 52 50 +49 51 48 41 42 42 35 37 36 28 31 30 23 27 26 20 23 23 +17 21 21 16 20 20 16 20 20 18 22 22 23 27 26 33 36 34 +48 49 45 71 71 57 82 81 62 43 44 41 8 9 9 6 7 7 +6 7 7 6 7 7 6 7 7 5 6 5 4 5 5 3 4 4 +2 3 3 1 2 2 4 5 4 36 38 35 48 49 45 32 35 33 +21 25 23 16 19 19 13 17 17 12 15 15 12 15 15 13 16 16 +14 18 18 14 18 18 16 18 16 36 38 35 61 61 53 82 81 62 +96 95 69 96 95 69 96 95 69 96 95 69 79 78 62 19 20 18 +10 12 12 10 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 13 13 13 46 47 45 43 45 43 +40 43 41 35 37 36 30 32 31 23 27 26 20 24 24 18 22 22 +17 21 21 16 20 20 17 21 21 20 23 23 27 30 29 40 41 39 +61 61 53 53 55 47 16 17 16 9 11 11 10 12 12 10 12 12 +10 12 12 10 12 12 10 12 12 9 11 11 8 10 10 8 9 9 +6 8 8 5 6 5 4 5 5 2 3 3 19 20 18 38 39 37 +26 28 27 17 21 21 14 17 17 13 16 16 12 15 15 12 15 15 +13 17 17 14 18 18 12 15 15 13 12 7 30 31 28 46 47 43 +53 55 47 66 65 55 66 65 55 53 55 47 36 38 35 10 12 12 +10 12 12 10 12 12 2 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 33 37 35 35 37 36 +32 35 33 28 31 30 23 27 26 20 24 24 18 22 22 17 21 21 +16 20 20 16 20 20 17 21 21 21 25 23 31 33 31 44 46 43 +31 33 31 11 13 13 12 14 14 12 15 15 13 16 16 14 17 17 +14 17 17 14 17 17 14 17 17 13 16 16 12 15 15 12 14 14 +11 13 13 9 11 11 8 10 10 6 8 8 4 5 5 17 18 17 +30 33 30 20 23 22 15 18 18 13 16 16 12 15 15 12 14 14 +13 16 16 14 17 17 14 18 18 11 12 11 7 7 5 16 17 12 +21 22 20 30 31 28 25 27 25 21 22 20 14 14 13 10 12 12 +10 12 12 9 11 11 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 18 22 22 27 30 29 +27 29 28 40 41 39 53 55 47 53 55 47 53 55 47 46 47 43 +25 27 25 16 20 20 17 21 21 23 25 24 31 33 31 20 20 20 +12 15 15 14 17 17 15 19 19 16 20 20 17 21 21 18 22 22 +18 22 22 18 22 22 18 22 22 17 21 21 17 21 21 16 19 19 +15 18 18 13 16 16 12 15 15 10 12 12 8 10 10 6 8 8 +21 22 21 22 24 23 15 19 19 13 17 17 13 16 16 12 15 15 +12 15 15 13 17 17 14 18 18 14 18 18 13 15 14 10 9 6 +7 7 5 7 7 5 7 7 5 9 11 11 10 12 12 10 12 12 +10 12 12 6 7 7 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 16 17 12 82 81 62 +118 116 76 118 116 76 161 156 96 161 156 96 161 156 96 118 116 76 +118 116 76 96 95 69 53 55 47 22 24 23 14 17 17 13 16 16 +15 19 19 17 21 21 18 22 22 20 24 24 20 24 24 23 27 26 +23 27 26 23 27 26 23 27 26 23 27 26 23 27 26 20 24 24 +20 23 23 17 21 21 16 19 19 14 17 17 12 15 15 10 12 12 +9 11 11 20 23 22 16 19 19 14 17 17 13 16 16 12 15 15 +11 14 14 13 16 16 14 17 17 14 18 18 14 17 17 12 15 15 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +9 11 11 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 53 55 47 161 156 96 +161 156 96 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 96 95 69 21 22 20 16 19 19 +18 22 22 20 24 24 23 27 26 23 27 26 26 28 27 27 30 29 +27 30 29 18 22 22 12 14 14 8 10 10 9 11 11 17 21 21 +23 27 26 23 27 26 20 24 24 18 22 22 16 20 20 14 17 17 +12 14 14 14 17 17 16 20 20 14 17 17 13 17 17 13 16 16 +12 15 15 12 15 15 13 17 17 14 18 18 14 17 17 13 16 16 +11 13 13 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 13 12 7 118 116 76 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 30 31 28 +20 24 24 23 27 26 27 30 29 28 31 30 30 32 31 23 27 26 +16 19 19 17 21 21 12 15 15 9 11 11 10 12 12 9 11 11 +20 24 24 28 31 30 26 28 27 23 27 26 20 24 24 17 21 21 +15 19 19 13 16 16 16 19 19 14 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 13 16 16 14 17 17 14 18 18 14 17 17 +12 15 15 10 12 12 10 12 12 10 12 12 10 12 12 8 9 9 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 82 81 62 161 156 96 230 229 82 +230 229 82 233 233 100 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 +27 29 28 27 30 29 30 32 31 30 32 31 23 27 26 20 24 24 +26 28 27 17 21 21 6 7 7 72 73 67 145 141 105 15 15 15 +14 17 17 33 37 35 30 32 31 28 31 30 26 28 27 23 27 26 +20 23 23 16 20 20 15 19 19 14 18 18 14 17 17 13 16 16 +12 15 15 11 14 14 12 15 15 13 17 17 14 18 18 14 17 17 +13 16 16 11 13 13 10 12 12 10 12 12 9 11 11 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 16 17 12 161 156 96 230 229 82 230 229 82 +243 242 120 235 234 117 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +82 81 62 28 31 30 28 31 30 27 30 29 28 31 30 30 32 31 +33 37 35 13 16 16 3 3 3 105 104 92 210 208 158 12 14 14 +17 21 21 33 37 35 33 37 35 32 35 33 30 32 31 27 30 29 +23 27 26 20 23 23 17 20 20 15 18 18 14 18 18 13 17 17 +13 16 16 12 15 15 11 14 14 13 16 16 14 17 17 14 18 18 +13 17 17 12 15 15 10 12 12 10 12 12 3 4 4 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 96 95 69 230 229 82 230 229 82 244 244 132 +241 241 143 243 242 120 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +161 156 96 46 47 43 32 35 33 33 37 35 33 37 35 33 37 35 +40 43 41 23 27 26 1 1 1 2 2 2 24 26 24 14 17 17 +23 27 26 33 37 35 33 37 35 33 37 35 33 37 35 30 32 31 +27 30 29 23 27 26 20 23 23 15 18 18 14 18 18 14 17 17 +13 16 16 12 15 15 11 14 14 12 15 15 13 17 17 14 17 17 +14 17 17 13 16 16 11 13 13 6 8 8 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 16 17 12 161 156 96 230 229 82 235 234 117 239 239 170 +239 239 170 236 236 101 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 118 116 76 33 37 35 33 37 35 37 39 37 37 39 37 +43 45 43 49 51 48 20 24 24 8 10 10 17 20 20 35 37 36 +33 37 35 40 43 41 37 39 37 35 37 36 33 37 35 33 37 35 +30 32 31 27 30 29 23 27 26 15 19 19 14 18 18 14 17 17 +13 17 17 13 16 16 12 15 15 11 14 14 13 16 16 14 17 17 +14 17 17 13 17 17 11 14 14 4 5 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 96 95 69 230 229 82 230 229 82 239 239 170 251 251 187 +241 241 143 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 36 38 35 33 37 35 33 37 35 33 37 35 +37 39 37 47 48 46 55 57 54 55 57 54 49 51 48 43 45 43 +43 45 43 43 45 43 40 43 41 40 43 41 37 39 37 33 37 35 +33 37 35 28 31 30 26 28 27 16 20 20 15 18 18 14 18 18 +14 17 17 13 16 16 12 15 15 11 14 14 12 15 15 13 17 17 +14 17 17 14 17 17 8 10 10 5 7 7 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +16 17 12 230 229 82 230 229 82 243 242 120 251 251 187 251 251 187 +246 246 123 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 66 65 55 30 32 31 32 35 33 33 37 35 +33 37 35 37 39 37 40 43 41 47 48 46 49 51 48 51 52 50 +55 57 54 55 57 54 51 52 50 47 48 46 43 45 43 39 40 39 +33 37 35 30 32 31 26 28 27 17 21 21 15 19 19 14 18 18 +14 17 17 13 16 16 12 15 15 12 14 14 11 14 14 13 16 16 +14 17 17 12 15 15 7 9 9 6 8 8 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +96 95 69 230 229 82 230 229 82 239 239 170 251 251 187 239 239 170 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 96 95 69 27 30 29 28 31 30 30 32 31 +33 37 35 40 43 41 46 47 45 55 57 54 63 64 60 72 73 67 +72 73 67 72 73 67 72 73 67 65 66 61 55 57 54 47 48 46 +39 40 39 32 35 33 27 30 29 17 21 21 15 19 19 15 18 18 +14 18 18 13 17 17 13 16 16 12 15 15 11 14 14 12 14 14 +13 16 16 9 11 11 7 9 9 9 11 11 66 65 55 115 113 82 +21 22 20 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 13 12 7 +230 229 82 230 229 82 236 236 101 251 251 187 251 251 187 246 246 123 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 118 116 76 23 27 26 26 28 27 32 35 33 +51 52 50 90 89 73 110 109 94 145 141 105 168 163 120 177 172 135 +177 172 135 188 184 146 188 184 146 181 176 137 194 191 148 188 184 146 +184 179 149 188 184 146 188 184 146 156 151 111 177 172 135 181 176 137 +177 172 135 168 163 120 168 163 120 158 153 112 156 151 111 158 153 112 +156 151 111 158 153 112 177 172 135 188 184 146 188 184 146 194 189 146 +36 38 35 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 82 81 62 +230 229 82 230 229 82 244 244 132 251 251 187 244 244 132 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 82 81 62 +96 95 69 230 229 82 181 178 103 110 109 94 156 151 111 188 184 146 +188 184 146 197 193 154 188 184 146 184 181 136 188 184 146 168 163 120 +168 163 120 178 174 128 156 151 111 158 153 112 174 170 121 156 151 111 +156 151 111 158 153 112 156 151 111 168 163 120 178 174 128 181 176 137 +176 171 126 178 174 128 184 181 136 176 171 126 178 174 128 184 181 136 +176 171 126 178 174 128 184 181 136 164 159 111 155 149 109 96 95 69 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 161 156 96 +230 229 82 230 229 82 244 244 132 244 244 132 236 236 101 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 46 47 43 82 81 62 +158 153 112 197 193 154 194 189 146 184 181 136 188 184 146 168 163 120 +156 151 111 137 133 100 131 127 93 137 133 100 137 133 100 158 153 112 +121 119 87 137 133 100 156 151 111 145 141 105 99 98 80 84 83 72 +63 64 60 52 53 49 40 43 41 33 36 34 36 38 35 36 38 35 +38 39 37 43 44 41 43 44 41 46 47 43 48 49 45 48 49 45 +46 47 43 36 38 35 30 31 28 19 20 18 6 7 7 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 36 38 35 230 229 82 +230 229 82 230 229 82 246 246 123 236 236 101 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 53 55 47 121 119 87 +176 171 126 171 165 117 161 156 96 82 81 62 53 55 47 33 37 35 +39 40 39 63 64 60 99 98 80 121 119 87 137 133 100 177 172 135 +176 171 126 184 181 136 131 127 93 131 127 93 110 109 94 84 83 72 +51 52 50 39 40 39 27 29 28 18 22 22 16 19 19 15 19 19 +15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 11 14 14 +10 13 13 9 12 12 9 11 11 8 9 9 7 9 9 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 +230 229 82 230 229 82 236 236 101 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 96 95 69 71 71 57 +36 38 35 118 116 76 118 116 76 12 15 15 15 18 18 20 24 24 +33 37 35 55 56 53 84 83 72 110 109 94 145 141 105 110 109 94 +168 163 120 121 119 87 156 151 111 131 127 93 87 86 72 61 63 57 +47 48 46 28 31 30 18 22 22 15 19 19 15 18 18 15 19 19 +15 19 19 14 18 18 14 17 17 13 17 17 13 16 16 12 15 15 +11 13 13 10 12 12 9 11 11 8 10 10 7 9 9 3 3 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 0 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +161 156 96 230 229 82 118 116 76 11 14 14 14 17 17 18 22 22 +27 30 29 40 43 41 60 60 56 84 83 72 105 104 92 110 109 94 +110 109 94 110 109 94 99 98 80 90 89 73 68 70 65 47 48 46 +32 34 33 23 25 24 20 23 23 17 21 21 15 19 19 14 17 17 +15 19 19 15 18 18 14 18 18 13 17 17 13 16 16 12 15 15 +11 14 14 10 12 12 9 11 11 8 10 10 7 9 9 4 5 5 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 16 17 12 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 11 13 13 13 16 16 15 19 19 +20 24 24 30 32 31 40 43 41 51 52 50 63 64 60 72 73 67 +65 66 61 65 66 61 65 66 61 55 57 54 46 47 45 33 37 35 +27 29 28 20 24 24 17 21 21 16 20 20 16 20 20 15 19 19 +15 19 19 15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 10 13 13 9 12 12 8 10 10 7 9 9 6 7 7 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 53 55 47 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +161 156 96 118 116 76 53 55 47 10 13 13 12 15 15 14 17 17 +17 20 20 20 24 24 27 29 28 32 34 33 37 39 37 40 43 41 +43 45 43 41 42 42 35 37 36 30 32 31 28 31 30 23 27 26 +20 23 23 17 21 21 16 20 20 16 20 20 16 20 20 16 19 19 +15 19 19 15 19 19 14 18 18 14 17 17 13 16 16 12 15 15 +11 14 14 10 13 13 9 12 12 9 11 11 8 10 10 10 12 12 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 82 81 62 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 +118 116 76 82 81 62 13 14 12 10 13 13 12 15 15 13 17 17 +15 19 19 16 20 20 20 23 23 20 24 24 23 27 26 26 28 27 +26 28 27 26 28 27 23 27 26 18 22 22 20 23 23 17 21 21 +17 21 21 16 20 20 16 20 20 16 20 20 16 20 20 16 19 19 +15 19 19 15 19 19 15 18 18 14 17 17 13 17 17 13 16 16 +12 15 15 12 14 14 12 14 14 12 14 14 12 14 14 23 24 24 +6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 118 116 76 +71 71 57 13 14 12 9 12 12 10 13 13 12 15 15 13 17 17 +15 18 18 15 19 19 16 20 20 17 21 21 17 21 21 18 22 22 +18 22 22 18 22 22 17 21 21 16 19 19 15 18 18 14 18 18 +16 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 15 19 19 15 18 18 14 18 18 16 20 20 23 25 24 +17 21 21 25 27 26 47 48 46 47 48 46 51 52 50 72 73 67 +33 36 34 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 161 156 96 118 116 76 118 116 76 46 47 43 +9 11 11 9 11 11 10 12 12 11 13 13 12 15 15 14 17 17 +15 18 18 15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +15 19 19 16 20 20 20 24 24 55 56 53 32 34 33 84 83 72 +90 89 73 110 109 94 110 109 94 105 104 92 110 109 94 110 109 94 +72 73 67 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 96 95 69 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 118 116 76 82 81 62 16 17 12 9 11 11 +9 11 11 9 12 12 10 13 13 12 14 14 13 16 16 14 18 18 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 19 19 33 36 34 99 98 80 156 151 111 145 141 105 184 179 149 +168 163 120 184 179 149 177 172 135 156 151 111 145 141 105 110 109 94 +90 89 73 2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 71 71 57 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 +230 229 82 161 156 96 230 229 82 230 229 82 230 229 82 161 156 96 +118 116 76 82 81 62 30 31 28 9 11 11 9 11 11 9 11 11 +10 12 12 10 13 13 11 14 14 13 16 16 14 17 17 15 18 18 +15 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +18 22 22 58 59 55 137 133 100 197 193 154 214 212 158 210 208 158 +197 193 154 184 179 149 184 179 149 137 133 100 110 109 94 99 98 80 +84 83 72 10 10 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 16 17 12 230 229 82 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 +161 156 96 161 156 96 161 156 96 161 156 96 118 116 76 71 71 57 +21 22 20 12 14 14 11 13 13 10 12 12 10 12 12 10 13 13 +11 13 13 12 15 15 13 16 16 14 17 17 14 18 18 15 19 19 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 17 21 21 +23 27 26 84 83 72 184 179 149 251 251 187 210 208 158 184 179 149 +184 179 149 156 151 111 110 109 94 84 83 72 63 64 60 51 52 50 +18 22 22 6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 118 116 76 230 229 82 +230 229 82 230 229 82 230 229 82 230 229 82 161 156 96 161 156 96 +161 156 96 161 156 96 118 116 76 53 55 47 20 23 22 16 19 19 +13 16 16 12 15 15 12 14 14 11 14 14 11 14 14 11 14 14 +12 15 15 13 16 16 14 17 17 15 19 19 16 20 20 17 21 21 +23 27 26 18 22 22 20 24 24 23 27 26 30 32 31 17 21 21 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +23 27 26 33 37 35 137 133 100 156 151 111 158 153 112 105 104 92 +105 104 92 68 70 65 39 40 39 18 22 22 12 14 14 12 15 15 +9 11 11 4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 16 17 12 230 229 82 +230 229 82 230 229 82 230 229 82 161 156 96 118 116 76 118 116 76 +118 116 76 66 65 55 43 45 43 32 34 33 25 27 26 20 23 22 +17 20 20 15 18 18 14 17 17 15 18 18 13 16 16 14 17 17 +14 18 18 16 20 20 32 34 33 55 57 54 58 59 55 72 73 67 +105 104 92 55 57 54 65 66 61 63 64 60 40 43 41 33 37 35 +41 42 42 20 24 24 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +17 21 21 26 28 27 30 32 31 35 37 36 68 70 65 39 40 39 +23 27 26 15 18 18 13 16 16 11 14 14 9 12 12 8 10 10 +7 9 9 6 7 7 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 38 35 +230 229 82 230 229 82 230 229 82 96 95 69 30 31 28 49 51 48 +90 89 73 68 70 65 55 57 54 47 48 46 47 48 46 43 45 43 +32 34 33 43 45 43 43 45 43 23 27 26 25 27 26 40 43 41 +40 43 41 90 89 73 110 109 94 145 141 105 156 151 111 156 151 111 +184 179 149 184 179 149 177 172 135 184 179 149 137 133 100 84 83 72 +105 104 92 63 64 60 49 51 48 47 48 46 28 31 30 18 22 22 +16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 15 19 19 15 19 19 15 19 19 18 22 22 15 19 19 +13 16 16 12 15 15 11 14 14 10 13 13 9 12 12 9 11 11 +8 10 10 6 8 8 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +30 31 28 230 229 82 71 71 57 2 2 1 0 0 0 58 59 55 +105 104 92 84 83 72 65 66 61 84 83 72 110 109 94 110 109 94 +145 141 105 105 104 92 110 109 94 110 109 94 84 83 72 110 109 94 +158 153 112 197 193 154 197 193 154 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 197 193 154 +197 193 154 184 179 149 145 141 105 137 133 100 105 104 92 47 48 46 +20 23 23 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 19 19 15 19 19 15 19 19 14 18 18 14 17 17 +13 17 17 13 16 16 12 14 14 12 14 14 13 13 13 13 13 13 +13 13 13 12 12 12 10 10 9 6 7 7 2 2 2 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 65 66 61 +105 104 92 84 83 72 84 83 72 110 109 94 184 179 149 210 208 158 +210 208 158 210 208 158 214 212 158 197 193 154 214 212 158 210 208 158 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 251 251 187 184 179 149 84 83 72 +26 28 27 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 18 18 14 18 18 +13 17 17 13 16 16 15 15 15 14 14 13 14 14 13 14 14 13 +13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 3 4 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 72 73 67 +105 104 92 99 98 80 84 83 72 99 98 80 177 172 135 197 193 154 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 214 212 158 197 193 154 99 98 80 +23 27 26 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 18 18 14 18 18 +14 17 17 16 16 16 16 16 16 16 16 16 15 15 15 14 14 13 +14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 84 83 72 +110 109 94 99 98 80 72 73 67 63 64 60 99 98 80 177 172 135 +184 179 149 210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 210 208 158 184 179 149 177 172 135 110 109 94 33 37 35 +17 21 21 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +16 20 20 16 20 20 15 19 19 15 19 19 15 19 19 14 18 18 +15 18 18 18 19 18 18 19 18 17 17 17 16 16 16 15 15 15 +14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 12 12 12 +10 10 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 105 104 92 +108 107 93 99 98 80 72 73 67 63 64 60 51 52 50 87 86 72 +105 104 92 110 109 94 108 107 93 156 151 111 184 179 149 184 179 149 +197 193 154 197 193 154 197 193 154 184 179 149 184 179 149 177 172 135 +197 193 154 156 151 111 177 172 135 184 179 149 168 163 120 137 133 100 +145 141 105 110 109 94 99 98 80 47 48 46 55 57 54 15 19 19 +16 19 19 16 20 20 16 20 20 16 20 20 16 20 20 16 20 20 +17 20 20 17 21 21 16 20 20 16 19 19 15 19 19 16 19 19 +20 20 20 21 22 21 20 20 20 19 20 19 18 19 18 16 16 16 +15 15 15 14 14 13 13 13 13 13 13 13 12 12 12 12 12 12 +12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 58 59 55 110 109 94 +105 104 92 90 89 73 72 73 67 55 57 54 43 45 43 39 40 39 +43 45 43 46 47 45 43 45 43 68 70 65 65 66 61 63 64 60 +108 107 93 72 73 67 105 104 92 90 89 73 72 73 67 40 43 41 +72 73 67 68 70 65 68 70 65 58 59 55 63 64 60 49 51 48 +43 45 43 33 36 34 27 30 29 20 24 24 16 20 20 15 19 19 +15 19 19 15 19 19 15 19 19 16 19 19 16 20 20 16 20 20 +17 21 21 20 24 24 20 23 22 17 21 21 17 20 20 20 20 20 +21 22 21 21 22 21 21 22 21 21 22 21 20 20 20 18 19 18 +16 16 16 15 15 15 13 13 13 13 13 13 12 12 12 12 12 12 +12 12 12 10 10 9 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 21 22 21 110 109 94 110 109 94 +105 104 92 84 83 72 68 70 65 51 52 50 41 42 42 33 37 35 +28 31 30 23 27 26 20 23 23 18 22 22 17 20 20 25 27 26 +26 28 27 27 30 29 25 27 26 20 23 23 23 27 26 30 32 31 +20 24 24 17 21 21 18 22 22 15 19 19 26 28 27 20 23 23 +14 18 18 15 19 19 15 18 18 15 19 19 15 19 19 15 19 19 +15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 16 19 19 +16 20 20 22 24 23 24 26 24 22 24 23 20 23 22 22 24 23 +24 26 24 24 26 24 23 24 24 22 24 23 21 22 21 19 20 19 +17 17 17 15 15 15 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 2 2 2 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 2 2 2 99 98 80 110 109 94 108 107 93 +105 104 92 84 83 72 63 64 60 49 51 48 39 40 39 32 34 33 +27 30 29 23 25 24 20 23 23 17 20 20 15 19 19 14 18 18 +14 17 17 13 17 17 13 17 17 13 17 17 13 17 17 13 17 17 +14 17 17 14 17 17 14 17 17 14 17 17 14 17 17 14 17 17 +14 18 18 14 18 18 14 18 18 14 18 18 15 18 18 15 19 19 +15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 15 19 19 +15 19 19 17 21 21 27 29 28 26 28 27 25 27 26 25 27 26 +27 29 28 27 29 28 26 28 27 24 26 24 21 22 21 20 20 20 +18 19 18 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 51 52 50 110 109 94 110 109 94 105 104 92 +90 89 73 72 73 67 55 57 54 43 45 43 35 37 36 30 32 31 +26 28 27 20 24 24 17 21 21 16 19 19 15 18 18 14 17 17 +13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 +14 17 17 14 17 17 14 17 17 14 18 18 14 18 18 14 18 18 +15 18 18 15 18 18 15 19 19 15 19 19 15 19 19 15 19 19 +15 19 19 15 19 19 27 29 28 32 34 33 28 31 30 27 29 28 +30 32 31 30 32 31 30 31 28 26 28 27 23 24 24 21 22 21 +19 20 19 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 3 3 3 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 10 10 9 108 107 93 110 109 94 108 107 93 99 98 80 +84 83 72 63 64 60 49 51 48 40 43 41 33 36 34 27 30 29 +23 27 26 18 22 22 17 20 20 15 18 18 14 17 17 13 16 16 +13 16 16 13 16 16 12 15 15 12 15 15 12 15 15 12 15 15 +13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 17 17 13 17 17 14 17 17 14 17 17 14 17 17 14 18 18 +14 18 18 14 18 18 15 18 18 15 18 18 15 19 19 15 19 19 +15 19 19 15 19 19 17 21 21 33 36 34 32 34 33 31 33 31 +33 36 34 33 36 34 31 33 31 27 29 28 25 27 26 21 22 21 +19 20 19 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 63 64 60 137 133 100 43 45 43 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 68 70 65 110 109 94 110 109 94 105 104 92 84 83 72 +68 70 65 55 57 54 43 45 43 35 37 36 30 32 31 26 28 27 +20 24 24 17 21 21 16 19 19 14 17 17 13 16 16 12 15 15 +12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 +12 15 15 12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 +13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 +14 17 17 14 17 17 14 18 18 14 18 18 14 18 18 15 18 18 +15 19 19 15 19 19 15 19 19 20 24 24 32 34 33 35 37 36 +37 39 37 35 37 36 33 36 34 30 32 31 26 28 27 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 99 98 80 184 179 149 184 179 149 68 70 65 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +15 15 15 110 109 94 110 109 94 108 107 93 99 98 80 72 73 67 +61 63 57 49 51 48 39 40 39 33 36 34 27 30 29 23 25 24 +18 22 22 16 19 19 14 17 17 13 16 16 12 15 15 12 15 15 +11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 +11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 12 15 15 +12 15 15 13 16 16 13 16 16 13 16 16 13 16 16 13 16 16 +13 17 17 14 17 17 14 17 17 14 17 17 14 18 18 14 18 18 +14 18 18 15 18 18 15 19 19 15 19 19 30 32 31 38 39 37 +39 40 39 39 40 39 35 37 36 31 33 31 27 29 28 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 +110 109 94 197 193 154 210 208 158 184 179 149 68 70 65 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +68 70 65 110 109 94 110 109 94 105 104 92 84 83 72 65 66 61 +51 52 50 43 45 43 35 37 36 30 32 31 25 27 26 20 23 23 +17 20 20 15 18 18 13 16 16 12 15 15 12 15 15 11 14 14 +11 14 14 11 14 14 11 13 13 11 13 13 11 13 13 11 13 13 +11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 11 14 14 +12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 13 16 16 +13 16 16 13 16 16 13 17 17 13 17 17 14 17 17 14 17 17 +14 18 18 14 18 18 14 18 18 16 19 19 37 39 37 41 42 42 +41 42 42 41 42 42 38 39 37 32 34 33 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 8 8 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 11 11 11 137 133 100 +197 193 154 251 251 187 239 239 170 184 179 149 31 33 31 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 12 12 12 +110 109 94 110 109 94 105 104 92 90 89 73 72 73 67 58 59 55 +46 47 45 37 39 37 31 33 31 26 28 27 20 24 24 17 21 21 +15 18 18 13 16 16 12 15 15 12 14 14 11 13 13 11 13 13 +10 13 13 10 13 13 10 13 13 10 13 13 10 13 13 10 13 13 +10 13 13 10 13 13 11 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 12 15 15 +13 16 16 13 16 16 13 16 16 13 16 16 13 17 17 13 17 17 +14 17 17 14 17 17 14 18 18 23 27 26 41 42 42 41 42 42 +43 45 43 41 42 42 39 40 39 33 36 34 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 27 29 28 168 163 120 210 208 158 +251 251 187 251 251 187 210 208 158 137 133 100 1 1 1 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 60 60 56 +110 109 94 105 104 92 105 104 92 84 83 72 65 66 61 51 52 50 +40 43 41 33 36 34 27 30 29 23 25 24 18 22 22 16 19 19 +14 17 17 12 15 15 11 14 14 11 14 14 10 13 13 10 13 13 +10 13 13 10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 +10 12 12 10 12 12 10 13 13 10 13 13 10 13 13 11 13 13 +11 13 13 11 14 14 11 14 14 11 14 14 11 14 14 12 15 15 +12 15 15 12 15 15 12 15 15 13 16 16 13 16 16 13 16 16 +13 17 17 13 17 17 14 17 17 32 34 33 43 45 43 43 45 43 +43 45 43 43 45 43 39 40 39 33 36 34 27 29 28 23 24 24 +21 22 21 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 6 7 7 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 68 70 65 184 179 149 210 208 158 251 251 187 +251 251 187 214 212 158 184 179 149 37 39 37 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 6 7 7 105 104 92 +105 104 92 105 104 92 99 98 80 72 73 67 58 59 55 46 47 45 +35 37 36 30 32 31 25 27 26 20 23 23 16 19 19 14 17 17 +12 15 15 12 14 14 11 13 13 10 13 13 10 12 12 10 12 12 +10 12 12 10 12 12 9 12 12 9 12 12 9 12 12 9 12 12 +10 12 12 10 12 12 10 12 12 10 12 12 10 12 12 10 13 13 +10 13 13 10 13 13 11 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 12 15 15 12 15 15 12 15 15 12 15 15 13 16 16 +13 16 16 13 16 16 17 20 20 41 42 42 46 47 45 46 47 45 +46 47 45 43 45 43 40 41 39 33 36 34 27 29 28 23 24 24 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 4 5 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +15 15 15 110 109 94 197 193 154 214 212 158 251 251 187 251 251 187 +239 239 170 184 179 149 84 83 72 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 47 48 46 105 104 92 +105 104 92 99 98 80 84 83 72 68 70 65 51 52 50 40 43 41 +32 34 33 27 29 28 22 24 23 17 21 21 15 18 18 13 16 16 +12 15 15 11 13 13 10 13 13 10 12 12 9 12 12 9 12 12 +9 12 12 9 12 12 9 11 11 9 11 11 9 11 11 9 11 11 +9 12 12 9 12 12 9 12 12 9 12 12 10 12 12 10 12 12 +10 12 12 10 12 12 10 13 13 10 13 13 10 13 13 11 13 13 +11 14 14 11 14 14 11 14 14 12 14 14 12 15 15 12 15 15 +12 15 15 13 16 16 28 31 30 43 45 43 47 48 46 47 48 46 +47 48 46 43 45 43 40 41 39 33 36 34 27 29 28 22 24 23 +20 20 20 17 17 17 15 15 15 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 3 4 4 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 60 60 56 +177 172 135 197 193 154 251 251 187 251 251 187 251 251 187 251 251 187 +184 179 149 110 109 94 3 4 4 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 1 1 1 99 98 80 105 104 92 +99 98 80 87 86 72 84 83 72 63 64 60 46 47 45 35 37 36 +30 32 31 25 27 26 18 22 22 16 19 19 14 17 17 12 15 15 +11 14 14 10 13 13 9 12 12 9 12 12 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 12 12 9 12 12 +9 12 12 10 12 12 10 12 12 10 12 12 10 13 13 10 13 13 +10 13 13 11 13 13 11 14 14 11 14 14 11 14 14 12 15 15 +12 15 15 14 17 17 41 42 42 47 48 46 49 51 48 51 52 50 +47 48 46 43 45 43 40 41 39 33 36 34 27 29 28 22 24 23 +19 20 19 16 16 16 14 14 13 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 2 2 2 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 23 24 24 137 133 100 184 179 149 +210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 184 179 149 +110 109 94 13 13 13 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 30 32 31 105 104 92 99 98 80 +84 83 72 84 83 72 72 73 67 55 57 54 41 42 42 32 34 33 +27 29 28 20 24 24 17 20 20 14 17 17 13 16 16 12 14 14 +10 13 13 10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 12 12 9 12 12 10 12 12 10 12 12 10 12 12 +10 13 13 10 13 13 10 13 13 11 13 13 11 14 14 11 14 14 +11 14 14 27 29 28 55 56 53 72 73 67 51 52 50 51 52 50 +49 51 48 43 45 43 39 40 39 32 34 33 26 28 27 21 22 21 +19 20 19 16 16 16 18 19 17 13 13 13 12 12 12 12 12 12 +12 12 12 12 12 12 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 8 8 7 84 83 72 184 179 149 197 193 154 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 184 179 149 145 141 105 +19 20 19 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 14 14 13 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 72 73 67 105 104 92 84 83 72 +72 73 67 84 83 72 68 70 65 49 51 48 39 40 39 30 32 31 +25 27 26 18 22 22 15 18 18 13 16 16 12 15 15 11 13 13 +10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 12 12 9 12 12 9 12 12 +10 12 12 10 12 12 10 12 12 10 13 13 10 13 13 11 13 13 +13 16 16 41 42 42 99 98 80 158 153 112 65 66 61 51 52 50 +49 51 48 43 45 43 39 40 39 31 33 31 25 27 26 21 22 21 +21 22 21 68 70 65 55 56 53 13 13 13 12 12 12 12 12 12 +12 12 12 11 11 11 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 3 3 3 +63 64 60 158 153 112 184 179 149 210 208 158 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 184 179 149 137 133 100 27 29 28 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +21 22 21 110 109 94 5 6 5 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 13 13 13 105 104 92 90 89 73 72 73 67 +68 70 65 84 83 72 63 64 60 46 47 45 35 37 36 27 29 28 +22 24 23 17 20 20 14 17 17 12 15 15 11 14 14 10 12 12 +10 12 12 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 12 12 9 12 12 10 12 12 10 12 12 10 13 13 10 13 13 +30 32 31 47 48 46 177 172 135 210 208 158 137 133 100 55 56 53 +49 51 48 43 45 43 38 39 37 31 33 31 25 27 26 22 24 23 +110 109 94 184 179 149 63 64 60 13 13 13 12 12 12 12 12 12 +12 12 12 8 9 9 0 0 0 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 21 22 21 105 104 92 +184 179 149 210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 251 251 187 184 179 149 145 141 105 23 24 24 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +68 70 65 184 179 149 105 104 92 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 51 52 50 99 98 80 84 83 72 63 64 60 +68 70 65 72 73 67 55 57 54 41 42 42 32 34 33 25 27 26 +20 23 23 16 19 19 13 16 16 12 14 14 10 13 13 10 12 12 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 12 12 9 12 12 10 12 12 17 20 20 +46 47 45 72 73 67 210 208 158 251 251 187 210 208 158 63 64 60 +49 51 48 43 45 43 37 39 37 30 32 31 24 26 24 105 104 92 +210 208 158 197 193 154 47 48 46 13 13 13 12 12 12 12 12 12 +12 12 12 6 7 7 33 36 34 48 49 45 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 8 8 7 23 24 24 55 56 53 110 109 94 +210 208 158 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 184 179 149 110 109 94 20 20 20 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +110 109 94 251 251 187 210 208 158 47 48 46 0 0 0 0 0 0 +0 0 0 1 1 1 90 89 73 90 89 73 72 73 67 55 56 53 +72 73 67 68 70 65 51 52 50 37 39 37 28 31 30 23 25 24 +17 21 21 15 18 18 12 15 15 11 14 14 10 13 13 9 12 12 +9 11 11 9 11 11 9 11 11 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 11 11 9 11 11 9 11 11 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 9 12 12 13 16 16 41 42 42 +49 51 48 110 109 94 251 251 187 251 251 187 251 251 187 105 104 92 +49 51 48 43 45 43 35 37 36 30 31 28 47 48 46 197 193 154 +251 251 187 197 193 154 31 33 31 12 12 12 12 12 12 12 12 12 +12 12 12 51 52 50 184 179 149 72 73 67 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 2 +11 11 11 21 22 21 30 32 31 40 41 39 60 60 56 145 141 105 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +184 179 149 110 109 94 13 13 13 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 4 5 4 61 61 53 48 49 45 3 4 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +156 151 111 251 251 187 251 251 187 184 179 149 11 11 11 0 0 0 +0 0 0 26 28 27 99 98 80 84 83 72 60 60 56 43 45 43 +72 73 67 65 66 61 49 51 48 35 37 36 27 29 28 20 24 24 +17 20 20 14 17 17 12 15 15 11 13 13 10 12 12 9 11 11 +9 11 11 9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 9 11 11 9 11 11 +9 11 11 9 11 11 9 11 11 11 13 13 37 39 37 47 48 46 +51 52 50 184 179 149 251 251 187 251 251 187 251 251 187 145 141 105 +47 48 46 41 42 42 35 37 36 27 29 28 137 133 100 251 251 187 +251 251 187 197 193 154 19 20 19 12 12 12 12 12 12 12 12 12 +27 29 28 184 179 149 214 212 158 63 64 60 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 6 7 7 16 16 16 24 26 24 +30 32 31 38 39 37 47 48 46 55 57 54 68 70 65 110 109 94 +197 193 154 251 251 187 251 251 187 251 251 187 210 208 158 184 179 149 +105 104 92 8 8 7 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 65 66 61 184 179 149 156 151 111 +30 32 31 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +168 163 120 251 251 187 251 251 187 251 251 187 110 109 94 0 0 0 +0 0 0 60 60 56 84 83 72 68 70 65 51 52 50 38 39 37 +84 83 72 63 64 60 43 45 43 33 36 34 25 27 26 20 23 22 +15 18 18 13 16 16 12 14 14 10 13 13 9 12 12 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +9 11 11 9 11 11 10 12 12 33 36 34 46 47 45 51 52 50 +72 73 67 210 208 158 251 251 187 251 251 187 251 251 187 177 172 135 +47 48 46 41 42 42 35 37 36 37 39 37 184 179 149 251 251 187 +251 251 187 197 193 154 13 13 13 12 12 12 12 12 12 12 12 12 +110 109 94 251 251 187 251 251 187 37 39 37 0 0 0 0 0 0 +0 0 0 21 22 20 2 2 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +4 5 5 12 12 12 21 22 21 25 27 26 30 32 31 38 39 37 +46 47 45 55 56 53 60 60 56 65 66 61 68 70 65 105 104 92 +110 109 94 197 193 154 210 208 158 197 193 154 184 179 149 84 83 72 +2 2 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 13 13 13 184 179 149 251 251 187 +197 193 154 43 44 41 0 0 0 0 0 0 0 0 0 0 0 0 +145 141 105 251 251 187 251 251 187 251 251 187 214 212 158 43 45 43 +2 2 2 84 83 72 72 73 67 58 59 55 41 42 42 38 39 37 +72 73 67 58 59 55 41 42 42 31 33 31 25 27 26 18 22 22 +14 17 17 12 15 15 12 14 14 10 12 12 9 12 12 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 9 12 12 31 33 31 43 45 43 49 51 48 55 56 53 +110 109 94 251 251 187 251 251 187 251 251 187 251 251 187 168 163 120 +47 48 46 41 42 42 33 36 34 63 64 60 197 193 154 251 251 187 +251 251 187 184 179 149 13 13 13 12 12 12 12 12 12 16 16 16 +197 193 154 251 251 187 239 239 170 20 20 20 0 0 0 2 2 1 +108 107 93 110 109 94 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 4 5 5 11 11 11 18 19 18 +22 24 23 26 28 27 32 34 33 39 40 39 46 47 45 51 52 50 +55 57 54 60 60 56 63 64 60 63 64 60 63 64 60 58 59 55 +63 64 60 99 98 80 145 141 105 137 133 100 43 45 43 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 3 4 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 110 109 94 251 251 187 +251 251 187 184 179 149 25 27 26 0 0 0 0 0 0 0 0 0 +99 98 80 251 251 187 251 251 187 251 251 187 251 251 187 156 151 111 +25 27 26 84 83 72 65 66 61 47 48 46 32 34 33 39 40 39 +72 73 67 55 57 54 40 41 39 30 32 31 23 25 24 18 22 22 +14 17 17 12 15 15 11 13 13 10 12 12 9 11 11 9 11 11 +9 11 11 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +9 11 11 28 31 30 41 42 42 47 48 46 55 56 53 58 59 55 +137 133 100 251 251 187 251 251 187 251 251 187 210 208 158 137 133 100 +47 48 46 40 41 39 32 34 33 75 75 61 184 179 149 239 239 170 +251 251 187 177 172 135 13 13 13 12 12 12 12 12 12 43 44 41 +197 193 154 251 251 187 210 208 158 10 10 9 0 0 0 84 83 72 +251 251 187 84 83 72 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +6 7 7 11 11 11 17 17 17 20 20 20 23 24 24 27 29 28 +32 34 33 38 39 37 43 45 43 47 48 46 51 52 50 55 56 53 +58 59 55 58 59 55 55 57 54 55 56 53 47 48 46 41 42 42 +35 37 36 31 33 31 47 48 46 14 14 13 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 66 65 55 99 98 80 20 20 20 +0 0 0 0 0 0 0 0 0 0 0 0 43 45 43 214 212 158 +251 251 187 251 251 187 145 141 105 3 3 3 0 0 0 0 0 0 +48 49 45 184 179 149 239 239 170 251 251 187 239 239 170 177 172 135 +84 83 72 72 73 67 55 56 53 39 40 39 26 28 27 39 40 39 +68 70 65 51 52 50 39 40 39 28 31 30 22 24 23 17 20 20 +14 17 17 12 14 14 10 13 13 9 11 11 9 11 11 9 11 11 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +27 29 28 40 41 39 46 47 45 51 52 50 55 57 54 63 64 60 +131 127 93 197 193 154 210 208 158 197 193 154 168 163 120 96 95 69 +47 48 46 40 41 39 32 34 33 71 71 57 145 141 105 184 179 149 +184 179 149 131 127 93 13 13 13 12 12 12 12 12 12 48 49 45 +168 163 120 184 179 149 156 151 111 6 7 7 14 14 13 177 172 135 +239 239 170 40 41 39 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 3 3 3 6 7 7 11 11 11 16 16 16 +18 19 18 21 22 21 23 24 24 27 29 28 32 34 33 37 39 37 +41 42 42 43 45 43 47 48 46 51 52 50 51 52 50 51 52 50 +51 52 50 49 51 48 46 47 45 40 41 39 32 34 33 25 27 26 +20 20 20 14 14 13 2 2 2 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 33 36 34 197 193 154 184 179 149 +41 42 42 0 0 0 0 0 0 0 0 0 3 3 3 184 179 149 +251 251 187 251 251 187 184 179 149 48 49 45 0 0 0 0 0 0 +16 17 12 121 119 87 177 172 135 194 189 146 188 184 146 145 141 105 +82 81 62 63 64 60 46 47 45 31 33 31 21 22 21 35 37 36 +68 70 65 51 52 50 37 39 37 27 30 29 22 24 23 17 20 20 +13 16 16 12 14 14 10 13 13 9 11 11 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 25 27 26 +38 39 37 43 45 43 51 52 50 55 56 53 60 60 56 63 64 60 +92 91 72 158 153 112 176 171 126 171 165 117 149 143 98 82 81 62 +44 46 43 38 39 37 30 32 31 71 71 57 131 127 93 160 154 106 +149 143 98 82 81 62 13 13 13 12 12 12 12 12 12 46 47 43 +121 119 87 134 131 96 96 95 69 7 7 6 38 39 37 131 127 93 +145 141 105 12 13 12 0 0 0 1 1 1 3 3 3 6 7 7 +10 10 9 12 12 12 14 14 13 16 16 16 18 19 18 21 22 21 +22 24 23 26 28 27 30 31 28 33 36 34 37 39 37 40 41 39 +41 42 42 43 45 43 46 47 45 46 47 45 46 47 45 43 45 43 +41 42 42 37 39 37 31 33 31 26 28 27 21 22 21 16 16 16 +6 7 7 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 177 172 135 251 251 187 +197 193 154 27 29 28 0 0 0 0 0 0 0 0 0 110 109 94 +239 239 170 239 239 170 184 179 149 87 86 72 2 2 1 0 0 0 +1 1 1 82 81 62 142 137 94 165 161 109 165 161 109 131 127 93 +75 75 61 55 56 53 37 39 37 25 27 26 19 20 19 32 34 33 +65 66 61 49 51 48 35 37 36 27 29 28 20 23 23 16 19 19 +13 16 16 13 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +8 9 9 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 22 24 23 35 37 36 +41 42 42 47 48 46 55 56 53 58 59 55 63 64 60 65 66 61 +71 71 57 131 127 93 160 154 106 160 154 106 142 137 94 82 81 62 +46 47 43 40 41 39 33 36 34 66 65 55 125 122 87 149 143 98 +142 137 94 82 81 62 17 17 17 18 19 17 14 14 13 46 47 43 +118 116 76 125 122 87 96 95 69 16 17 12 71 71 57 103 101 77 +82 81 62 11 11 11 11 11 11 13 13 13 14 14 13 14 14 13 +15 15 15 16 16 16 17 17 17 19 20 19 21 22 21 23 24 24 +26 28 27 27 29 28 31 33 31 33 36 34 35 37 36 38 39 37 +39 40 39 39 40 39 38 39 37 37 39 37 35 37 36 31 33 31 +27 29 28 24 26 24 21 22 21 17 17 17 12 12 12 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 68 70 65 251 251 187 +251 251 187 156 151 111 2 2 1 0 0 0 0 0 0 43 44 41 +177 172 135 184 179 149 158 153 112 103 101 77 19 20 18 0 0 0 +0 0 0 46 47 43 131 127 93 160 154 106 160 154 106 131 127 93 +71 71 57 43 45 43 30 32 31 21 22 21 16 16 16 26 28 27 +63 64 60 47 48 46 35 37 36 26 28 27 20 23 23 16 19 19 +13 16 16 13 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +7 9 9 7 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 20 20 20 33 36 34 40 41 39 +46 47 45 51 52 50 55 57 54 60 60 56 63 64 60 65 66 61 +66 65 55 118 116 76 151 147 98 165 161 109 151 147 98 121 119 87 +96 95 69 96 95 69 96 95 69 103 101 77 142 137 94 151 147 98 +142 137 94 103 101 77 82 81 62 82 81 62 82 81 62 96 95 69 +131 127 93 142 137 94 103 101 77 46 47 43 96 95 69 118 116 76 +71 71 57 14 14 13 14 14 13 15 15 15 15 15 15 16 16 16 +16 16 16 17 17 17 18 19 18 20 20 20 21 22 21 23 24 24 +25 27 26 27 29 28 30 31 28 30 32 31 31 33 31 31 33 31 +31 33 31 31 33 31 30 31 28 27 29 28 25 27 26 22 24 23 +20 20 20 16 16 16 13 13 13 6 7 7 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +58 59 55 68 70 65 8 8 7 0 0 0 10 10 9 210 208 158 +251 251 187 184 179 149 38 39 37 0 0 0 0 0 0 8 8 7 +103 101 77 149 143 98 149 143 98 118 116 76 40 41 39 25 27 25 +53 55 47 82 81 62 144 139 99 165 161 109 165 161 109 142 137 94 +71 71 57 35 37 36 24 26 24 18 19 18 15 15 15 22 24 23 +63 64 60 46 47 45 33 36 34 26 28 27 20 23 22 17 18 17 +12 15 15 11 13 13 10 12 12 9 11 11 8 10 10 8 10 10 +7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 16 16 16 30 31 28 35 37 36 41 42 42 +47 48 46 55 56 53 58 59 55 63 64 60 65 66 61 65 66 61 +61 61 53 103 101 77 151 147 98 171 165 117 171 165 117 168 163 120 +158 153 112 158 153 112 155 149 109 151 147 98 151 147 98 160 154 106 +151 147 98 149 143 98 142 137 94 149 143 98 149 143 98 149 143 98 +155 149 109 151 147 98 131 127 93 103 101 77 125 122 87 118 116 76 +71 71 57 16 16 16 16 16 16 16 16 16 17 17 17 17 17 17 +17 17 17 17 17 17 18 19 18 19 20 19 20 20 20 21 22 21 +23 24 24 24 26 24 25 27 26 26 28 27 26 28 27 26 28 27 +25 27 26 24 26 24 22 24 23 21 22 21 19 20 19 16 16 16 +14 14 13 8 8 7 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +20 20 20 184 179 149 168 163 120 21 22 21 0 0 0 105 104 92 +177 172 135 145 141 105 71 71 57 0 0 0 0 0 0 0 0 0 +66 65 55 131 127 93 151 147 98 142 137 94 118 116 76 121 119 87 +145 141 105 158 153 112 176 171 126 178 174 128 176 171 126 149 145 103 +96 95 69 31 33 31 21 22 21 16 16 16 14 14 13 18 19 18 +60 60 56 46 47 45 33 36 34 25 27 26 21 22 21 15 18 18 +12 15 15 11 13 13 9 11 11 8 10 10 8 10 10 8 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 +8 9 9 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 10 12 12 26 28 27 31 33 31 38 39 37 43 45 43 +51 52 50 55 56 53 60 60 56 63 64 60 65 66 61 68 70 65 +63 64 60 96 95 69 158 153 112 178 174 128 188 184 146 194 189 146 +194 189 146 188 184 146 184 181 136 176 171 126 171 165 117 173 167 111 +173 167 111 165 161 109 171 165 117 174 170 121 176 171 126 178 174 128 +178 174 128 174 170 121 160 154 106 149 143 98 149 143 98 125 122 87 +71 71 57 16 16 16 16 16 16 17 17 17 17 17 17 17 17 17 +17 17 17 17 17 17 17 17 17 18 19 18 19 20 19 20 20 20 +21 22 21 21 22 21 21 22 21 22 24 23 21 22 21 21 22 21 +21 22 21 19 20 19 18 19 18 16 16 16 14 14 13 11 11 11 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 105 104 92 197 193 154 110 109 94 9 9 8 36 38 35 +121 119 87 131 127 93 96 95 69 18 19 17 30 31 28 66 65 55 +96 95 69 142 137 94 160 154 106 160 154 106 160 154 106 168 163 120 +184 181 136 194 191 148 197 193 154 197 193 154 194 189 146 168 163 120 +125 122 87 46 47 43 18 19 18 15 15 15 13 13 13 14 14 13 +55 57 54 43 45 43 32 34 33 25 27 26 18 22 22 17 17 17 +12 14 14 10 12 12 9 11 11 8 10 10 8 9 9 7 9 9 +6 8 8 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 8 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 32 34 33 41 42 42 35 37 36 39 40 39 37 39 37 +35 37 36 55 57 54 60 60 56 63 64 60 65 66 61 65 66 61 +61 63 57 115 113 82 168 163 120 194 191 148 204 201 155 210 208 158 +210 208 158 210 208 158 197 193 154 194 189 146 186 182 128 176 171 126 +174 170 121 176 171 126 186 182 128 190 186 136 194 191 148 197 193 154 +197 193 154 188 184 146 181 176 137 174 170 121 165 161 109 142 137 94 +82 81 62 24 26 24 16 16 16 16 16 16 16 16 16 16 16 16 +17 17 17 17 17 17 17 17 17 17 17 17 18 19 18 19 20 19 +19 20 19 19 20 19 20 20 20 19 20 19 19 20 19 18 19 18 +17 17 17 15 15 15 13 13 13 12 12 12 6 7 7 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 17 18 17 137 133 100 115 113 82 53 55 47 19 20 18 +103 101 77 144 139 99 137 133 100 115 113 82 137 133 100 156 151 111 +158 153 112 164 159 111 171 165 117 174 170 121 178 174 128 194 189 146 +204 201 155 214 212 158 214 212 158 214 212 158 210 208 158 188 184 146 +158 153 112 87 86 72 17 17 17 13 13 13 13 13 13 15 15 15 +55 56 53 43 45 43 32 34 33 24 26 24 17 20 20 16 16 16 +12 14 14 10 12 12 8 10 10 8 10 10 7 9 9 6 8 8 +6 8 8 6 8 8 6 8 8 7 9 9 7 9 9 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 8 9 9 8 10 10 +8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 8 10 10 +8 10 10 110 109 94 84 83 72 49 51 48 26 28 27 8 10 10 +8 9 9 51 52 50 58 59 55 63 64 60 63 64 60 63 64 60 +66 65 55 134 131 96 181 176 137 210 208 158 214 212 158 239 239 170 +239 239 170 224 223 159 210 208 158 204 201 155 194 189 146 186 182 128 +186 182 128 184 181 136 194 189 146 204 201 155 210 208 158 210 208 158 +210 208 158 210 208 158 197 193 154 190 186 136 176 171 126 155 149 109 +118 116 76 36 38 35 15 15 15 16 16 16 16 16 16 16 16 16 +16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 17 17 17 +17 17 17 17 17 17 17 17 17 16 16 16 16 16 16 15 15 15 +13 13 13 12 12 12 8 8 7 2 2 2 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 53 55 47 103 101 77 96 95 69 53 55 47 +103 101 77 158 153 112 177 172 135 184 179 149 188 184 146 197 193 154 +194 189 146 190 186 136 184 181 136 184 181 136 194 189 146 210 208 158 +214 212 158 239 239 170 251 251 187 251 251 187 224 223 159 204 201 155 +177 172 135 121 119 87 30 31 28 13 13 13 12 12 12 39 40 39 +60 60 56 43 45 43 32 34 33 23 25 24 18 19 18 13 16 16 +13 13 13 9 11 11 8 10 10 8 9 9 6 8 8 6 8 8 +6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 8 9 9 8 9 9 8 10 10 8 10 10 8 10 10 +14 17 17 197 193 154 158 153 112 55 57 54 7 9 9 7 9 9 +8 10 10 51 52 50 58 59 55 60 60 56 63 64 60 63 64 60 +71 71 57 155 149 109 194 191 148 214 212 158 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 197 193 154 190 186 136 +190 186 136 194 189 146 204 201 155 210 208 158 224 223 159 239 239 170 +239 239 170 224 223 159 210 208 158 204 201 155 190 186 136 164 159 111 +125 122 87 40 41 39 15 15 15 15 15 15 15 15 15 15 15 15 +16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 16 +16 16 16 16 16 16 15 15 15 14 14 13 13 13 13 12 12 12 +8 9 9 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 21 22 20 96 95 69 125 122 87 121 119 87 +144 139 99 177 172 135 197 193 154 210 208 158 214 212 158 214 212 158 +210 208 158 204 201 155 194 191 148 194 189 146 204 201 155 214 212 158 +239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +188 184 146 145 141 105 53 55 47 12 12 12 15 15 15 63 64 60 +63 64 60 41 42 42 31 33 31 23 24 24 17 18 17 12 15 15 +11 13 13 9 11 11 8 9 9 7 9 9 6 8 8 6 8 8 +6 7 7 6 7 7 6 8 8 6 8 8 6 8 8 6 8 8 +6 8 8 7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 +7 9 9 7 9 9 7 9 9 7 9 9 7 9 9 8 8 7 +43 45 43 251 251 187 156 151 111 8 10 10 7 9 9 7 9 9 +21 22 21 51 52 50 55 56 53 55 57 54 58 59 55 58 59 55 +75 75 61 158 153 112 197 193 154 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 214 212 158 204 201 155 194 189 146 +190 186 136 197 193 154 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 197 193 154 176 171 126 +125 122 87 36 38 35 14 14 13 14 14 13 15 15 15 15 15 15 +15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 15 +15 15 15 14 14 13 13 13 13 12 12 12 10 10 9 3 4 4 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 7 7 5 71 71 57 131 127 93 158 153 112 +177 172 135 197 193 154 214 212 158 239 239 170 251 251 187 251 251 187 +238 237 168 210 208 158 204 201 155 197 193 154 204 201 155 214 212 158 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 214 212 158 +197 193 154 156 151 111 66 65 55 12 12 12 37 39 37 58 59 55 +58 59 55 41 42 42 31 33 31 22 24 23 17 17 17 12 14 14 +10 12 12 8 10 10 6 8 8 6 8 8 6 7 7 6 7 7 +6 7 7 5 7 7 6 7 7 6 7 7 6 8 8 6 8 8 +6 8 8 6 8 8 6 8 8 7 9 9 7 9 9 7 9 9 +7 9 9 6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 +61 63 57 197 193 154 16 19 19 6 8 8 6 8 8 8 9 9 +41 42 42 47 48 46 51 52 50 51 52 50 55 56 53 55 56 53 +71 71 57 158 153 112 197 193 154 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 239 239 170 214 212 158 204 201 155 194 189 146 +190 186 136 197 193 154 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 224 223 159 204 201 155 177 172 135 +121 119 87 30 31 28 13 13 13 14 14 13 14 14 13 14 14 13 +14 14 13 14 14 13 15 15 15 15 15 15 14 14 13 13 13 13 +12 12 12 12 12 12 10 10 9 4 5 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 48 49 45 131 127 93 174 170 121 +194 189 146 210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 204 201 155 197 193 154 204 201 155 210 208 158 +239 239 170 251 251 187 251 251 187 251 251 187 239 239 170 214 212 158 +194 191 148 156 151 111 71 71 57 19 20 19 51 52 50 51 52 50 +51 52 50 41 42 42 30 32 31 21 22 21 17 17 17 13 13 13 +9 11 11 8 9 9 6 8 8 6 7 7 6 7 7 5 7 7 +5 6 5 5 6 5 5 7 7 5 7 7 6 7 7 6 7 7 +6 8 8 6 8 8 6 8 8 6 7 7 6 7 7 6 7 7 +6 7 7 6 8 8 6 8 8 6 8 8 6 8 8 6 8 8 +55 56 53 43 45 43 6 8 8 6 8 8 6 8 8 47 48 46 +60 60 56 47 48 46 46 47 45 47 48 46 38 39 37 10 12 12 +66 65 55 145 141 105 197 193 154 214 212 158 251 251 187 251 251 187 +251 251 187 251 251 187 224 223 159 210 208 158 194 191 148 184 181 136 +184 181 136 194 189 146 204 201 155 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 181 176 137 +115 113 82 21 22 20 13 13 13 13 13 13 13 13 13 13 13 13 +14 14 13 13 13 13 13 13 13 13 13 13 12 12 12 11 11 11 +10 10 9 6 7 7 1 1 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 2 2 1 66 65 55 144 139 99 178 174 128 +204 201 155 214 212 158 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 204 201 155 194 191 148 197 193 154 204 201 155 +214 212 158 239 239 170 239 239 170 239 239 170 214 212 158 210 208 158 +184 181 136 149 145 103 66 65 55 41 42 42 47 48 46 46 47 45 +43 45 43 39 40 39 28 31 30 21 22 21 16 16 16 10 12 12 +8 10 10 6 8 8 6 7 7 6 7 7 5 6 5 5 6 5 +5 6 5 5 6 5 5 6 5 5 6 5 5 7 7 5 7 7 +6 7 7 6 7 7 6 7 7 5 7 7 5 7 7 5 7 7 +5 7 7 6 7 7 6 7 7 6 7 7 6 7 7 6 8 8 +6 8 8 6 8 8 6 7 7 6 7 7 46 47 45 156 151 111 +105 104 92 58 59 55 43 45 43 32 34 33 6 8 8 6 8 8 +49 51 48 125 122 87 181 176 137 204 201 155 214 212 158 239 239 170 +239 239 170 214 212 158 210 208 158 197 193 154 181 176 137 176 171 126 +176 171 126 184 181 136 197 193 154 210 208 158 239 239 170 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 177 172 135 +99 98 80 13 13 13 12 12 12 12 12 12 13 13 13 12 12 12 +12 12 12 12 12 12 11 11 11 11 11 11 8 9 9 4 5 5 +1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 1 1 0 61 61 53 142 137 94 181 176 137 +204 201 155 224 223 159 251 251 187 251 251 187 251 251 187 251 251 187 +251 251 187 214 212 158 197 193 154 190 186 136 184 181 136 188 184 146 +197 193 154 204 201 155 210 208 158 210 208 158 204 201 155 194 189 146 +176 171 126 134 131 96 66 65 55 43 45 43 41 42 42 39 40 39 +35 37 36 33 36 34 27 29 28 20 20 20 15 15 15 9 11 11 +8 9 9 6 7 7 5 6 5 5 6 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 5 6 5 4 5 5 +4 5 5 5 6 5 4 5 5 5 6 5 5 6 5 5 6 5 +5 7 7 5 7 7 5 7 7 5 7 7 5 7 7 5 7 7 +6 7 7 6 7 7 6 7 7 28 31 30 184 179 149 184 179 149 +145 141 105 84 83 72 27 29 28 5 7 7 5 6 5 16 16 16 +43 44 41 96 95 69 158 153 112 188 184 146 204 201 155 210 208 158 +204 201 155 197 193 154 184 179 149 177 172 135 168 163 120 164 159 111 +164 159 111 174 170 121 184 181 136 197 193 154 214 212 158 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 210 208 158 177 172 135 +71 71 57 11 11 11 12 12 12 11 11 11 11 11 11 11 11 11 +10 10 9 10 10 9 8 8 7 3 4 4 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 31 33 31 121 119 87 176 171 126 +197 193 154 214 212 158 251 251 187 251 251 187 251 251 187 251 251 187 +239 239 170 210 208 158 194 189 146 178 174 128 174 170 121 176 171 126 +177 172 135 181 176 137 184 179 149 184 179 149 181 176 137 178 174 128 +158 153 112 121 119 87 53 55 47 37 39 37 33 36 34 30 32 31 +27 29 28 25 27 26 24 26 24 19 20 19 13 13 13 8 10 10 +6 8 8 6 7 7 5 6 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 3 4 4 3 4 4 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +5 6 5 5 6 5 5 6 5 5 6 5 5 6 5 5 6 5 +5 6 5 5 6 5 12 14 14 145 141 105 184 179 149 177 172 135 +90 89 73 21 22 21 5 6 5 5 6 5 4 5 5 37 39 37 +38 39 37 61 61 53 134 131 96 168 163 120 184 181 136 188 184 146 +184 179 149 177 172 135 168 163 120 164 159 111 155 149 109 151 147 98 +151 147 98 164 159 111 176 171 126 184 179 149 210 208 158 239 239 170 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 158 153 112 +46 47 43 10 10 9 10 10 9 10 10 9 8 9 9 8 9 9 +6 7 7 3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 13 12 7 82 81 62 158 153 112 +188 184 146 210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 +224 223 159 204 201 155 184 181 136 171 165 117 164 159 111 160 154 106 +158 153 112 164 159 111 168 163 120 168 163 120 168 163 120 164 159 111 +142 137 94 96 95 69 43 44 41 27 29 28 26 28 27 23 24 24 +21 22 21 18 19 18 17 17 17 18 19 18 13 13 13 8 8 7 +6 7 7 5 6 5 4 5 5 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 3 3 3 3 3 3 4 4 3 4 4 +3 4 4 3 4 4 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 4 5 5 4 5 5 4 5 5 31 33 31 65 66 61 +37 39 37 38 39 37 96 95 69 144 139 99 168 163 120 174 170 121 +168 163 120 164 159 111 155 149 109 149 145 103 149 143 98 142 137 94 +149 143 98 151 147 98 164 159 111 177 172 135 197 193 154 210 208 158 +251 251 187 251 251 187 251 251 187 239 239 170 197 193 154 137 133 100 +24 26 24 8 9 9 8 9 9 8 8 7 6 7 7 2 2 2 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 46 47 43 125 122 87 +176 171 126 197 193 154 210 208 158 239 239 170 251 251 187 239 239 170 +214 212 158 197 193 154 181 176 137 164 159 111 151 147 98 149 143 98 +149 143 98 149 143 98 149 145 103 155 149 109 160 154 106 149 143 98 +118 116 76 82 81 62 30 31 28 21 22 21 19 20 19 17 17 17 +14 14 13 12 12 12 10 10 9 12 12 12 10 12 12 6 8 8 +4 5 5 3 4 4 3 4 4 3 4 4 3 3 3 3 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 2 3 3 2 3 3 +3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 4 5 5 +4 5 5 3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 +4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 4 5 5 +4 5 5 3 4 4 3 4 4 23 24 24 110 109 94 72 73 67 +39 40 39 22 24 23 46 47 43 103 101 77 142 137 94 155 149 109 +160 154 106 155 149 109 149 143 98 142 137 94 142 137 94 142 137 94 +142 137 94 149 143 98 155 149 109 176 171 126 184 179 149 210 208 158 +239 239 170 251 251 187 251 251 187 214 212 158 184 179 149 105 104 92 +10 10 9 6 7 7 3 4 4 1 1 1 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 12 12 9 82 81 62 +149 145 103 181 176 137 197 193 154 210 208 158 214 212 158 214 212 158 +210 208 158 197 193 154 177 172 135 158 153 112 149 143 98 142 137 94 +142 137 94 142 137 94 149 143 98 151 147 98 151 147 98 131 127 93 +103 101 77 71 71 57 22 24 23 15 15 15 13 13 13 11 11 11 +8 9 9 6 7 7 6 7 7 4 5 5 8 9 9 6 7 7 +4 5 5 3 3 3 3 3 3 3 3 3 3 3 3 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 +2 3 3 2 3 3 2 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 21 22 21 145 141 105 145 141 105 72 73 67 +17 18 17 3 4 4 21 22 20 66 65 55 118 116 76 142 137 94 +149 143 98 151 147 98 149 143 98 142 137 94 142 137 94 142 137 94 +142 137 94 149 143 98 155 149 109 168 163 120 184 179 149 210 208 158 +239 239 170 251 251 187 251 251 187 210 208 158 177 172 135 71 71 57 +3 3 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 36 38 35 +115 113 82 158 153 112 181 176 137 197 193 154 204 201 155 210 208 158 +204 201 155 188 184 146 177 172 135 164 159 111 149 145 103 142 137 94 +142 137 94 142 137 94 149 143 98 151 147 98 149 143 98 125 122 87 +96 95 69 61 61 53 16 17 12 8 9 9 8 8 7 6 7 7 +4 5 5 3 4 4 3 3 3 3 3 3 3 3 3 5 6 5 +3 4 4 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 2 2 +2 2 2 2 2 2 2 3 3 2 3 3 2 3 3 2 3 3 +3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 +3 3 3 2 3 3 2 3 3 3 4 4 3 4 4 3 4 4 +3 4 4 3 4 4 3 4 4 8 9 9 8 8 7 3 3 3 +3 3 3 3 3 3 9 9 8 36 38 35 82 81 62 118 116 76 +142 137 94 151 147 98 151 147 98 151 147 98 149 143 98 149 143 98 +149 143 98 151 147 98 160 154 106 176 171 126 188 184 146 210 208 158 +239 239 170 251 251 187 239 239 170 210 208 158 156 151 111 31 33 31 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 7 5 +66 65 55 125 122 87 158 153 112 181 176 137 194 189 146 197 193 154 +197 193 154 184 179 149 177 172 135 168 163 120 156 151 111 151 147 98 +151 147 98 151 147 98 151 147 98 161 156 96 149 143 98 118 116 76 +82 81 62 53 55 47 12 12 9 4 5 5 3 4 4 3 3 3 +3 3 3 3 3 3 2 2 2 2 2 2 1 1 1 1 2 2 +3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 2 2 2 2 2 2 2 3 3 +2 3 3 2 3 3 2 3 3 2 3 3 2 2 2 2 2 2 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 3 3 3 +3 3 3 3 3 3 72 73 67 61 61 53 53 55 47 96 95 69 +131 127 93 151 147 98 161 156 96 161 156 96 151 147 98 151 147 98 +161 156 96 160 154 106 164 159 111 177 172 135 197 193 154 210 208 158 +239 239 170 251 251 187 224 223 159 197 193 154 131 127 93 9 9 8 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +24 26 24 82 81 62 131 127 93 164 159 111 178 174 128 188 184 146 +188 184 146 188 184 146 181 176 137 176 171 126 168 163 120 164 159 111 +160 154 106 160 154 106 160 154 106 160 154 106 151 147 98 125 122 87 +82 81 62 61 61 53 12 12 9 3 3 3 3 3 3 2 2 2 +2 2 2 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 +0 0 0 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 2 2 1 2 2 1 2 2 1 2 2 +1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 2 3 3 +2 3 3 30 32 31 72 73 67 31 33 31 36 38 35 82 81 62 +118 116 76 149 143 98 161 156 96 161 156 96 161 156 96 160 154 106 +165 161 109 165 161 109 176 171 126 188 184 146 204 201 155 214 212 158 +239 239 170 239 239 170 214 212 158 184 179 149 82 81 62 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +2 2 2 43 44 41 96 95 69 131 127 93 160 154 106 176 171 126 +184 181 136 184 181 136 184 181 136 181 176 137 178 174 128 174 170 121 +171 165 117 173 167 111 173 167 111 173 167 111 160 154 106 131 127 93 +96 95 69 66 65 55 16 17 12 2 2 2 1 1 1 1 1 1 +1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 10 9 6 30 31 28 71 71 57 +118 116 76 149 143 98 165 161 109 165 161 109 165 161 109 173 167 111 +173 167 111 176 171 126 184 181 136 197 193 154 210 208 158 224 223 159 +251 251 187 239 239 170 210 208 158 168 163 120 40 41 39 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 13 12 7 61 61 53 96 95 69 131 127 93 160 154 106 +176 171 126 184 181 136 184 181 136 188 184 146 184 181 136 184 181 136 +184 181 136 186 182 128 186 182 128 178 174 128 174 170 121 149 145 103 +118 116 76 82 81 62 21 22 20 1 1 1 1 1 1 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 +2 2 2 2 2 2 2 2 2 3 3 3 30 31 28 66 65 55 +118 116 76 149 143 98 165 161 109 173 167 111 173 167 111 174 170 121 +186 182 128 190 186 136 197 193 154 210 208 158 224 223 159 251 251 187 +251 251 187 239 239 170 197 193 154 137 133 100 12 12 9 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 30 31 28 71 71 57 103 101 77 134 131 96 +164 159 111 176 171 126 184 181 136 188 184 146 194 189 146 197 193 154 +197 193 154 197 193 154 194 191 148 194 189 146 190 186 136 176 171 126 +145 141 105 103 101 77 40 41 39 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 1 2 2 +1 2 2 1 2 2 1 2 2 1 2 2 30 31 28 71 71 57 +118 116 76 160 154 106 173 167 111 178 174 128 186 182 128 190 186 136 +194 191 148 204 201 155 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 214 212 158 184 179 149 84 83 72 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 5 5 3 43 44 41 82 81 62 103 101 77 +142 137 94 165 161 109 178 174 128 190 186 136 197 193 154 204 201 155 +210 208 158 210 208 158 210 208 158 210 208 158 210 208 158 197 193 154 +177 172 135 145 141 105 79 78 62 5 4 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 2 2 1 2 2 30 31 28 82 81 62 +142 137 94 165 161 109 178 174 128 190 186 136 194 191 148 204 201 155 +210 208 158 214 212 158 239 239 170 251 251 187 251 251 187 251 251 187 +251 251 187 210 208 158 168 163 120 36 38 35 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 16 17 12 53 55 47 82 81 62 +118 116 76 151 147 98 171 165 117 184 181 136 194 191 148 210 208 158 +214 212 158 224 223 159 239 239 170 239 239 170 224 223 159 214 212 158 +197 193 154 176 171 126 115 113 82 24 26 24 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 40 41 39 103 101 77 +151 147 98 176 171 126 190 186 136 197 193 154 210 208 158 214 212 158 +239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +239 239 170 197 193 154 110 109 94 3 4 3 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 30 31 28 66 65 55 +96 95 69 125 122 87 160 154 106 178 174 128 194 189 146 204 201 155 +214 212 158 239 239 170 251 251 187 251 251 187 251 251 187 239 239 170 +210 208 158 188 184 146 149 145 103 61 61 53 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 61 61 53 131 127 93 +164 159 111 184 181 136 197 193 154 210 208 158 224 223 159 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 +210 208 158 168 163 120 43 44 41 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 4 3 2 36 38 35 +71 71 57 96 95 69 142 137 94 165 161 109 184 181 136 197 193 154 +210 208 158 239 239 170 251 251 187 251 251 187 251 251 187 251 251 187 +214 212 158 197 193 154 168 163 120 103 101 77 7 7 5 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +1 1 1 0 0 0 0 0 0 0 0 0 82 81 62 142 137 94 +174 170 121 194 189 146 210 208 158 224 223 159 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 251 251 187 224 223 159 +184 179 149 99 98 80 3 3 3 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 7 7 5 +43 44 41 82 81 62 118 116 76 142 137 94 171 165 117 190 186 136 +204 201 155 224 223 159 251 251 187 251 251 187 251 251 187 251 251 187 +214 212 158 197 193 154 174 170 121 125 122 87 30 31 28 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 +1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 3 4 3 82 81 62 149 143 98 +176 171 126 194 191 148 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 251 251 187 239 239 170 204 201 155 +145 141 105 30 31 28 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +10 9 6 46 47 43 82 81 62 118 116 76 149 143 98 174 170 121 +194 189 146 210 208 158 224 223 159 251 251 187 251 251 187 224 223 159 +210 208 158 194 191 148 174 170 121 134 131 96 53 55 47 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 5 96 95 69 149 143 98 +176 171 126 194 191 148 210 208 158 239 239 170 251 251 187 251 251 187 +251 251 187 251 251 187 251 251 187 239 239 170 210 208 158 177 172 135 +75 75 61 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 10 9 6 46 47 43 82 81 62 118 116 76 149 143 98 +176 171 126 194 191 148 210 208 158 214 212 158 214 212 158 210 208 158 +197 193 154 184 181 136 164 159 111 131 127 93 53 55 47 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 5 96 95 69 149 143 98 +174 170 121 194 189 146 204 201 155 214 212 158 239 239 170 251 251 187 +251 251 187 251 251 187 239 239 170 210 208 158 184 179 149 110 109 94 +12 12 9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 10 9 6 43 44 41 82 81 62 115 113 82 +144 139 99 168 163 120 188 184 146 197 193 154 197 193 154 194 189 146 +184 181 136 174 170 121 151 147 98 118 116 76 36 38 35 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 4 3 2 82 81 62 142 137 94 +171 165 117 186 182 128 194 191 148 210 208 158 214 212 158 224 223 159 +239 239 170 224 223 159 210 208 158 184 179 149 137 133 100 36 38 35 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 7 7 5 36 38 35 71 71 57 +103 101 77 131 127 93 155 149 109 168 163 120 168 163 120 168 163 120 +164 159 111 149 143 98 125 122 87 82 81 62 13 12 7 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 61 61 53 125 122 87 +160 154 106 174 170 121 184 181 136 194 189 146 204 201 155 210 208 158 +210 208 158 204 201 155 184 179 149 145 141 105 61 61 53 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 3 3 2 30 31 28 +61 61 53 82 81 62 103 101 77 121 119 87 125 122 87 125 122 87 +118 116 76 103 101 77 79 78 62 24 26 24 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 25 27 25 96 95 69 +142 137 94 160 154 106 171 165 117 178 174 128 184 181 136 184 181 136 +181 176 137 177 172 135 145 141 105 75 75 61 5 5 3 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +16 17 12 40 41 39 61 61 53 71 71 57 71 71 57 71 71 57 +66 65 55 43 44 41 12 12 9 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 46 47 43 +96 95 69 125 122 87 142 137 94 149 145 103 155 149 109 155 149 109 +145 141 105 121 119 87 66 65 55 7 7 5 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 1 1 1 16 17 12 24 26 24 25 27 25 19 20 18 +7 7 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 2 1 +25 27 25 61 61 53 82 81 62 96 95 69 96 95 69 82 81 62 +61 61 53 25 27 25 2 2 1 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 5 6 5 13 12 7 10 9 6 3 4 3 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 diff --git a/drivers/video/logo/logo_linux_vga16.ppm b/drivers/video/logo/logo_linux_vga16.ppm index 1850c15e6fe..12ac3a5454c 100644 --- a/drivers/video/logo/logo_linux_vga16.ppm +++ b/drivers/video/logo/logo_linux_vga16.ppm @@ -1,1604 +1,2739 @@ P3 -# Standard 16-color Linux logo -80 80 +142 114 255 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 170 170 170 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 170 170 170 85 85 85 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 170 170 170 170 170 -170 170 170 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 170 170 170 170 170 170 170 170 170 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 170 170 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -170 170 170 170 170 170 255 255 255 255 255 255 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 255 255 255 170 170 170 170 170 170 -255 255 255 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -170 170 170 0 0 0 0 0 0 255 255 255 - 85 85 85 0 0 0 0 0 0 0 0 0 -255 255 255 170 170 170 0 0 0 85 85 85 -170 170 170 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 - 85 85 85 0 0 0 0 0 0 170 170 170 - 85 85 85 0 0 0 0 0 0 0 0 0 -255 255 255 85 85 85 0 0 0 0 0 0 - 85 85 85 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -170 170 170 0 0 0 0 0 0 170 170 170 - 85 85 85 85 85 85 85 85 85 85 85 85 -255 255 255 85 85 85 0 0 0 0 0 0 - 85 85 85 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -255 255 255 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 85 85 85 255 255 255 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -170 170 170 170 170 170 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 170 170 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 170 85 0 85 85 85 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 85 85 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 85 85 85 0 0 0 - 0 0 0 85 85 85 170 170 170 85 85 85 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 85 85 85 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 170 170 170 170 170 170 170 170 0 0 0 - 0 0 0 0 0 0 170 170 170 170 170 170 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 170 170 170 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 85 85 85 - 0 0 0 0 0 0 85 85 85 85 85 85 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 170 170 170 170 170 170 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 170 170 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 255 255 255 170 170 170 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 170 170 170 -255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 -170 170 170 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 85 85 85 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 85 85 85 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 170 170 170 170 170 170 170 170 170 -255 255 255 255 255 255 255 255 255 170 170 170 -170 170 170 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 170 170 170 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 170 170 170 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 -170 170 170 170 170 170 170 170 170 85 85 85 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 170 170 170 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 85 85 85 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 170 170 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 170 170 170 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 85 85 85 - 85 85 85 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 - 0 0 0 85 85 85 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 0 0 0 85 85 85 - 85 85 85 0 0 0 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 85 85 85 - 0 0 0 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 85 85 85 0 0 0 - 0 0 0 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 85 85 85 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 85 85 85 0 0 0 0 0 0 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 0 0 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 0 0 0 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 85 85 85 85 85 85 0 0 0 - 0 0 0 85 85 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 85 85 85 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 85 85 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 170 170 170 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 85 85 85 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 170 170 170 85 85 85 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 85 85 85 85 85 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 85 85 85 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 170 170 170 - 85 85 85 0 0 0 0 0 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 85 85 85 - 0 0 0 0 0 0 0 0 0 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 170 170 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -170 170 170 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 170 170 170 255 255 255 255 255 255 -255 255 255 255 255 255 255 255 255 255 255 255 -255 255 255 255 255 255 170 170 170 85 85 85 - 85 85 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 85 85 85 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 170 85 0 170 85 0 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 85 85 85 85 85 85 85 85 85 - 85 85 85 85 85 85 85 85 85 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 255 255 85 170 85 0 -170 85 0 170 85 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 255 255 85 170 85 0 -255 255 85 170 85 0 170 85 0 170 85 0 - 85 85 85 85 85 85 85 85 85 85 85 85 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 85 85 85 - 85 85 85 85 85 85 85 85 85 170 85 0 -170 85 0 170 85 0 170 85 0 255 255 85 -170 85 0 255 255 85 170 85 0 170 85 0 -170 85 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 170 85 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 -170 85 0 170 85 0 170 85 0 170 85 0 -170 85 0 170 85 0 170 85 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 170 170 170 170 85 0 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +255 255 85 170 170 170 170 170 170 170 85 0 85 255 85 170 85 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 170 170 170 +170 170 170 170 85 0 170 170 170 170 170 170 170 85 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 255 85 +255 85 85 85 255 85 170 170 170 170 85 0 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 85 85 85 +170 170 170 170 85 0 170 170 170 85 85 85 170 85 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 +85 85 85 85 85 85 170 85 0 85 255 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 170 85 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 170 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 85 0 85 255 85 170 85 0 170 85 0 170 85 0 85 255 85 +170 85 0 170 85 0 0 170 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 170 85 0 +255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 85 255 85 170 85 0 170 85 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 +85 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 170 85 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 85 255 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 170 85 0 255 255 85 170 85 0 +170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 85 0 255 255 85 85 255 85 255 255 85 +170 170 170 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 255 255 85 +85 255 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 255 255 85 +255 255 255 255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 +170 85 0 170 85 0 0 170 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 85 0 85 255 85 255 255 85 170 170 170 255 255 255 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 +255 255 85 85 255 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 255 255 85 255 255 85 255 255 85 255 255 255 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 85 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 85 0 170 85 0 255 255 85 255 255 85 255 255 255 170 170 170 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +255 255 85 85 255 85 170 85 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 85 85 255 85 255 255 85 170 170 170 255 255 255 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 85 255 85 170 85 0 +255 255 85 170 85 0 170 85 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170 +85 255 85 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 +170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 170 85 0 170 85 0 +170 85 0 85 255 85 255 255 85 85 85 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 85 255 85 170 170 170 170 170 170 +85 85 85 170 170 170 170 170 170 170 85 0 170 170 170 170 170 170 +85 255 85 170 170 170 170 85 0 170 170 170 85 255 85 255 85 85 +85 255 85 170 170 170 255 255 85 85 85 85 255 255 85 170 170 170 +85 255 85 170 170 170 255 255 85 170 170 170 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 255 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 170 85 0 0 170 0 85 85 85 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 +255 85 85 85 255 85 85 85 85 255 85 85 85 85 85 170 170 170 +170 85 0 170 170 170 85 85 85 85 255 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 +170 85 0 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 85 85 85 85 85 85 +255 255 85 170 170 170 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 170 170 170 170 85 0 170 170 170 +170 170 170 255 255 85 170 170 170 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 170 85 0 170 85 0 0 170 0 +0 0 0 170 85 0 170 85 0 0 170 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 +170 170 170 85 85 85 85 85 85 170 170 170 170 85 0 85 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 170 85 0 +170 85 0 255 255 85 170 85 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 170 85 0 255 255 85 255 255 85 +85 255 85 170 85 0 0 170 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 170 0 170 85 0 255 255 85 +85 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 170 85 0 +85 255 85 170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 170 85 0 +255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 170 85 0 +255 255 85 170 85 0 255 255 85 170 85 0 255 255 85 85 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 170 85 0 170 85 0 +0 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +255 255 85 85 255 85 170 85 0 170 85 0 85 255 85 170 85 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 85 255 85 +255 255 85 255 255 85 85 255 85 255 255 85 255 255 85 255 255 85 +255 255 85 170 85 0 255 255 85 85 255 85 255 255 85 255 255 85 +170 85 0 170 85 0 85 255 85 170 85 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 255 255 85 170 85 0 +255 255 85 85 255 85 170 85 0 255 255 85 170 85 0 85 255 85 +170 85 0 170 85 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 255 255 85 85 255 85 +170 85 0 255 255 85 170 85 0 85 255 85 170 85 0 170 85 0 +0 170 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 255 85 255 255 85 +170 85 0 255 255 85 255 255 85 170 85 0 85 255 85 170 85 0 +255 255 85 170 85 0 0 170 0 170 85 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 170 170 170 170 170 170 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 255 85 +255 255 85 255 255 85 255 255 85 255 255 85 170 85 0 170 85 0 +0 170 0 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +255 255 85 255 255 85 170 85 0 0 170 0 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 85 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 +255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +255 255 255 255 255 255 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 170 170 170 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 170 170 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 170 170 170 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 255 255 255 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 +170 170 170 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +255 255 255 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 255 255 255 +255 255 255 170 170 170 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +170 170 170 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 170 170 170 255 255 255 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 170 170 170 255 255 255 170 170 170 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 255 255 255 255 255 255 255 255 255 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 +255 255 255 170 170 170 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 +170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 255 255 255 255 255 255 85 85 85 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 255 255 255 +255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 255 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 255 255 255 255 255 255 255 255 255 255 255 255 0 0 0 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 85 85 85 170 170 170 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 170 170 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 255 255 255 +170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 255 255 255 255 255 255 0 0 0 0 0 0 85 85 85 +255 255 255 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 +255 255 255 255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 170 170 170 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 +255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 170 170 255 255 85 85 85 85 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +85 85 85 170 170 170 170 170 170 170 170 170 170 85 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 170 170 170 170 85 0 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +170 85 0 170 170 170 85 85 85 0 0 0 85 85 85 85 85 85 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 255 255 255 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 170 85 0 170 170 170 170 170 170 85 85 85 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 85 255 85 170 85 0 170 170 170 85 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 170 85 0 85 255 85 +170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +85 85 85 85 85 85 170 85 0 0 0 0 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 255 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +170 170 170 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 170 85 0 170 170 170 170 85 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 255 85 85 170 170 170 85 255 85 170 85 0 +85 85 85 85 85 85 170 85 0 85 85 85 170 170 170 85 85 85 +170 170 170 170 85 0 85 85 85 85 85 85 85 85 85 85 85 85 +170 85 0 85 255 85 85 85 85 85 85 85 85 85 85 170 85 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 170 170 170 +255 255 255 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 85 0 170 170 170 170 85 0 85 85 85 0 0 0 +85 85 85 85 85 85 85 255 85 170 170 170 170 170 170 170 85 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 85 255 85 255 85 85 170 170 170 170 170 170 +170 170 170 85 255 85 170 170 170 170 85 0 170 170 170 170 85 0 +170 170 170 85 85 85 85 255 85 170 85 0 170 170 170 170 85 0 +170 170 170 170 170 170 170 85 0 85 85 85 85 85 85 85 255 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 170 170 170 170 170 170 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 255 255 85 85 85 85 85 85 85 85 85 85 +85 255 85 255 85 85 170 170 170 170 85 0 170 170 170 85 255 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 +170 170 170 255 85 85 170 170 170 170 170 170 255 255 85 170 170 170 +85 255 85 170 170 170 255 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 85 85 85 0 0 0 85 85 85 +85 85 85 170 85 0 85 85 85 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 85 85 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 85 85 85 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 85 0 +170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 170 85 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 170 170 170 85 85 85 85 85 85 0 0 0 +85 85 85 85 85 85 170 170 170 85 85 85 170 170 170 170 85 0 +170 170 170 85 255 85 170 170 170 170 85 0 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 255 255 255 85 170 170 170 +255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 255 255 85 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 85 85 170 170 170 170 170 170 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 85 85 85 +85 85 85 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 255 85 170 170 170 255 255 85 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 +255 255 85 255 255 255 255 255 85 170 170 170 170 170 170 170 85 0 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +255 255 255 255 255 255 255 255 85 255 255 255 255 255 255 170 170 170 +255 255 85 85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 170 170 170 170 170 170 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 170 170 170 255 255 85 170 170 170 255 255 85 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 170 170 170 +255 255 85 170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 85 85 85 85 85 85 0 0 0 +85 85 85 170 85 0 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 255 255 255 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 255 255 85 +170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 +255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 255 255 85 +85 85 85 85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 255 255 255 170 170 170 255 255 255 170 170 170 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 85 85 85 85 85 85 +0 0 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +85 85 85 85 85 85 170 170 170 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 +255 85 85 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +170 170 170 255 255 255 255 255 255 170 170 170 255 255 255 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 170 170 170 +255 255 85 170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 255 85 +170 170 170 170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 255 255 85 170 170 170 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 255 85 85 +85 255 85 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 255 255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 255 255 85 +170 170 170 170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 +255 255 255 170 170 170 170 170 170 170 170 170 170 170 170 255 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 85 85 85 0 0 0 +85 85 85 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 170 170 170 170 170 170 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 85 255 85 +255 85 85 170 170 170 255 255 85 170 170 170 170 170 170 255 255 255 +255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 170 170 170 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 255 255 255 +170 170 170 170 170 170 255 255 85 170 170 170 255 85 85 85 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 85 85 85 85 85 85 85 85 85 170 170 170 255 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 170 85 0 85 85 85 +170 170 170 170 85 0 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 85 170 170 170 170 170 170 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 +170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 170 170 170 170 170 170 170 85 0 170 170 170 85 85 85 +170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 85 85 85 +85 255 85 85 85 85 0 0 0 0 0 0 0 0 0 85 85 85 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170 +170 85 0 170 170 170 85 255 85 170 85 0 170 170 170 85 85 85 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 +255 255 85 255 255 255 170 170 170 170 170 170 170 170 170 170 85 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 85 255 85 170 170 170 +170 85 0 170 85 0 170 170 170 85 255 85 85 85 85 170 170 170 +170 85 0 85 85 85 0 0 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 +170 170 170 170 85 0 170 170 170 85 85 85 170 170 170 170 85 0 +170 170 170 85 255 85 170 85 0 170 170 170 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +170 85 0 170 170 170 255 255 85 170 170 170 255 255 255 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 170 170 170 170 85 0 +170 170 170 85 255 85 170 85 0 170 170 170 170 85 0 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +85 255 85 170 170 170 170 85 0 170 170 170 170 85 0 85 255 85 +170 170 170 170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 255 170 170 170 170 170 170 170 170 170 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 85 0 85 85 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 85 0 +170 170 170 85 85 85 170 170 170 170 85 0 170 170 170 85 85 85 +170 85 0 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 0 0 0 85 85 85 170 85 0 +85 85 85 255 85 85 85 255 85 170 85 0 170 170 170 170 170 170 +170 85 0 170 170 170 85 85 85 255 255 85 170 170 170 170 170 170 +255 255 255 170 170 170 255 255 255 255 255 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 170 170 170 170 85 0 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 85 85 85 170 170 170 +85 255 85 255 85 85 170 170 170 85 255 85 255 85 85 85 255 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 85 85 85 0 0 0 85 85 85 +85 85 85 85 255 85 255 85 85 170 170 170 85 255 85 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 255 255 255 +170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 170 170 85 85 85 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +85 85 85 255 255 85 170 170 170 170 85 0 170 170 170 85 85 85 +170 85 0 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 170 170 170 85 0 170 170 170 170 85 0 170 170 170 170 170 170 +170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 170 85 0 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 85 0 85 255 85 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 170 170 170 170 170 255 255 255 255 255 255 +255 255 255 170 170 170 255 255 85 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 170 85 0 +170 170 170 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 170 170 170 +170 170 170 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 170 85 0 170 170 170 170 85 0 170 170 170 170 170 170 +170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 255 255 255 +170 170 170 255 255 255 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 85 85 85 +170 85 0 170 170 170 170 85 0 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +255 255 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 170 170 170 255 255 85 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 +170 170 170 170 170 170 170 170 170 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 170 0 85 85 85 +170 85 0 85 255 85 170 170 170 170 170 170 170 170 170 255 255 85 +255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +170 170 170 255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +170 85 0 170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 255 255 255 +255 255 255 255 255 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 +170 170 170 255 255 255 255 255 255 255 255 255 170 170 170 255 255 255 +170 170 170 170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 255 85 +170 170 170 255 255 85 170 170 170 255 255 85 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 +170 170 170 170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 170 85 0 170 170 170 170 170 170 +255 255 85 170 170 170 255 255 255 255 255 85 255 255 255 255 255 255 +170 170 170 255 255 85 170 170 170 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 +170 170 170 170 170 170 170 170 170 255 255 255 170 170 170 255 255 255 +170 170 170 255 255 255 170 170 170 255 255 255 255 255 85 255 255 255 +170 170 170 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 170 85 0 85 85 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 170 170 170 255 255 255 255 255 255 170 170 170 +255 255 85 170 170 170 170 170 170 170 85 0 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +255 255 85 170 170 170 255 255 85 170 170 170 255 255 255 255 255 255 +255 255 255 255 255 255 255 255 255 255 255 255 170 170 170 170 170 170 +170 170 170 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 170 85 0 170 170 170 +255 255 85 170 170 170 255 255 85 255 255 255 170 170 170 255 255 255 +170 170 170 170 170 170 170 170 170 170 170 170 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 170 170 +170 85 0 170 170 170 255 255 255 170 170 170 255 255 255 170 170 170 +255 255 255 255 255 255 170 170 170 255 255 255 255 255 85 170 170 170 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 85 85 85 170 85 0 85 85 85 170 170 170 +170 170 170 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 85 170 170 170 170 85 0 85 255 85 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 170 85 0 +170 170 170 170 170 170 255 255 85 170 170 170 255 255 255 255 255 255 +255 255 85 255 255 255 170 170 170 255 255 255 170 170 170 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 85 0 170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 +170 170 170 170 170 170 170 170 170 170 85 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +255 255 85 170 170 170 170 170 170 170 170 170 255 255 85 170 170 170 +255 255 255 170 170 170 255 255 85 170 170 170 85 85 85 85 85 85 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 170 170 170 +170 85 0 170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 85 85 85 +170 170 170 170 170 170 255 255 85 170 170 170 170 170 170 170 170 170 +170 170 170 255 255 255 170 170 170 170 170 170 85 85 85 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +85 85 85 85 85 85 85 85 85 170 85 0 85 85 85 170 85 0 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 170 85 0 +85 85 85 170 85 0 170 170 170 170 170 170 170 170 170 255 255 85 +170 170 170 170 170 170 170 85 0 85 85 85 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 85 85 85 +85 85 85 85 255 85 170 85 0 170 170 170 170 85 0 170 170 170 +85 85 85 85 85 85 85 85 85 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 85 85 85 85 85 85 85 85 85 85 85 85 85 85 85 +85 85 85 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +0 0 0 0 0 0 0 0 0 0 0 0 -- cgit v1.2.3 From bc0fd67feba2e0770aad85393500ba77c6489f1c Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Mon, 16 Mar 2009 16:56:01 +0000 Subject: dm ioctl: validate name length when renaming When renaming a mapped device validate the length of the new name. The rename ioctl accepted any correctly-terminated string enclosed within the data passed from userspace. The other ioctls enforce a size limit of DM_NAME_LEN. If the name is changed and becomes longer than that, the device can no longer be addressed by name. Fix it by properly checking for device name length (including terminating zero). Cc: stable@kernel.org Signed-off-by: Milan Broz Reviewed-by: Jonathan Brassow Reviewed-by: Alasdair G Kergon Signed-off-by: Alasdair G Kergon --- drivers/md/dm-ioctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 54d0588fc1f..977f36612e8 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -704,7 +704,8 @@ static int dev_rename(struct dm_ioctl *param, size_t param_size) char *new_name = (char *) param + param->data_start; if (new_name < param->data || - invalid_str(new_name, (void *) param + param_size)) { + invalid_str(new_name, (void *) param + param_size) || + strlen(new_name) > DM_NAME_LEN - 1) { DMWARN("Invalid new logical volume name supplied."); return -EINVAL; } -- cgit v1.2.3 From f80a557008462a0a4adef25407f1872e793d8dd5 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 16 Mar 2009 17:44:26 +0000 Subject: dm table: rework reference counting fix Fix an error introduced in dm-table-rework-reference-counting.patch. When there is failure after table initialization, we need to use dm_table_destroy, not dm_table_put, to free the table. dm_table_put may be used only after dm_table_get. Cc: Kiyoshi Ueda Signed-off-by: Mikulas Patocka Reviewed-by: Jonathan Brassow Reviewed-by: Alasdair G Kergon Signed-off-by: Alasdair G Kergon --- drivers/md/dm-ioctl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 977f36612e8..f01096549a9 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1064,7 +1064,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) r = populate_table(t, param, param_size); if (r) { - dm_table_put(t); + dm_table_destroy(t); goto out; } @@ -1072,7 +1072,7 @@ static int table_load(struct dm_ioctl *param, size_t param_size) hc = dm_get_mdptr(md); if (!hc || hc->md != md) { DMWARN("device has been removed from the dev hash table."); - dm_table_put(t); + dm_table_destroy(t); up_write(&_hash_lock); r = -ENXIO; goto out; -- cgit v1.2.3 From d659e6cc98766a1a61d6bdd283f95d149abd7719 Mon Sep 17 00:00:00 2001 From: Mikulas Patocka Date: Mon, 16 Mar 2009 17:44:30 +0000 Subject: dm io: respect BIO_MAX_PAGES limit dm-io calls bio_get_nr_vecs to get the maximum number of pages to use for a given device. It allocates one additional bio_vec to use internally but failed to respect BIO_MAX_PAGES, so fix this. This was the likely cause of: https://bugzilla.redhat.com/show_bug.cgi?id=173153 Cc: stable@kernel.org Signed-off-by: Mikulas Patocka Signed-off-by: Alasdair G Kergon --- drivers/md/dm-io.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/md/dm-io.c b/drivers/md/dm-io.c index f14813be4ef..36e2b5e46a6 100644 --- a/drivers/md/dm-io.c +++ b/drivers/md/dm-io.c @@ -292,6 +292,8 @@ static void do_region(int rw, unsigned region, struct dm_io_region *where, (PAGE_SIZE >> SECTOR_SHIFT)); num_bvecs = 1 + min_t(int, bio_get_nr_vecs(where->bdev), num_bvecs); + if (unlikely(num_bvecs > BIO_MAX_PAGES)) + num_bvecs = BIO_MAX_PAGES; bio = bio_alloc_bioset(GFP_NOIO, num_bvecs, io->client->bios); bio->bi_sector = where->sector + (where->count - remaining); bio->bi_bdev = where->bdev; -- cgit v1.2.3 From b2174eebd1fadb76454dad09a1dacbc17081e6b0 Mon Sep 17 00:00:00 2001 From: Huang Ying Date: Mon, 16 Mar 2009 17:44:33 +0000 Subject: dm crypt: fix kcryptd_async_done parameter In the async encryption-complete function (kcryptd_async_done), the crypto_async_request passed in may be different from the one passed to crypto_ablkcipher_encrypt/decrypt. Only crypto_async_request->data is guaranteed to be same as the one passed in. The current kcryptd_async_done uses the passed-in crypto_async_request directly which may cause the AES-NI-based AES algorithm implementation to panic. This patch fixes this bug by only using crypto_async_request->data, which points to dm_crypt_request, the crypto_async_request passed in. The original data (convert_context) is gotten from dm_crypt_request. [mbroz@redhat.com: reworked] Cc: stable@kernel.org Signed-off-by: Huang Ying Cc: Herbert Xu Signed-off-by: Milan Broz Signed-off-by: Andrew Morton Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index 35bda49796f..ebab49f8cc1 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -60,6 +60,7 @@ struct dm_crypt_io { }; struct dm_crypt_request { + struct convert_context *ctx; struct scatterlist sg_in; struct scatterlist sg_out; }; @@ -335,6 +336,18 @@ static void crypt_convert_init(struct crypt_config *cc, init_completion(&ctx->restart); } +static struct dm_crypt_request *dmreq_of_req(struct crypt_config *cc, + struct ablkcipher_request *req) +{ + return (struct dm_crypt_request *)((char *)req + cc->dmreq_start); +} + +static struct ablkcipher_request *req_of_dmreq(struct crypt_config *cc, + struct dm_crypt_request *dmreq) +{ + return (struct ablkcipher_request *)((char *)dmreq - cc->dmreq_start); +} + static int crypt_convert_block(struct crypt_config *cc, struct convert_context *ctx, struct ablkcipher_request *req) @@ -345,10 +358,11 @@ static int crypt_convert_block(struct crypt_config *cc, u8 *iv; int r = 0; - dmreq = (struct dm_crypt_request *)((char *)req + cc->dmreq_start); + dmreq = dmreq_of_req(cc, req); iv = (u8 *)ALIGN((unsigned long)(dmreq + 1), crypto_ablkcipher_alignmask(cc->tfm) + 1); + dmreq->ctx = ctx; sg_init_table(&dmreq->sg_in, 1); sg_set_page(&dmreq->sg_in, bv_in->bv_page, 1 << SECTOR_SHIFT, bv_in->bv_offset + ctx->offset_in); @@ -395,8 +409,9 @@ static void crypt_alloc_req(struct crypt_config *cc, cc->req = mempool_alloc(cc->req_pool, GFP_NOIO); ablkcipher_request_set_tfm(cc->req, cc->tfm); ablkcipher_request_set_callback(cc->req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - kcryptd_async_done, ctx); + CRYPTO_TFM_REQ_MAY_SLEEP, + kcryptd_async_done, + dmreq_of_req(cc, cc->req)); } /* @@ -821,7 +836,8 @@ static void kcryptd_crypt_read_convert(struct dm_crypt_io *io) static void kcryptd_async_done(struct crypto_async_request *async_req, int error) { - struct convert_context *ctx = async_req->data; + struct dm_crypt_request *dmreq = async_req->data; + struct convert_context *ctx = dmreq->ctx; struct dm_crypt_io *io = container_of(ctx, struct dm_crypt_io, ctx); struct crypt_config *cc = io->target->private; @@ -830,7 +846,7 @@ static void kcryptd_async_done(struct crypto_async_request *async_req, return; } - mempool_free(ablkcipher_request_cast(async_req), cc->req_pool); + mempool_free(req_of_dmreq(cc, dmreq), cc->req_pool); if (!atomic_dec_and_test(&ctx->pending)) return; -- cgit v1.2.3 From b35f8caa0890169000fec22902290d9a15274cbd Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Mon, 16 Mar 2009 17:44:36 +0000 Subject: dm crypt: wait for endio to complete before destruction The following oops has been reported when dm-crypt runs over a loop device. ... [ 70.381058] Process loop0 (pid: 4268, ti=cf3b2000 task=cf1cc1f0 task.ti=cf3b2000) ... [ 70.381058] Call Trace: [ 70.381058] [] ? crypt_dec_pending+0x5e/0x62 [dm_crypt] [ 70.381058] [] ? crypt_endio+0xa2/0xaa [dm_crypt] [ 70.381058] [] ? crypt_endio+0x0/0xaa [dm_crypt] [ 70.381058] [] ? bio_endio+0x2b/0x2e [ 70.381058] [] ? dec_pending+0x224/0x23b [dm_mod] [ 70.381058] [] ? clone_endio+0x79/0xa4 [dm_mod] [ 70.381058] [] ? clone_endio+0x0/0xa4 [dm_mod] [ 70.381058] [] ? bio_endio+0x2b/0x2e [ 70.381058] [] ? loop_thread+0x380/0x3b7 [ 70.381058] [] ? do_lo_send_aops+0x0/0x165 [ 70.381058] [] ? autoremove_wake_function+0x0/0x33 [ 70.381058] [] ? loop_thread+0x0/0x3b7 When a table is being replaced, it waits for I/O to complete before destroying the mempool, but the endio function doesn't call mempool_free() until after completing the bio. Fix it by swapping the order of those two operations. The same problem occurs in dm.c with md referenced after dec_pending. Again, we swap the order. Cc: stable@kernel.org Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- drivers/md/dm-crypt.c | 17 ++++++++++------- drivers/md/dm.c | 32 +++++++++++++++++++------------- 2 files changed, 29 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c index ebab49f8cc1..bfefd079a95 100644 --- a/drivers/md/dm-crypt.c +++ b/drivers/md/dm-crypt.c @@ -568,19 +568,22 @@ static void crypt_inc_pending(struct dm_crypt_io *io) static void crypt_dec_pending(struct dm_crypt_io *io) { struct crypt_config *cc = io->target->private; + struct bio *base_bio = io->base_bio; + struct dm_crypt_io *base_io = io->base_io; + int error = io->error; if (!atomic_dec_and_test(&io->pending)) return; - if (likely(!io->base_io)) - bio_endio(io->base_bio, io->error); + mempool_free(io, cc->io_pool); + + if (likely(!base_io)) + bio_endio(base_bio, error); else { - if (io->error && !io->base_io->error) - io->base_io->error = io->error; - crypt_dec_pending(io->base_io); + if (error && !base_io->error) + base_io->error = error; + crypt_dec_pending(base_io); } - - mempool_free(io, cc->io_pool); } /* diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 51ba1db4b3e..8d40f27cce8 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -525,9 +525,12 @@ static int __noflush_suspending(struct mapped_device *md) static void dec_pending(struct dm_io *io, int error) { unsigned long flags; + int io_error; + struct bio *bio; + struct mapped_device *md = io->md; /* Push-back supersedes any I/O errors */ - if (error && !(io->error > 0 && __noflush_suspending(io->md))) + if (error && !(io->error > 0 && __noflush_suspending(md))) io->error = error; if (atomic_dec_and_test(&io->io_count)) { @@ -537,24 +540,27 @@ static void dec_pending(struct dm_io *io, int error) * This must be handled before the sleeper on * suspend queue merges the pushback list. */ - spin_lock_irqsave(&io->md->pushback_lock, flags); - if (__noflush_suspending(io->md)) - bio_list_add(&io->md->pushback, io->bio); + spin_lock_irqsave(&md->pushback_lock, flags); + if (__noflush_suspending(md)) + bio_list_add(&md->pushback, io->bio); else /* noflush suspend was interrupted. */ io->error = -EIO; - spin_unlock_irqrestore(&io->md->pushback_lock, flags); + spin_unlock_irqrestore(&md->pushback_lock, flags); } end_io_acct(io); - if (io->error != DM_ENDIO_REQUEUE) { - trace_block_bio_complete(io->md->queue, io->bio); + io_error = io->error; + bio = io->bio; - bio_endio(io->bio, io->error); - } + free_io(md, io); + + if (io_error != DM_ENDIO_REQUEUE) { + trace_block_bio_complete(md->queue, bio); - free_io(io->md, io); + bio_endio(bio, io_error); + } } } @@ -562,6 +568,7 @@ static void clone_endio(struct bio *bio, int error) { int r = 0; struct dm_target_io *tio = bio->bi_private; + struct dm_io *io = tio->io; struct mapped_device *md = tio->io->md; dm_endio_fn endio = tio->ti->type->end_io; @@ -585,15 +592,14 @@ static void clone_endio(struct bio *bio, int error) } } - dec_pending(tio->io, error); - /* * Store md for cleanup instead of tio which is about to get freed. */ bio->bi_private = md->bs; - bio_put(bio); free_tio(md, tio); + bio_put(bio); + dec_pending(io, error); } static sector_t max_io_len(struct mapped_device *md, -- cgit v1.2.3 From da62e71d13ad0b76011491e36cb58999c464516a Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Tue, 17 Mar 2009 09:30:36 +0900 Subject: sh: dma: Make PVR2 DMA configurable. With arch/sh/drivers/dma/ always being built, the Dreamcast DMA engines are being unconditionally built in, regardless of whether the DMA API is enabled or not. This is a regression from previous behaviour, but there is not much advantage in building them all in unconditionally regardless. Add a new config option to make it optional, and update the only user of it to reflect that. Signed-off-by: Paul Mundt --- drivers/video/pvr2fb.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/video/pvr2fb.c b/drivers/video/pvr2fb.c index 0a0fd48a856..53f8f1100e8 100644 --- a/drivers/video/pvr2fb.c +++ b/drivers/video/pvr2fb.c @@ -61,7 +61,7 @@ #include #endif -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA #include #include #include @@ -188,7 +188,7 @@ static unsigned int is_blanked = 0; /* Is the screen blanked? */ static unsigned long pvr2fb_map; #endif -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA static unsigned int shdma = PVR2_CASCADE_CHAN; static unsigned int pvr2dma = ONCHIP_NR_DMA_CHANNELS; #endif @@ -207,7 +207,7 @@ static irqreturn_t pvr2fb_interrupt(int irq, void *dev_id); static int pvr2_init_cable(void); static int pvr2_get_param(const struct pvr2_params *p, const char *s, int val, int size); -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, size_t count, loff_t *ppos); #endif @@ -218,7 +218,7 @@ static struct fb_ops pvr2fb_ops = { .fb_blank = pvr2fb_blank, .fb_check_var = pvr2fb_check_var, .fb_set_par = pvr2fb_set_par, -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA .fb_write = pvr2fb_write, #endif .fb_fillrect = cfb_fillrect, @@ -671,7 +671,7 @@ static int pvr2_init_cable(void) return cable_type; } -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA static ssize_t pvr2fb_write(struct fb_info *info, const char *buf, size_t count, loff_t *ppos) { @@ -743,7 +743,7 @@ out_unmap: return ret; } -#endif /* CONFIG_SH_DMA */ +#endif /* CONFIG_PVR2_DMA */ /** * pvr2fb_common_init @@ -893,7 +893,7 @@ static int __init pvr2fb_dc_init(void) return -EBUSY; } -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA if (request_dma(pvr2dma, "pvr2") != 0) { free_irq(HW_EVENT_VSYNC, 0); return -EBUSY; @@ -915,7 +915,7 @@ static void __exit pvr2fb_dc_exit(void) } free_irq(HW_EVENT_VSYNC, 0); -#ifdef CONFIG_SH_DMA +#ifdef CONFIG_PVR2_DMA free_dma(pvr2dma); #endif } -- cgit v1.2.3 From 5b10916ea0a62920204517e1c4ce14560b4f96ab Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 10 Mar 2009 20:42:55 -0700 Subject: USB: usbtmc: fix stupid bug in open() open() will never succeed, as we always return -ENODEV. Fix this obvious bug. Thanks to Jouni Ryno for reporting it. Reported-by: Jouni Ryno Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 0f5c05f6f9d..895a0983900 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -106,12 +106,13 @@ static int usbtmc_open(struct inode *inode, struct file *filp) { struct usb_interface *intf; struct usbtmc_device_data *data; - int retval = -ENODEV; + int retval = 0; intf = usb_find_interface(&usbtmc_driver, iminor(inode)); if (!intf) { printk(KERN_ERR KBUILD_MODNAME ": can not find device for minor %d", iminor(inode)); + retval = -ENODEV; goto exit; } -- cgit v1.2.3 From 228dd05dbfdd0fced8ab1a28ed73b500ba6bb0a6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Mar 2009 13:51:42 -0700 Subject: USB: usbtmc: add protocol 1 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The driver already supports the 1 protocol support, so just add it to the MODULE_DEVICE_TABLE entry so it properly picks up these devices. Thanks to Jouni Rynö for pointing this out. Reported-by: Jouni Ryno Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usbtmc.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/class/usbtmc.c b/drivers/usb/class/usbtmc.c index 895a0983900..c40a9b284cc 100644 --- a/drivers/usb/class/usbtmc.c +++ b/drivers/usb/class/usbtmc.c @@ -50,6 +50,7 @@ static struct usb_device_id usbtmc_devices[] = { { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 0), }, + { USB_INTERFACE_INFO(USB_CLASS_APP_SPEC, 3, 1), }, { 0, } /* terminating entry */ }; MODULE_DEVICE_TABLE(usb, usbtmc_devices); -- cgit v1.2.3 From 6ff10464096540e14d7575a72c50d0316d003714 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 9 Mar 2009 13:44:02 -0400 Subject: USB: usbfs: keep async URBs until the device file is closed The usbfs driver manages a list of completed asynchronous URBs. But it is too eager to free the entries on this list: destroy_async() gets called whenever an interface is unbound or a device is removed, and it deallocates the outstanding struct async entries for all URBs on that interface or device. This is wrong; the user program should be able to reap an URB any time after it has completed, regardless of whether or not the interface is still bound or the device is still present. This patch (as1222) moves the code for deallocating the completed list entries from destroy_async() to usbdev_release(). The outstanding entries won't be freed until the user program has closed the device file, thereby eliminating any possibility that the remaining URBs might still be reaped. This fixes a bug in which a program can hang in the USBDEVFS_REAPURB ioctl when the device is unplugged. Reported-and-tested-by: Martin Poupe Signed-off-by: Alan Stern Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 7513bb083c1..6585f527e38 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -359,11 +359,6 @@ static void destroy_async(struct dev_state *ps, struct list_head *list) spin_lock_irqsave(&ps->lock, flags); } spin_unlock_irqrestore(&ps->lock, flags); - as = async_getcompleted(ps); - while (as) { - free_async(as); - as = async_getcompleted(ps); - } } static void destroy_async_on_interface(struct dev_state *ps, @@ -643,6 +638,7 @@ static int usbdev_release(struct inode *inode, struct file *file) struct dev_state *ps = file->private_data; struct usb_device *dev = ps->dev; unsigned int ifnum; + struct async *as; usb_lock_device(dev); @@ -661,6 +657,12 @@ static int usbdev_release(struct inode *inode, struct file *file) usb_unlock_device(dev); usb_put_dev(dev); put_pid(ps->disc_pid); + + as = async_getcompleted(ps); + while (as) { + free_async(as); + as = async_getcompleted(ps); + } kfree(ps); return 0; } -- cgit v1.2.3 From 7f82b6dd7015aabca2fd55fb690248f742cd67f3 Mon Sep 17 00:00:00 2001 From: Axel Wachtler Date: Thu, 5 Mar 2009 14:09:22 -0800 Subject: USB: serial: add FTDI USB/Serial converter devices Add the following devices to the USB FTDI SIO device table: Bus 001 Device 009: ID 03eb:2109 Atmel Corp. http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4187 Bus 001 Device 008: ID 1cf1:0001 http://www.dresden-elektronik.de/shop/prod75.html Bus 001 Device 007: ID 1c1f:0004 http://www.dresden-elektronik.de/shop/prod64.html Signed-off-by: Axel Wachtler Signed-off-by: Robert Richter Signed-off-by: Andrew Morton Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 3 +++ drivers/usb/serial/ftdi_sio.h | 13 +++++++++++++ 2 files changed, 16 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f92f4d77337..f77339265ee 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -663,6 +663,9 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ALTI2_VID, ALTI2_N3_PID) }, { USB_DEVICE(FTDI_VID, DIEBOLD_BCS_SE923_PID) }, { USB_DEVICE(FTDI_VID, FTDI_NDI_HUC_PID) }, + { USB_DEVICE(ATMEL_VID, STK541_PID) }, + { USB_DEVICE(DE_VID, STB_PID) }, + { USB_DEVICE(DE_VID, WHT_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index e300c840f8c..f2745edabcd 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -892,6 +892,19 @@ */ #define DIEBOLD_BCS_SE923_PID 0xfb99 +/* + * Atmel STK541 + */ +#define ATMEL_VID 0x03eb /* Vendor ID */ +#define STK541_PID 0x2109 /* Zigbee Controller */ + +/* + * Dresden Elektronic Sensor Terminal Board + */ +#define DE_VID 0x1cf1 /* Vendor ID */ +#define STB_PID 0x0001 /* Sensor Terminal Board */ +#define WHT_PID 0x0004 /* Wireless Handheld Terminal */ + /* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ -- cgit v1.2.3 From b0d659002168146ec6b03d1ef062d8dcf05ff510 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Fri, 6 Mar 2009 14:07:43 -0800 Subject: USB: serial: ftdi: enable UART detection on gnICE JTAG adaptors blacklist interface0 Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu Signed-off-by: Andrew Morton Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 ++ drivers/usb/serial/ftdi_sio.h | 7 +++++++ 2 files changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index f77339265ee..ae84c326a54 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -666,6 +666,8 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(ATMEL_VID, STK541_PID) }, { USB_DEVICE(DE_VID, STB_PID) }, { USB_DEVICE(DE_VID, WHT_PID) }, + { USB_DEVICE(ADI_VID, ADI_GNICE_PID), + .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/drivers/usb/serial/ftdi_sio.h b/drivers/usb/serial/ftdi_sio.h index f2745edabcd..daaf63db0b5 100644 --- a/drivers/usb/serial/ftdi_sio.h +++ b/drivers/usb/serial/ftdi_sio.h @@ -905,6 +905,13 @@ #define STB_PID 0x0001 /* Sensor Terminal Board */ #define WHT_PID 0x0004 /* Wireless Handheld Terminal */ +/* + * Blackfin gnICE JTAG + * http://docs.blackfin.uclinux.org/doku.php?id=hw:jtag:gnice + */ +#define ADI_VID 0x0456 +#define ADI_GNICE_PID 0xF000 + /* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ -- cgit v1.2.3 From c6535668798b0644e1af5934c2aec0e912280449 Mon Sep 17 00:00:00 2001 From: "Robert M. Kenney" Date: Thu, 26 Feb 2009 14:58:39 -0500 Subject: USB: serial: new cp2101 device id From: Robert M. Kenney Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 027f4b7dde8..9b4082b58c5 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -79,6 +79,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ -- cgit v1.2.3 From c497e715f93d148d751c055401568684eea0bf6b Mon Sep 17 00:00:00 2001 From: Jan Dumon Date: Tue, 10 Mar 2009 17:29:47 +0100 Subject: USB: unusual_devs: Add support for GI 0431 SD-Card interface Enable the SD-Card interface on the GI 0431 HSUPA stick from Option. The unusual_devs.h entry is necessary because the device descriptor is vendor-specific. That prevents usb-storage from binding to it as an interface driver. T: Bus=07 Lev=01 Prnt=01 Port=01 Cnt=02 Dev#= 15 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=ff(vend.) Sub=ff Prot=ff MxPS=64 #Cfgs= 1 P: Vendor=0af0 ProdID=7501 Rev= 0.00 S: Manufacturer=Option N.V. S: Product=Globetrotter HSUPA Modem C:* #Ifs=11 Cfg#= 1 Atr=a0 MxPwr=500mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 4 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=06(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 6 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=07(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 7 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=88(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=08(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 8 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=(none) E: Ad=89(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=09(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#= 9 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=ff Driver=hso E: Ad=8a(I) Atr=03(Int.) MxPS= 64 Ivl=2ms E: Ad=8b(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=0a(O) Atr=02(Bulk) MxPS= 512 Ivl=4ms I:* If#=10 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=0b(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=8c(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Jan Dumon Signed-off-by: Phil Dibowitz Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6f59c8e510e..bfa8db0d8aa 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1390,6 +1390,16 @@ UNUSUAL_DEV( 0x0af0, 0x7401, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, 0 ), +/* Reported by Jan Dumon + * This device (wrongly) has a vendor-specific device descriptor. + * The entry is needed so usb-storage can bind to it's mass-storage + * interface as an interface driver */ +UNUSUAL_DEV( 0x0af0, 0x7501, 0x0000, 0x0000, + "Option", + "GI 0431 SD-Card", + US_SC_DEVICE, US_PR_DEVICE, NULL, + 0 ), + /* Reported by Ben Efros */ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, "Seagate", -- cgit v1.2.3 From eeafa64b7a4134da24d48ed944e48541f8171152 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:36 +0100 Subject: USB: atm/cxacru, fix lock imbalance We do not hold mutex in one place in cxacru_cm, but unlock it on fail path. Fix this. Signed-off-by: Jiri Slaby Cc: Simon Arlott Signed-off-by: Greg Kroah-Hartman --- drivers/usb/atm/cxacru.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 5ed4ae07bac..6789089e246 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c @@ -485,7 +485,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, usb_err(instance->usbatm, "requested transfer size too large (%d, %d)\n", wbuflen, rbuflen); ret = -ENOMEM; - goto fail; + goto err; } mutex_lock(&instance->cm_serialize); @@ -565,6 +565,7 @@ static int cxacru_cm(struct cxacru_data *instance, enum cxacru_cm_request cm, dbg("cm %#x", cm); fail: mutex_unlock(&instance->cm_serialize); +err: return ret; } -- cgit v1.2.3 From 909b6c3fc20ea772dc63a03986d74148fcbb1a1d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:37 +0100 Subject: USB: image/mdc800, fix lock imbalance There is an omitted unlock in mdc800_usb_probe's fail path. Add it. Signed-off-by: Jiri Slaby Cc: Henning Zabel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/image/mdc800.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 878c77ca086..972f20b3406 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -499,6 +499,7 @@ static int mdc800_usb_probe (struct usb_interface *intf, retval = usb_register_dev(intf, &mdc800_class); if (retval) { dev_err(&intf->dev, "Not able to get a minor for this device.\n"); + mutex_unlock(&mdc800->io_lock); return -ENODEV; } -- cgit v1.2.3 From 46c9844c4014be53c67622dcd3ba4302f36e9cac Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:38 +0100 Subject: USB: misc/adutux, fix lock imbalance Don't unlock adutux_mutex when not held. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/adutux.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/misc/adutux.c b/drivers/usb/misc/adutux.c index 7b6922e08ed..20352654201 100644 --- a/drivers/usb/misc/adutux.c +++ b/drivers/usb/misc/adutux.c @@ -376,7 +376,7 @@ static int adu_release(struct inode *inode, struct file *file) if (dev->open_count <= 0) { dbg(1," %s : device not opened", __func__); retval = -ENODEV; - goto exit; + goto unlock; } adu_release_internal(dev); @@ -385,9 +385,9 @@ static int adu_release(struct inode *inode, struct file *file) if (!dev->open_count) /* ... and we're the last user */ adu_delete(dev); } - -exit: +unlock: mutex_unlock(&adutux_mutex); +exit: dbg(2," %s : leave, return value %d", __func__, retval); return retval; } -- cgit v1.2.3 From a08b43aee46ed4272ad7bee2c785edcf313339b3 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:39 +0100 Subject: USB: misc/vstusb, fix lock imbalance Make sure we don't leak locked vstdev->lock in vstusb_write. Unlock properly on one fail path. Signed-off-by: Jiri Slaby Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/vstusb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/misc/vstusb.c b/drivers/usb/misc/vstusb.c index 63dff9ba73c..f26ea8dc157 100644 --- a/drivers/usb/misc/vstusb.c +++ b/drivers/usb/misc/vstusb.c @@ -401,6 +401,7 @@ static ssize_t vstusb_write(struct file *file, const char __user *buffer, } if (copy_from_user(buf, buffer, count)) { + mutex_unlock(&vstdev->lock); dev_err(&dev->dev, "%s: can't copy_from_user\n", __func__); retval = -EFAULT; goto exit; -- cgit v1.2.3 From 49fa09215c03116449184057f062c6aea2f1d0b4 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Wed, 11 Mar 2009 21:47:40 +0100 Subject: USB: wusbcore/wa-xfer, fix lock imbalance Fix locking on one wa_urb_enqueue_b's fail path. There was omitted unlock. Signed-off-by: Jiri Slaby Cc: Inaky Perez-Gonzalez Signed-off-by: Greg Kroah-Hartman --- drivers/usb/wusbcore/wa-xfer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c index 238a96aee3a..613a5fc490d 100644 --- a/drivers/usb/wusbcore/wa-xfer.c +++ b/drivers/usb/wusbcore/wa-xfer.c @@ -921,8 +921,10 @@ static void wa_urb_enqueue_b(struct wa_xfer *xfer) result = -ENODEV; /* FIXME: segmentation broken -- kills DWA */ mutex_lock(&wusbhc->mutex); /* get a WUSB dev */ - if (urb->dev == NULL) + if (urb->dev == NULL) { + mutex_unlock(&wusbhc->mutex); goto error_dev_gone; + } wusb_dev = __wusb_dev_get_by_usb_dev(wusbhc, urb->dev); if (wusb_dev == NULL) { mutex_unlock(&wusbhc->mutex); -- cgit v1.2.3 From 9ea19b82f3126da4e47d6b94563a3c2cd586f6e2 Mon Sep 17 00:00:00 2001 From: Albert Pauw Date: Sun, 1 Mar 2009 09:37:52 +0100 Subject: USB: option.c: add ZTE 622 modem device Please consider this small patch for the usb option-card driver. This patch adds the ZTE 622 usb modem device. Signed-off-by: Albert Pauw Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index b7c132bded7..ddd0a0b7e1a 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -288,6 +288,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 +#define ZTE_PRODUCT_MF622 0x0001 #define ZTE_PRODUCT_MF628 0x0015 #define ZTE_PRODUCT_MF626 0x0031 #define ZTE_PRODUCT_CDMA_TECH 0xfffe @@ -510,6 +511,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, + { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, -- cgit v1.2.3 From 508db8c954d55ed30f870d2c24d741ba6269d13c Mon Sep 17 00:00:00 2001 From: Karsten Wiese Date: Thu, 26 Feb 2009 01:47:48 +0100 Subject: USB: EHCI: Fix isochronous URB leak ehci-hcd uses usb_get_urb() and usb_put_urb() in an unbalanced way causing isochronous URB's kref.counts incrementing once per usb_submit_urb() call. The culprit is *usb being set to NULL when usb_put_urb() is called after URB is given back. Due to other fixes there is no need for ehci-hcd to deal with usb_get_urb() nor usb_put_urb() anymore, so patch removes their usages in ehci-hcd. Patch also makes ehci_to_hcd(ehci)->self.bandwidth_allocated adjust, if a stream finishes. Signed-off-by: Karsten Wiese Cc: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-sched.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 07bcb931021..1d0b49e3f19 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -1536,7 +1536,7 @@ itd_link_urb ( struct ehci_itd, itd_list); list_move_tail (&itd->itd_list, &stream->td_list); itd->stream = iso_stream_get (stream); - itd->urb = usb_get_urb (urb); + itd->urb = urb; itd_init (ehci, stream, itd); } @@ -1645,7 +1645,7 @@ itd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (unlikely (list_empty (&stream->td_list))) { + if (unlikely(list_is_singular(&stream->td_list))) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, @@ -1656,7 +1656,6 @@ itd_complete ( iso_stream_put (ehci, stream); done: - usb_put_urb(urb); itd->urb = NULL; if (ehci->clock_frame != itd->frame || itd->index[7] != -1) { /* OK to recycle this ITD now. */ @@ -1949,7 +1948,7 @@ sitd_link_urb ( struct ehci_sitd, sitd_list); list_move_tail (&sitd->sitd_list, &stream->td_list); sitd->stream = iso_stream_get (stream); - sitd->urb = usb_get_urb (urb); + sitd->urb = urb; sitd_patch(ehci, stream, sitd, sched, packet); sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, @@ -2034,7 +2033,7 @@ sitd_complete ( (void) disable_periodic(ehci); ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (list_empty (&stream->td_list)) { + if (list_is_singular(&stream->td_list)) { ehci_to_hcd(ehci)->self.bandwidth_allocated -= stream->bandwidth; ehci_vdbg (ehci, @@ -2045,7 +2044,6 @@ sitd_complete ( iso_stream_put (ehci, stream); /* OK to recycle this SITD now that its completion callback ran. */ done: - usb_put_urb(urb); sitd->urb = NULL; sitd->stream = NULL; list_move(&sitd->sitd_list, &stream->free_list); -- cgit v1.2.3 From 391016f6e2fe3b9979b4c6880a76e5e434d6947c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 16 Mar 2009 14:21:56 -0400 Subject: USB: EHCI: expedite unlinks when the root hub is suspended This patch (as1225) fixes a bug in ehci-hcd. The condition for whether unlinked QHs can become IDLE should not be that the controller is halted, but rather that the controller isn't running. In other words when the root hub is suspended, the hardware doesn't own any QHs. This fixes a problem that can show up during hibernation: If a QH is only partially unlinked when the root hub is frozen, then when the root hub is thawed the QH won't be in the IDLE state. As a result it can't be used properly for new URB submissions. Signed-off-by: Alan Stern Reported-by: Brandon Philips Tested-by: Brandon Philips Acked-by: David Brownell Cc: Stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3712b925b31..ecc9b66c03c 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -1095,7 +1095,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) prev->qh_next = qh->qh_next; wmb (); - if (unlikely (ehci_to_hcd(ehci)->state == HC_STATE_HALT)) { + /* If the controller isn't running, we don't have to wait for it */ + if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) { /* if (unlikely (qh->reclaim != 0)) * this will recurse, probably not much */ -- cgit v1.2.3 From 0cc6bfe901b946df125d8e37186d8e45f876457d Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 12 Mar 2009 06:53:00 -0400 Subject: USB: Option: let cdc-acm handle Sony Ericsson F3507g / Dell 5530 The generic cdc-acm driver is now the best one to handle Sony Ericsson F3507g-based devices (which the Dell 5530 is a rebrand of), now that all the pieces are in place (ie, cac477e8f1038c41b6f29d3161ce351462ef3df7). Removing the IDs from option allows cdc-acm to handle the device. Signed-off-by: Dan Williams Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index ddd0a0b7e1a..3cf765b0bed 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -293,11 +293,6 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define ZTE_PRODUCT_MF626 0x0031 #define ZTE_PRODUCT_CDMA_TECH 0xfffe -/* Ericsson products */ -#define ERICSSON_VENDOR_ID 0x0bdb -#define ERICSSON_PRODUCT_F3507G_1 0x1900 -#define ERICSSON_PRODUCT_F3507G_2 0x1902 - #define BENQ_VENDOR_ID 0x04a5 #define BENQ_PRODUCT_H10 0x4068 @@ -443,7 +438,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_CINGULAR) }, /* Dell Wireless HSDPA 5520 == Novatel Expedite EU860D */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_L) }, /* Dell Wireless HSDPA 5520 */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5520_MINICARD_GENERIC_I) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */ - { USB_DEVICE(DELL_VENDOR_ID, 0x8147) }, /* Dell Wireless 5530 Mobile Broadband (3G HSPA) Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_SPRINT) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_TELUS) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ { USB_DEVICE(DELL_VENDOR_ID, DELL_PRODUCT_5730_MINICARD_VZW) }, /* Dell Wireless 5730 Mobile Broadband EVDO/HSPA Mini-Card */ @@ -515,8 +509,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF626) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_MF628) }, { USB_DEVICE(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH) }, - { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_1) }, - { USB_DEVICE(ERICSSON_VENDOR_ID, ERICSSON_PRODUCT_F3507G_2) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(0x1da5, 0x4515) }, /* BenQ H20 */ { } /* Terminating entry */ -- cgit v1.2.3 From 716a9c8561d9c50ec454f4fbd39a265892feda2c Mon Sep 17 00:00:00 2001 From: Moritz Muehlenhoff Date: Sat, 14 Mar 2009 00:43:21 +0100 Subject: USB: Updated unusual-devs entry for USB mass storage on Nokia 6233 Current firmware revision 5.60 still behaves the same, so update the quirk up a (non-existing) 99.99 revision. http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=493415 Signed-off-by: Moritz Muehlenhoff Tested-by: Jan Heitkoetter Cc: stable Signed-off-by: Phil Dibowitz --- drivers/usb/storage/unusual_devs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index bfa8db0d8aa..84ca4332e6b 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -226,7 +226,7 @@ UNUSUAL_DEV( 0x0421, 0x047c, 0x0370, 0x0610, US_FL_MAX_SECTORS_64 ), /* Reported by Manuel Osdoba */ -UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x0452, +UNUSUAL_DEV( 0x0421, 0x0492, 0x0452, 0x9999, "Nokia", "Nokia 6233", US_SC_DEVICE, US_PR_DEVICE, NULL, -- cgit v1.2.3 From 56a21827439a4d715b510bfaf488534e6f4ad2f8 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Sat, 14 Mar 2009 20:47:39 -0700 Subject: USB: Add Vendor/Product ID for new CDMA U727 to option driver * newer versions of the Novatel Wireless U727 CDMA 3G USB stick have a different Product ID (0x5010); adding this ID makes them work just fine with the option driver Signed-off-by: Dirk Hohndel Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 3cf765b0bed..d31fc2bcf77 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -197,6 +197,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po /* OVATION PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_MC727 0x4100 #define NOVATELWIRELESS_PRODUCT_MC950D 0x4400 +#define NOVATELWIRELESS_PRODUCT_U727 0x5010 /* FUTURE NOVATEL PRODUCTS */ #define NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED 0X6000 @@ -411,6 +412,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EU870D) }, /* Novatel EU850D/EU860D/EU870D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC950D) }, /* Novatel MC930D/MC950D */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_MC727) }, /* Novatel MC727/U727/USB727 */ + { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_U727) }, /* Novatel MC727/U727/USB727 */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_FULLSPEED) }, /* Novatel EVDO product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_HSPA_FULLSPEED) }, /* Novatel HSPA product */ { USB_DEVICE(NOVATELWIRELESS_VENDOR_ID, NOVATELWIRELESS_PRODUCT_EVDO_EMBEDDED_FULLSPEED) }, /* Novatel EVDO Embedded product */ -- cgit v1.2.3 From e7f2f0d77a7b483a26054f29ba8393831b25a8a4 Mon Sep 17 00:00:00 2001 From: Achilleas Kotsis Date: Mon, 16 Mar 2009 16:35:02 +0200 Subject: USB: Add device id for Option GTM380 to option driver Option GTM380 in Modem mode uses Product ID 0x7201. This has been tested and works on production systems for over 6 months. Signed-off-by: Achilleas Kotsis Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index d31fc2bcf77..61ebddc4849 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -89,6 +89,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define OPTION_PRODUCT_ETNA_MODEM_GT 0x7041 #define OPTION_PRODUCT_ETNA_MODEM_EX 0x7061 #define OPTION_PRODUCT_ETNA_KOI_MODEM 0x7100 +#define OPTION_PRODUCT_GTM380_MODEM 0x7201 #define HUAWEI_VENDOR_ID 0x12D1 #define HUAWEI_PRODUCT_E600 0x1001 @@ -322,6 +323,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_GT) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_MODEM_EX) }, { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_ETNA_KOI_MODEM) }, + { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_GTM380_MODEM) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q101) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_Q111) }, { USB_DEVICE(QUANTA_VENDOR_ID, QUANTA_PRODUCT_GLX) }, -- cgit v1.2.3 From 8a0845c51b2e300f5204a323b874f7f58ea0eff7 Mon Sep 17 00:00:00 2001 From: Thomas Bartosik Date: Mon, 16 Mar 2009 16:04:38 +0100 Subject: USB: storage: Unusual USB device Prolific 2507 variation added The "c-enter" USB to Toshiba 1.8" IDE enclosure needs special treatment to work flawlessly. This patch is absolutely trivial, as the integrated USB-IDE bridge is already identified to be an "unusual" device, only the bcdDevice is different (lower) to the bcdDeviceMin already included in the kernel. It is a Prolific 2507 bridge. T: Bus=02 Lev=01 Prnt=01 Port=02 Cnt=01 Dev#= 4 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=067b ProdID=2507 Rev= 0.01 S: Manufacturer=Prolific Technology Inc. S: Product=ATAPI-6 Bridge Controller S: SerialNumber=00000272 C:* #Ifs= 1 Cfg#= 1 Atr=c0 MxPwr=100mA I:* If#= 0 Alt= 0 #EPs= 2 Cls=08(stor.) Sub=06 Prot=50 Driver=usb-storage E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms Signed-off-by: Thomas Bartosik Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/unusual_devs.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 84ca4332e6b..cfde74a6faa 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -951,7 +951,9 @@ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, US_FL_FIX_CAPACITY ), /* Reported by Richard -=[]=- */ -UNUSUAL_DEV( 0x067b, 0x2507, 0x0100, 0x0100, +/* Change to bcdDeviceMin (0x0100 to 0x0001) reported by + * Thomas Bartosik */ +UNUSUAL_DEV( 0x067b, 0x2507, 0x0001, 0x0100, "Prolific Technology Inc.", "Mass Storage Device", US_SC_DEVICE, US_PR_DEVICE, NULL, -- cgit v1.2.3 From d0573facf21d1e5cfbc1ddac272b7592722e6c01 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 18 Mar 2009 09:22:17 -0700 Subject: Staging: benet: remove driver now that it is merged in drivers/net/ The benet driver is now in the proper place in drivers/net/benet, so we can remove the staging version. Acked-by: Sathya Perla Cc: David S. Miller Signed-off-by: Greg Kroah-Hartman --- drivers/staging/Kconfig | 2 - drivers/staging/Makefile | 1 - drivers/staging/benet/Kconfig | 7 - drivers/staging/benet/MAINTAINERS | 6 - drivers/staging/benet/Makefile | 14 - drivers/staging/benet/TODO | 6 - drivers/staging/benet/asyncmesg.h | 82 -- drivers/staging/benet/be_cm.h | 134 --- drivers/staging/benet/be_common.h | 53 -- drivers/staging/benet/be_ethtool.c | 348 -------- drivers/staging/benet/be_init.c | 1382 ----------------------------- drivers/staging/benet/be_int.c | 863 ------------------ drivers/staging/benet/be_netif.c | 705 --------------- drivers/staging/benet/benet.h | 429 --------- drivers/staging/benet/bestatus.h | 103 --- drivers/staging/benet/cev.h | 243 ----- drivers/staging/benet/cq.c | 211 ----- drivers/staging/benet/descriptors.h | 71 -- drivers/staging/benet/doorbells.h | 179 ---- drivers/staging/benet/ep.h | 66 -- drivers/staging/benet/eq.c | 299 ------- drivers/staging/benet/eth.c | 1273 -------------------------- drivers/staging/benet/etx_context.h | 55 -- drivers/staging/benet/funcobj.c | 565 ------------ drivers/staging/benet/fwcmd_common.h | 222 ----- drivers/staging/benet/fwcmd_common_bmap.h | 717 --------------- drivers/staging/benet/fwcmd_eth_bmap.h | 280 ------ drivers/staging/benet/fwcmd_hdr_bmap.h | 54 -- drivers/staging/benet/fwcmd_mcc.h | 94 -- drivers/staging/benet/fwcmd_opcodes.h | 244 ----- drivers/staging/benet/fwcmd_types_bmap.h | 29 - drivers/staging/benet/host_struct.h | 182 ---- drivers/staging/benet/hwlib.h | 830 ----------------- drivers/staging/benet/mpu.c | 1364 ---------------------------- drivers/staging/benet/mpu.h | 74 -- drivers/staging/benet/mpu_context.h | 46 - drivers/staging/benet/pcicfg.h | 825 ----------------- drivers/staging/benet/post_codes.h | 111 --- drivers/staging/benet/regmap.h | 68 -- 39 files changed, 12237 deletions(-) delete mode 100644 drivers/staging/benet/Kconfig delete mode 100644 drivers/staging/benet/MAINTAINERS delete mode 100644 drivers/staging/benet/Makefile delete mode 100644 drivers/staging/benet/TODO delete mode 100644 drivers/staging/benet/asyncmesg.h delete mode 100644 drivers/staging/benet/be_cm.h delete mode 100644 drivers/staging/benet/be_common.h delete mode 100644 drivers/staging/benet/be_ethtool.c delete mode 100644 drivers/staging/benet/be_init.c delete mode 100644 drivers/staging/benet/be_int.c delete mode 100644 drivers/staging/benet/be_netif.c delete mode 100644 drivers/staging/benet/benet.h delete mode 100644 drivers/staging/benet/bestatus.h delete mode 100644 drivers/staging/benet/cev.h delete mode 100644 drivers/staging/benet/cq.c delete mode 100644 drivers/staging/benet/descriptors.h delete mode 100644 drivers/staging/benet/doorbells.h delete mode 100644 drivers/staging/benet/ep.h delete mode 100644 drivers/staging/benet/eq.c delete mode 100644 drivers/staging/benet/eth.c delete mode 100644 drivers/staging/benet/etx_context.h delete mode 100644 drivers/staging/benet/funcobj.c delete mode 100644 drivers/staging/benet/fwcmd_common.h delete mode 100644 drivers/staging/benet/fwcmd_common_bmap.h delete mode 100644 drivers/staging/benet/fwcmd_eth_bmap.h delete mode 100644 drivers/staging/benet/fwcmd_hdr_bmap.h delete mode 100644 drivers/staging/benet/fwcmd_mcc.h delete mode 100644 drivers/staging/benet/fwcmd_opcodes.h delete mode 100644 drivers/staging/benet/fwcmd_types_bmap.h delete mode 100644 drivers/staging/benet/host_struct.h delete mode 100644 drivers/staging/benet/hwlib.h delete mode 100644 drivers/staging/benet/mpu.c delete mode 100644 drivers/staging/benet/mpu.h delete mode 100644 drivers/staging/benet/mpu_context.h delete mode 100644 drivers/staging/benet/pcicfg.h delete mode 100644 drivers/staging/benet/post_codes.h delete mode 100644 drivers/staging/benet/regmap.h (limited to 'drivers') diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index ce6badded47..211af86a6c5 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig @@ -73,8 +73,6 @@ source "drivers/staging/rt2860/Kconfig" source "drivers/staging/rt2870/Kconfig" -source "drivers/staging/benet/Kconfig" - source "drivers/staging/comedi/Kconfig" source "drivers/staging/asus_oled/Kconfig" diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 9ddcc2bb336..47a56f5ffab 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile @@ -19,7 +19,6 @@ obj-$(CONFIG_AGNX) += agnx/ obj-$(CONFIG_OTUS) += otus/ obj-$(CONFIG_RT2860) += rt2860/ obj-$(CONFIG_RT2870) += rt2870/ -obj-$(CONFIG_BENET) += benet/ obj-$(CONFIG_COMEDI) += comedi/ obj-$(CONFIG_ASUS_OLED) += asus_oled/ obj-$(CONFIG_PANEL) += panel/ diff --git a/drivers/staging/benet/Kconfig b/drivers/staging/benet/Kconfig deleted file mode 100644 index f6806074f99..00000000000 --- a/drivers/staging/benet/Kconfig +++ /dev/null @@ -1,7 +0,0 @@ -config BENET - tristate "ServerEngines 10Gb NIC - BladeEngine" - depends on PCI && INET - select INET_LRO - help - This driver implements the NIC functionality for ServerEngines - 10Gb network adapter BladeEngine (EC 3210). diff --git a/drivers/staging/benet/MAINTAINERS b/drivers/staging/benet/MAINTAINERS deleted file mode 100644 index d5ce340218b..00000000000 --- a/drivers/staging/benet/MAINTAINERS +++ /dev/null @@ -1,6 +0,0 @@ -SERVER ENGINES 10Gbe NIC - BLADE-ENGINE -P: Subbu Seetharaman -M: subbus@serverengines.com -L: netdev@vger.kernel.org -W: http://www.serverengines.com -S: Supported diff --git a/drivers/staging/benet/Makefile b/drivers/staging/benet/Makefile deleted file mode 100644 index 460b923b99b..00000000000 --- a/drivers/staging/benet/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Makefile to build the network driver for ServerEngine's BladeEngine -# -obj-$(CONFIG_BENET) += benet.o - -benet-y := be_init.o \ - be_int.o \ - be_netif.o \ - be_ethtool.o \ - funcobj.o \ - cq.o \ - eq.o \ - mpu.o \ - eth.o diff --git a/drivers/staging/benet/TODO b/drivers/staging/benet/TODO deleted file mode 100644 index a51dfb59a62..00000000000 --- a/drivers/staging/benet/TODO +++ /dev/null @@ -1,6 +0,0 @@ -TODO: - - remove wrappers around common iowrite functions - - full netdev audit of common problems/issues - -Please send all patches and questions to Subbu Seetharaman - and Greg Kroah-Hartman diff --git a/drivers/staging/benet/asyncmesg.h b/drivers/staging/benet/asyncmesg.h deleted file mode 100644 index d1e779adb84..00000000000 --- a/drivers/staging/benet/asyncmesg.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __asyncmesg_amap_h__ -#define __asyncmesg_amap_h__ -#include "fwcmd_common.h" - -/* --- ASYNC_EVENT_CODES --- */ -#define ASYNC_EVENT_CODE_LINK_STATE (1) -#define ASYNC_EVENT_CODE_ISCSI (2) - -/* --- ASYNC_LINK_STATES --- */ -#define ASYNC_EVENT_LINK_DOWN (0) /* Link Down on a port */ -#define ASYNC_EVENT_LINK_UP (1) /* Link Up on a port */ - -/* - * The last 4 bytes of the async events have this common format. It allows - * the driver to distinguish [link]MCC_CQ_ENTRY[/link] structs from - * asynchronous events. Both arrive on the same completion queue. This - * structure also contains the common fields used to decode the async event. - */ -struct BE_ASYNC_EVENT_TRAILER_AMAP { - u8 rsvd0[8]; /* DWORD 0 */ - u8 event_code[8]; /* DWORD 0 */ - u8 event_type[8]; /* DWORD 0 */ - u8 rsvd1[6]; /* DWORD 0 */ - u8 async_event; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ -} __packed; -struct ASYNC_EVENT_TRAILER_AMAP { - u32 dw[1]; -}; - -/* - * Applicable in Initiator, Target and NIC modes. - * A link state async event is seen by all device drivers as soon they - * create an MCC ring. Thereafter, anytime the link status changes the - * drivers will receive a link state async event. Notifications continue to - * be sent until a driver destroys its MCC ring. A link down event is - * reported when either port loses link. A link up event is reported - * when either port regains link. When BE's failover mechanism is enabled, a - * link down on the active port causes traffic to be diverted to the standby - * port by the BE's ARM firmware (assuming the standby port has link). In - * this case, the standy port assumes the active status. Note: when link is - * restored on the failed port, traffic continues on the currently active - * port. The ARM firmware does not attempt to 'fail back' traffic to - * the restored port. - */ -struct BE_ASYNC_EVENT_LINK_STATE_AMAP { - u8 port0_link_status[8]; - u8 port1_link_status[8]; - u8 active_port[8]; - u8 rsvd0[8]; /* DWORD 0 */ - u8 port0_duplex[8]; - u8 port0_speed[8]; - u8 port1_duplex[8]; - u8 port1_speed[8]; - u8 port0_fault[8]; - u8 port1_fault[8]; - u8 rsvd1[2][8]; /* DWORD 2 */ - struct BE_ASYNC_EVENT_TRAILER_AMAP trailer; -} __packed; -struct ASYNC_EVENT_LINK_STATE_AMAP { - u32 dw[4]; -}; -#endif /* __asyncmesg_amap_h__ */ diff --git a/drivers/staging/benet/be_cm.h b/drivers/staging/benet/be_cm.h deleted file mode 100644 index b7a1dfd20c3..00000000000 --- a/drivers/staging/benet/be_cm.h +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __be_cm_amap_h__ -#define __be_cm_amap_h__ -#include "be_common.h" -#include "etx_context.h" -#include "mpu_context.h" - -/* - * --- CEV_WATERMARK_ENUM --- - * CQ/EQ Watermark Encodings. Encoded as number of free entries in - * Queue when Watermark is reached. - */ -#define CEV_WMARK_0 (0) /* Watermark when Queue full */ -#define CEV_WMARK_16 (1) /* Watermark at 16 free entries */ -#define CEV_WMARK_32 (2) /* Watermark at 32 free entries */ -#define CEV_WMARK_48 (3) /* Watermark at 48 free entries */ -#define CEV_WMARK_64 (4) /* Watermark at 64 free entries */ -#define CEV_WMARK_80 (5) /* Watermark at 80 free entries */ -#define CEV_WMARK_96 (6) /* Watermark at 96 free entries */ -#define CEV_WMARK_112 (7) /* Watermark at 112 free entries */ -#define CEV_WMARK_128 (8) /* Watermark at 128 free entries */ -#define CEV_WMARK_144 (9) /* Watermark at 144 free entries */ -#define CEV_WMARK_160 (10) /* Watermark at 160 free entries */ -#define CEV_WMARK_176 (11) /* Watermark at 176 free entries */ -#define CEV_WMARK_192 (12) /* Watermark at 192 free entries */ -#define CEV_WMARK_208 (13) /* Watermark at 208 free entries */ -#define CEV_WMARK_224 (14) /* Watermark at 224 free entries */ -#define CEV_WMARK_240 (15) /* Watermark at 240 free entries */ - -/* - * --- CQ_CNT_ENUM --- - * Completion Queue Count Encodings. - */ -#define CEV_CQ_CNT_256 (0) /* CQ has 256 entries */ -#define CEV_CQ_CNT_512 (1) /* CQ has 512 entries */ -#define CEV_CQ_CNT_1024 (2) /* CQ has 1024 entries */ - -/* - * --- EQ_CNT_ENUM --- - * Event Queue Count Encodings. - */ -#define CEV_EQ_CNT_256 (0) /* EQ has 256 entries (16-byte EQEs only) */ -#define CEV_EQ_CNT_512 (1) /* EQ has 512 entries (16-byte EQEs only) */ -#define CEV_EQ_CNT_1024 (2) /* EQ has 1024 entries (4-byte or */ - /* 16-byte EQEs only) */ -#define CEV_EQ_CNT_2048 (3) /* EQ has 2048 entries (4-byte or */ - /* 16-byte EQEs only) */ -#define CEV_EQ_CNT_4096 (4) /* EQ has 4096 entries (4-byte EQEs only) */ - -/* - * --- EQ_SIZE_ENUM --- - * Event Queue Entry Size Encoding. - */ -#define CEV_EQ_SIZE_4 (0) /* EQE is 4 bytes */ -#define CEV_EQ_SIZE_16 (1) /* EQE is 16 bytes */ - -/* - * Completion Queue Context Table Entry. Contains the state of a CQ. - * Located in RAM within the CEV block. - */ -struct BE_CQ_CONTEXT_AMAP { - u8 Cidx[11]; /* DWORD 0 */ - u8 Watermark[4]; /* DWORD 0 */ - u8 NoDelay; /* DWORD 0 */ - u8 EPIdx[11]; /* DWORD 0 */ - u8 Count[2]; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ - u8 SolEvent; /* DWORD 0 */ - u8 Eventable; /* DWORD 0 */ - u8 Pidx[11]; /* DWORD 1 */ - u8 PD[10]; /* DWORD 1 */ - u8 EQID[7]; /* DWORD 1 */ - u8 Func; /* DWORD 1 */ - u8 WME; /* DWORD 1 */ - u8 Stalled; /* DWORD 1 */ - u8 Armed; /* DWORD 1 */ -} __packed; -struct CQ_CONTEXT_AMAP { - u32 dw[2]; -}; - -/* - * Event Queue Context Table Entry. Contains the state of an EQ. - * Located in RAM in the CEV block. - */ -struct BE_EQ_CONTEXT_AMAP { - u8 Cidx[13]; /* DWORD 0 */ - u8 rsvd0[2]; /* DWORD 0 */ - u8 Func; /* DWORD 0 */ - u8 EPIdx[13]; /* DWORD 0 */ - u8 valid; /* DWORD 0 */ - u8 rsvd1; /* DWORD 0 */ - u8 Size; /* DWORD 0 */ - u8 Pidx[13]; /* DWORD 1 */ - u8 rsvd2[3]; /* DWORD 1 */ - u8 PD[10]; /* DWORD 1 */ - u8 Count[3]; /* DWORD 1 */ - u8 SolEvent; /* DWORD 1 */ - u8 Stalled; /* DWORD 1 */ - u8 Armed; /* DWORD 1 */ - u8 Watermark[4]; /* DWORD 2 */ - u8 WME; /* DWORD 2 */ - u8 rsvd3[3]; /* DWORD 2 */ - u8 EventVect[6]; /* DWORD 2 */ - u8 rsvd4[2]; /* DWORD 2 */ - u8 Delay[8]; /* DWORD 2 */ - u8 rsvd5[6]; /* DWORD 2 */ - u8 TMR; /* DWORD 2 */ - u8 rsvd6; /* DWORD 2 */ - u8 rsvd7[32]; /* DWORD 3 */ -} __packed; -struct EQ_CONTEXT_AMAP { - u32 dw[4]; -}; - -#endif /* __be_cm_amap_h__ */ diff --git a/drivers/staging/benet/be_common.h b/drivers/staging/benet/be_common.h deleted file mode 100644 index 7e63dc5e334..00000000000 --- a/drivers/staging/benet/be_common.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __be_common_amap_h__ -#define __be_common_amap_h__ - -/* Physical Address. */ -struct BE_PHYS_ADDR_AMAP { - u8 lo[32]; /* DWORD 0 */ - u8 hi[32]; /* DWORD 1 */ -} __packed; -struct PHYS_ADDR_AMAP { - u32 dw[2]; -}; - -/* Virtual Address. */ -struct BE_VIRT_ADDR_AMAP { - u8 lo[32]; /* DWORD 0 */ - u8 hi[32]; /* DWORD 1 */ -} __packed; -struct VIRT_ADDR_AMAP { - u32 dw[2]; -}; - -/* Scatter gather element. */ -struct BE_SGE_AMAP { - u8 addr_hi[32]; /* DWORD 0 */ - u8 addr_lo[32]; /* DWORD 1 */ - u8 rsvd0[32]; /* DWORD 2 */ - u8 len[16]; /* DWORD 3 */ - u8 rsvd1[16]; /* DWORD 3 */ -} __packed; -struct SGE_AMAP { - u32 dw[4]; -}; - -#endif /* __be_common_amap_h__ */ diff --git a/drivers/staging/benet/be_ethtool.c b/drivers/staging/benet/be_ethtool.c deleted file mode 100644 index 027af85707a..00000000000 --- a/drivers/staging/benet/be_ethtool.c +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * be_ethtool.c - * - * This file contains various functions that ethtool can use - * to talk to the driver and the BE H/W. - */ - -#include "benet.h" - -#include - -static const char benet_gstrings_stats[][ETH_GSTRING_LEN] = { -/* net_device_stats */ - "rx_packets", - "tx_packets", - "rx_bytes", - "tx_bytes", - "rx_errors", - "tx_errors", - "rx_dropped", - "tx_dropped", - "multicast", - "collisions", - "rx_length_errors", - "rx_over_errors", - "rx_crc_errors", - "rx_frame_errors", - "rx_fifo_errors", - "rx_missed_errors", - "tx_aborted_errors", - "tx_carrier_errors", - "tx_fifo_errors", - "tx_heartbeat_errors", - "tx_window_errors", - "rx_compressed", - "tc_compressed", -/* BE driver Stats */ - "bes_tx_reqs", - "bes_tx_fails", - "bes_fwd_reqs", - "bes_tx_wrbs", - "bes_interrupts", - "bes_events", - "bes_tx_events", - "bes_rx_events", - "bes_tx_compl", - "bes_rx_compl", - "bes_ethrx_post_fail", - "bes_802_3_dropped_frames", - "bes_802_3_malformed_frames", - "bes_rx_misc_pkts", - "bes_eth_tx_rate", - "bes_eth_rx_rate", - "Num Packets collected", - "Num Times Flushed", -}; - -#define NET_DEV_STATS_LEN \ - (sizeof(struct net_device_stats)/sizeof(unsigned long)) - -#define BENET_STATS_LEN ARRAY_SIZE(benet_gstrings_stats) - -static void -be_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - strncpy(drvinfo->driver, be_driver_name, 32); - strncpy(drvinfo->version, be_drvr_ver, 32); - strncpy(drvinfo->fw_version, be_fw_ver, 32); - strcpy(drvinfo->bus_info, pci_name(adapter->pdev)); - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = 0; - drvinfo->eedump_len = 0; -} - -static int -be_get_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - coalesce->rx_max_coalesced_frames = adapter->max_rx_coal; - - coalesce->rx_coalesce_usecs = adapter->cur_eqd; - coalesce->rx_coalesce_usecs_high = adapter->max_eqd; - coalesce->rx_coalesce_usecs_low = adapter->min_eqd; - - coalesce->tx_coalesce_usecs = adapter->cur_eqd; - coalesce->tx_coalesce_usecs_high = adapter->max_eqd; - coalesce->tx_coalesce_usecs_low = adapter->min_eqd; - - coalesce->use_adaptive_rx_coalesce = adapter->enable_aic; - coalesce->use_adaptive_tx_coalesce = adapter->enable_aic; - - return 0; -} - -/* - * This routine is used to set interrup coalescing delay *as well as* - * the number of pkts to coalesce for LRO. - */ -static int -be_set_coalesce(struct net_device *netdev, struct ethtool_coalesce *coalesce) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - struct be_eq_object *eq_objectp; - u32 max, min, cur; - int status; - - adapter->max_rx_coal = coalesce->rx_max_coalesced_frames; - if (adapter->max_rx_coal >= BE_LRO_MAX_PKTS) - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - if (adapter->enable_aic == 0 && - coalesce->use_adaptive_rx_coalesce == 1) { - /* if AIC is being turned on now, start with an EQD of 0 */ - adapter->cur_eqd = 0; - } - adapter->enable_aic = coalesce->use_adaptive_rx_coalesce; - - /* round off to nearest multiple of 8 */ - max = (((coalesce->rx_coalesce_usecs_high + 4) >> 3) << 3); - min = (((coalesce->rx_coalesce_usecs_low + 4) >> 3) << 3); - cur = (((coalesce->rx_coalesce_usecs + 4) >> 3) << 3); - - if (adapter->enable_aic) { - /* accept low and high if AIC is enabled */ - if (max > MAX_EQD) - max = MAX_EQD; - if (min > max) - min = max; - adapter->max_eqd = max; - adapter->min_eqd = min; - if (adapter->cur_eqd > max) - adapter->cur_eqd = max; - if (adapter->cur_eqd < min) - adapter->cur_eqd = min; - } else { - /* accept specified coalesce_usecs only if AIC is disabled */ - if (cur > MAX_EQD) - cur = MAX_EQD; - eq_objectp = &pnob->event_q_obj; - status = - be_eq_modify_delay(&pnob->fn_obj, 1, &eq_objectp, &cur, - NULL, NULL, NULL); - if (status == BE_SUCCESS) - adapter->cur_eqd = cur; - } - return 0; -} - -static u32 be_get_rx_csum(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - return adapter->rx_csum; -} - -static int be_set_rx_csum(struct net_device *netdev, uint32_t data) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - if (data) - adapter->rx_csum = 1; - else - adapter->rx_csum = 0; - - return 0; -} - -static void -be_get_strings(struct net_device *netdev, uint32_t stringset, uint8_t *data) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(data, *benet_gstrings_stats, - sizeof(benet_gstrings_stats)); - break; - } -} - -static int be_get_stats_count(struct net_device *netdev) -{ - return BENET_STATS_LEN; -} - -static void -be_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, uint64_t *data) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - int i; - - benet_get_stats(netdev); - - for (i = 0; i <= NET_DEV_STATS_LEN; i++) - data[i] = ((unsigned long *)&adapter->benet_stats)[i]; - - data[i] = adapter->be_stat.bes_tx_reqs; - data[i++] = adapter->be_stat.bes_tx_fails; - data[i++] = adapter->be_stat.bes_fwd_reqs; - data[i++] = adapter->be_stat.bes_tx_wrbs; - - data[i++] = adapter->be_stat.bes_ints; - data[i++] = adapter->be_stat.bes_events; - data[i++] = adapter->be_stat.bes_tx_events; - data[i++] = adapter->be_stat.bes_rx_events; - data[i++] = adapter->be_stat.bes_tx_compl; - data[i++] = adapter->be_stat.bes_rx_compl; - data[i++] = adapter->be_stat.bes_ethrx_post_fail; - data[i++] = adapter->be_stat.bes_802_3_dropped_frames; - data[i++] = adapter->be_stat.bes_802_3_malformed_frames; - data[i++] = adapter->be_stat.bes_rx_misc_pkts; - data[i++] = adapter->be_stat.bes_eth_tx_rate; - data[i++] = adapter->be_stat.bes_eth_rx_rate; - data[i++] = adapter->be_stat.bes_rx_coal; - data[i++] = adapter->be_stat.bes_rx_flush; - -} - -static int be_get_settings(struct net_device *netdev, struct ethtool_cmd *ecmd) -{ - ecmd->speed = SPEED_10000; - ecmd->duplex = DUPLEX_FULL; - ecmd->autoneg = AUTONEG_DISABLE; - return 0; -} - -/* Get the Ring parameters from the pnob */ -static void -be_get_ringparam(struct net_device *netdev, struct ethtool_ringparam *ring) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - /* Pre Set Maxims */ - ring->rx_max_pending = pnob->rx_q_len; - ring->rx_mini_max_pending = ring->rx_mini_max_pending; - ring->rx_jumbo_max_pending = ring->rx_jumbo_max_pending; - ring->tx_max_pending = pnob->tx_q_len; - - /* Current hardware Settings */ - ring->rx_pending = atomic_read(&pnob->rx_q_posted); - ring->rx_mini_pending = ring->rx_mini_pending; - ring->rx_jumbo_pending = ring->rx_jumbo_pending; - ring->tx_pending = atomic_read(&pnob->tx_q_used); - -} - -static void -be_get_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) -{ - struct be_net_object *pnob = netdev_priv(netdev); - bool rxfc, txfc; - int status; - - status = be_eth_get_flow_control(&pnob->fn_obj, &txfc, &rxfc); - if (status != BE_SUCCESS) { - dev_info(&netdev->dev, "Unable to get pause frame settings\n"); - /* return defaults */ - ecmd->rx_pause = 1; - ecmd->tx_pause = 0; - ecmd->autoneg = AUTONEG_ENABLE; - return; - } - - if (txfc == true) - ecmd->tx_pause = 1; - else - ecmd->tx_pause = 0; - - if (rxfc == true) - ecmd->rx_pause = 1; - else - ecmd->rx_pause = 0; - - ecmd->autoneg = AUTONEG_ENABLE; -} - -static int -be_set_pauseparam(struct net_device *netdev, struct ethtool_pauseparam *ecmd) -{ - struct be_net_object *pnob = netdev_priv(netdev); - bool txfc, rxfc; - int status; - - if (ecmd->autoneg != AUTONEG_ENABLE) - return -EINVAL; - - if (ecmd->tx_pause) - txfc = true; - else - txfc = false; - - if (ecmd->rx_pause) - rxfc = true; - else - rxfc = false; - - status = be_eth_set_flow_control(&pnob->fn_obj, txfc, rxfc); - if (status != BE_SUCCESS) { - dev_info(&netdev->dev, "Unable to set pause frame settings\n"); - return -1; - } - return 0; -} - -struct ethtool_ops be_ethtool_ops = { - .get_settings = be_get_settings, - .get_drvinfo = be_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_coalesce = be_get_coalesce, - .set_coalesce = be_set_coalesce, - .get_ringparam = be_get_ringparam, - .get_pauseparam = be_get_pauseparam, - .set_pauseparam = be_set_pauseparam, - .get_rx_csum = be_get_rx_csum, - .set_rx_csum = be_set_rx_csum, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = ethtool_op_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, - .get_strings = be_get_strings, - .get_stats_count = be_get_stats_count, - .get_ethtool_stats = be_get_ethtool_stats, -}; diff --git a/drivers/staging/benet/be_init.c b/drivers/staging/benet/be_init.c deleted file mode 100644 index 12a026c3f9e..00000000000 --- a/drivers/staging/benet/be_init.c +++ /dev/null @@ -1,1382 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include "benet.h" - -#define DRVR_VERSION "1.0.728" - -static const struct pci_device_id be_device_id_table[] = { - {PCI_DEVICE(0x19a2, 0x0201)}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, be_device_id_table); - -MODULE_VERSION(DRVR_VERSION); - -#define DRV_DESCRIPTION "ServerEngines BladeEngine Network Driver Version " - -MODULE_DESCRIPTION(DRV_DESCRIPTION DRVR_VERSION); -MODULE_AUTHOR("ServerEngines"); -MODULE_LICENSE("GPL"); - -static unsigned int msix = 1; -module_param(msix, uint, S_IRUGO); -MODULE_PARM_DESC(msix, "Use MSI-x interrupts"); - -static unsigned int rxbuf_size = 2048; /* Default RX frag size */ -module_param(rxbuf_size, uint, S_IRUGO); -MODULE_PARM_DESC(rxbuf_size, "Size of buffers to hold Rx data"); - -const char be_drvr_ver[] = DRVR_VERSION; -char be_fw_ver[32]; /* F/W version filled in by be_probe */ -char be_driver_name[] = "benet"; - -/* - * Number of entries in each queue. - */ -#define EVENT_Q_LEN 1024 -#define ETH_TXQ_LEN 2048 -#define ETH_TXCQ_LEN 1024 -#define ETH_RXQ_LEN 1024 /* Does not support any other value */ -#define ETH_UC_RXCQ_LEN 1024 -#define ETH_BC_RXCQ_LEN 256 -#define MCC_Q_LEN 64 /* total size not to exceed 8 pages */ -#define MCC_CQ_LEN 256 - -/* Bit mask describing events of interest to be traced */ -unsigned int trace_level; - -static int -init_pci_be_function(struct be_adapter *adapter, struct pci_dev *pdev) -{ - u64 pa; - - /* CSR */ - pa = pci_resource_start(pdev, 2); - adapter->csr_va = ioremap_nocache(pa, pci_resource_len(pdev, 2)); - if (adapter->csr_va == NULL) - return -ENOMEM; - - /* Door Bell */ - pa = pci_resource_start(pdev, 4); - adapter->db_va = ioremap_nocache(pa, (128 * 1024)); - if (adapter->db_va == NULL) { - iounmap(adapter->csr_va); - return -ENOMEM; - } - - /* PCI */ - pa = pci_resource_start(pdev, 1); - adapter->pci_va = ioremap_nocache(pa, pci_resource_len(pdev, 1)); - if (adapter->pci_va == NULL) { - iounmap(adapter->csr_va); - iounmap(adapter->db_va); - return -ENOMEM; - } - return 0; -} - -/* - This function enables the interrupt corresponding to the Event - queue ID for the given NetObject -*/ -void be_enable_eq_intr(struct be_net_object *pnob) -{ - struct CQ_DB_AMAP cqdb; - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - This function disables the interrupt corresponding to the Event - queue ID for the given NetObject -*/ -void be_disable_eq_intr(struct be_net_object *pnob) -{ - struct CQ_DB_AMAP cqdb; - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, event, &cqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, 0); - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, pnob->event_q_id); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - This function enables the interrupt from the network function - of the BladeEngine. Use the function be_disable_eq_intr() - to enable the interrupt from the event queue of only one specific - NetObject -*/ -void be_enable_intr(struct be_net_object *pnob) -{ - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - u32 host_intr; - - ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (!host_intr) { - AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw, 1); - PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl, - ctrl.dw[0]); - } -} - -/* - This function disables the interrupt from the network function of - the BladeEngine. Use the function be_disable_eq_intr() to - disable the interrupt from the event queue of only one specific NetObject -*/ -void be_disable_intr(struct be_net_object *pnob) -{ - - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - u32 host_intr; - ctrl.dw[0] = PCICFG1_READ(&pnob->fn_obj, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (host_intr) { - AMAP_SET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, hostintr, - ctrl.dw, 0); - PCICFG1_WRITE(&pnob->fn_obj, host_timer_int_ctrl, - ctrl.dw[0]); - } -} - -static int be_enable_msix(struct be_adapter *adapter) -{ - int i, ret; - - if (!msix) - return -1; - - for (i = 0; i < BE_MAX_REQ_MSIX_VECTORS; i++) - adapter->msix_entries[i].entry = i; - - ret = pci_enable_msix(adapter->pdev, adapter->msix_entries, - BE_MAX_REQ_MSIX_VECTORS); - - if (ret == 0) - adapter->msix_enabled = 1; - return ret; -} - -static int be_register_isr(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - struct net_device *netdev = pnob->netdev; - int intx = 0, r; - - netdev->irq = adapter->pdev->irq; - r = be_enable_msix(adapter); - - if (r == 0) { - r = request_irq(adapter->msix_entries[0].vector, - be_int, IRQF_SHARED, netdev->name, netdev); - if (r) { - printk(KERN_WARNING - "MSIX Request IRQ failed - Errno %d\n", r); - intx = 1; - pci_disable_msix(adapter->pdev); - adapter->msix_enabled = 0; - } - } else { - intx = 1; - } - - if (intx) { - r = request_irq(netdev->irq, be_int, IRQF_SHARED, - netdev->name, netdev); - if (r) { - printk(KERN_WARNING - "INTx Request IRQ failed - Errno %d\n", r); - return -1; - } - } - adapter->isr_registered = 1; - return 0; -} - -static void be_unregister_isr(struct be_adapter *adapter) -{ - struct net_device *netdev = adapter->netdevp; - if (adapter->isr_registered) { - if (adapter->msix_enabled) { - free_irq(adapter->msix_entries[0].vector, netdev); - pci_disable_msix(adapter->pdev); - adapter->msix_enabled = 0; - } else { - free_irq(netdev->irq, netdev); - } - adapter->isr_registered = 0; - } -} - -/* - This function processes the Flush Completions that are issued by the - ARM F/W, when a Recv Ring is destroyed. A flush completion is - identified when a Rx COmpl descriptor has the tcpcksum and udpcksum - set and the pktsize is 32. These completions are received on the - Rx Completion Queue. -*/ -static u32 be_process_rx_flush_cmpl(struct be_net_object *pnob) -{ - struct ETH_RX_COMPL_AMAP *rxcp; - unsigned int i = 0; - while ((rxcp = be_get_rx_cmpl(pnob)) != NULL) { - be_notify_cmpl(pnob, 1, pnob->rx_cq_id, 1); - i++; - } - return i; -} - -static void be_tx_q_clean(struct be_net_object *pnob) -{ - while (atomic_read(&pnob->tx_q_used)) - process_one_tx_compl(pnob, tx_compl_lastwrb_idx_get(pnob)); -} - -static void be_rx_q_clean(struct be_net_object *pnob) -{ - if (pnob->rx_ctxt) { - int i; - struct be_rx_page_info *rx_page_info; - for (i = 0; i < pnob->rx_q_len; i++) { - rx_page_info = &(pnob->rx_page_info[i]); - if (!pnob->rx_pg_shared || rx_page_info->page_offset) { - pci_unmap_page(pnob->adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - pnob->rx_buf_size, - PCI_DMA_FROMDEVICE); - } - if (rx_page_info->page) - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - } - pnob->rx_pg_info_hd = 0; - } -} - -static void be_destroy_netobj(struct be_net_object *pnob) -{ - int status; - - if (pnob->tx_q_created) { - status = be_eth_sq_destroy(&pnob->tx_q_obj); - pnob->tx_q_created = 0; - } - - if (pnob->rx_q_created) { - status = be_eth_rq_destroy(&pnob->rx_q_obj); - if (status != 0) { - status = be_eth_rq_destroy_options(&pnob->rx_q_obj, 0, - NULL, NULL); - BUG_ON(status); - } - pnob->rx_q_created = 0; - } - - be_process_rx_flush_cmpl(pnob); - - if (pnob->tx_cq_created) { - status = be_cq_destroy(&pnob->tx_cq_obj); - pnob->tx_cq_created = 0; - } - - if (pnob->rx_cq_created) { - status = be_cq_destroy(&pnob->rx_cq_obj); - pnob->rx_cq_created = 0; - } - - if (pnob->mcc_q_created) { - status = be_mcc_ring_destroy(&pnob->mcc_q_obj); - pnob->mcc_q_created = 0; - } - if (pnob->mcc_cq_created) { - status = be_cq_destroy(&pnob->mcc_cq_obj); - pnob->mcc_cq_created = 0; - } - - if (pnob->event_q_created) { - status = be_eq_destroy(&pnob->event_q_obj); - pnob->event_q_created = 0; - } - be_function_cleanup(&pnob->fn_obj); -} - -/* - * free all resources associated with a pnob - * Called at the time of module cleanup as well a any error during - * module init. Some resources may be partially allocated in a NetObj. - */ -static void netobject_cleanup(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - struct net_device *netdev = adapter->netdevp; - - if (netif_running(netdev)) { - netif_stop_queue(netdev); - be_wait_nic_tx_cmplx_cmpl(pnob); - be_disable_eq_intr(pnob); - } - - be_unregister_isr(adapter); - - if (adapter->tasklet_started) { - tasklet_kill(&(adapter->sts_handler)); - adapter->tasklet_started = 0; - } - if (pnob->fn_obj_created) - be_disable_intr(pnob); - - if (adapter->dev_state != BE_DEV_STATE_NONE) - unregister_netdev(netdev); - - if (pnob->fn_obj_created) - be_destroy_netobj(pnob); - - adapter->net_obj = NULL; - adapter->netdevp = NULL; - - be_rx_q_clean(pnob); - if (pnob->rx_ctxt) { - kfree(pnob->rx_page_info); - kfree(pnob->rx_ctxt); - } - - be_tx_q_clean(pnob); - kfree(pnob->tx_ctxt); - - if (pnob->mcc_q) - pci_free_consistent(adapter->pdev, pnob->mcc_q_size, - pnob->mcc_q, pnob->mcc_q_bus); - - if (pnob->mcc_wrb_ctxt) - free_pages((unsigned long)pnob->mcc_wrb_ctxt, - get_order(pnob->mcc_wrb_ctxt_size)); - - if (pnob->mcc_cq) - pci_free_consistent(adapter->pdev, pnob->mcc_cq_size, - pnob->mcc_cq, pnob->mcc_cq_bus); - - if (pnob->event_q) - pci_free_consistent(adapter->pdev, pnob->event_q_size, - pnob->event_q, pnob->event_q_bus); - - if (pnob->tx_cq) - pci_free_consistent(adapter->pdev, pnob->tx_cq_size, - pnob->tx_cq, pnob->tx_cq_bus); - - if (pnob->tx_q) - pci_free_consistent(adapter->pdev, pnob->tx_q_size, - pnob->tx_q, pnob->tx_q_bus); - - if (pnob->rx_q) - pci_free_consistent(adapter->pdev, pnob->rx_q_size, - pnob->rx_q, pnob->rx_q_bus); - - if (pnob->rx_cq) - pci_free_consistent(adapter->pdev, pnob->rx_cq_size, - pnob->rx_cq, pnob->rx_cq_bus); - - - if (pnob->mb_ptr) - pci_free_consistent(adapter->pdev, pnob->mb_size, pnob->mb_ptr, - pnob->mb_bus); - - free_netdev(netdev); -} - - -static int be_nob_ring_alloc(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - u32 size; - - /* Mail box rd; mailbox pointer needs to be 16 byte aligned */ - pnob->mb_size = sizeof(struct MCC_MAILBOX_AMAP) + 16; - pnob->mb_ptr = pci_alloc_consistent(adapter->pdev, pnob->mb_size, - &pnob->mb_bus); - if (!pnob->mb_bus) - return -1; - memset(pnob->mb_ptr, 0, pnob->mb_size); - pnob->mb_rd.va = PTR_ALIGN(pnob->mb_ptr, 16); - pnob->mb_rd.pa = PTR_ALIGN(pnob->mb_bus, 16); - pnob->mb_rd.length = sizeof(struct MCC_MAILBOX_AMAP); - /* - * Event queue - */ - pnob->event_q_len = EVENT_Q_LEN; - pnob->event_q_size = pnob->event_q_len * sizeof(struct EQ_ENTRY_AMAP); - pnob->event_q = pci_alloc_consistent(adapter->pdev, pnob->event_q_size, - &pnob->event_q_bus); - if (!pnob->event_q_bus) - return -1; - memset(pnob->event_q, 0, pnob->event_q_size); - /* - * Eth TX queue - */ - pnob->tx_q_len = ETH_TXQ_LEN; - pnob->tx_q_port = 0; - pnob->tx_q_size = pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP); - pnob->tx_q = pci_alloc_consistent(adapter->pdev, pnob->tx_q_size, - &pnob->tx_q_bus); - if (!pnob->tx_q_bus) - return -1; - memset(pnob->tx_q, 0, pnob->tx_q_size); - /* - * Eth TX Compl queue - */ - pnob->txcq_len = ETH_TXCQ_LEN; - pnob->tx_cq_size = pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP); - pnob->tx_cq = pci_alloc_consistent(adapter->pdev, pnob->tx_cq_size, - &pnob->tx_cq_bus); - if (!pnob->tx_cq_bus) - return -1; - memset(pnob->tx_cq, 0, pnob->tx_cq_size); - /* - * Eth RX queue - */ - pnob->rx_q_len = ETH_RXQ_LEN; - pnob->rx_q_size = pnob->rx_q_len * sizeof(struct ETH_RX_D_AMAP); - pnob->rx_q = pci_alloc_consistent(adapter->pdev, pnob->rx_q_size, - &pnob->rx_q_bus); - if (!pnob->rx_q_bus) - return -1; - memset(pnob->rx_q, 0, pnob->rx_q_size); - /* - * Eth Unicast RX Compl queue - */ - pnob->rx_cq_len = ETH_UC_RXCQ_LEN; - pnob->rx_cq_size = pnob->rx_cq_len * - sizeof(struct ETH_RX_COMPL_AMAP); - pnob->rx_cq = pci_alloc_consistent(adapter->pdev, pnob->rx_cq_size, - &pnob->rx_cq_bus); - if (!pnob->rx_cq_bus) - return -1; - memset(pnob->rx_cq, 0, pnob->rx_cq_size); - - /* TX resources */ - size = pnob->tx_q_len * sizeof(void **); - pnob->tx_ctxt = kzalloc(size, GFP_KERNEL); - if (pnob->tx_ctxt == NULL) - return -1; - - /* RX resources */ - size = pnob->rx_q_len * sizeof(void *); - pnob->rx_ctxt = kzalloc(size, GFP_KERNEL); - if (pnob->rx_ctxt == NULL) - return -1; - - size = (pnob->rx_q_len * sizeof(struct be_rx_page_info)); - pnob->rx_page_info = kzalloc(size, GFP_KERNEL); - if (pnob->rx_page_info == NULL) - return -1; - - adapter->eth_statsp = kzalloc(sizeof(struct FWCMD_ETH_GET_STATISTICS), - GFP_KERNEL); - if (adapter->eth_statsp == NULL) - return -1; - pnob->rx_buf_size = rxbuf_size; - return 0; -} - -/* - This function initializes the be_net_object for subsequent - network operations. - - Before calling this function, the driver must have allocated - space for the NetObject structure, initialized the structure, - allocated DMAable memory for all the network queues that form - part of the NetObject and populated the start address (virtual) - and number of entries allocated for each queue in the NetObject structure. - - The driver must also have allocated memory to hold the - mailbox structure (MCC_MAILBOX) and post the physical address, - virtual addresses and the size of the mailbox memory in the - NetObj.mb_rd. This structure is used by BECLIB for - initial communication with the embedded MCC processor. BECLIB - uses the mailbox until MCC rings are created for more efficient - communication with the MCC processor. - - If the driver wants to create multiple network interface for more - than one protection domain, it can call be_create_netobj() - multiple times once for each protection domain. A Maximum of - 32 protection domains are supported. - -*/ -static int -be_create_netobj(struct be_net_object *pnob, u8 __iomem *csr_va, - u8 __iomem *db_va, u8 __iomem *pci_va) -{ - int status = 0; - bool eventable = false, tx_no_delay = false, rx_no_delay = false; - struct be_eq_object *eq_objectp = NULL; - struct be_function_object *pfob = &pnob->fn_obj; - struct ring_desc rd; - u32 set_rxbuf_size; - u32 tx_cmpl_wm = CEV_WMARK_96; /* 0xffffffff to disable */ - u32 rx_cmpl_wm = CEV_WMARK_160; /* 0xffffffff to disable */ - u32 eq_delay = 0; /* delay in 8usec units. 0xffffffff to disable */ - - memset(&rd, 0, sizeof(struct ring_desc)); - - status = be_function_object_create(csr_va, db_va, pci_va, - BE_FUNCTION_TYPE_NETWORK, &pnob->mb_rd, pfob); - if (status != BE_SUCCESS) - return status; - pnob->fn_obj_created = true; - - if (tx_cmpl_wm == 0xffffffff) - tx_no_delay = true; - if (rx_cmpl_wm == 0xffffffff) - rx_no_delay = true; - /* - * now create the necessary rings - * Event Queue first. - */ - if (pnob->event_q_len) { - rd.va = pnob->event_q; - rd.pa = pnob->event_q_bus; - rd.length = pnob->event_q_size; - - status = be_eq_create(pfob, &rd, 4, pnob->event_q_len, - (u32) -1, /* CEV_WMARK_* or -1 */ - eq_delay, /* in 8us units, or -1 */ - &pnob->event_q_obj); - if (status != BE_SUCCESS) - goto error_ret; - pnob->event_q_id = pnob->event_q_obj.eq_id; - pnob->event_q_created = 1; - eventable = true; - eq_objectp = &pnob->event_q_obj; - } - /* - * Now Eth Tx Compl. queue. - */ - if (pnob->txcq_len) { - rd.va = pnob->tx_cq; - rd.pa = pnob->tx_cq_bus; - rd.length = pnob->tx_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->txcq_len * sizeof(struct ETH_TX_COMPL_AMAP), - false, /* solicted events, */ - tx_no_delay, /* nodelay */ - tx_cmpl_wm, /* Watermark encodings */ - eq_objectp, &pnob->tx_cq_obj); - if (status != BE_SUCCESS) - goto error_ret; - - pnob->tx_cq_id = pnob->tx_cq_obj.cq_id; - pnob->tx_cq_created = 1; - } - /* - * Eth Tx queue - */ - if (pnob->tx_q_len) { - struct be_eth_sq_parameters ex_params = { 0 }; - u32 type; - - if (pnob->tx_q_port) { - /* TXQ to be bound to a specific port */ - type = BE_ETH_TX_RING_TYPE_BOUND; - ex_params.port = pnob->tx_q_port - 1; - } else - type = BE_ETH_TX_RING_TYPE_STANDARD; - - rd.va = pnob->tx_q; - rd.pa = pnob->tx_q_bus; - rd.length = pnob->tx_q_size; - - status = be_eth_sq_create_ex(pfob, &rd, - pnob->tx_q_len * sizeof(struct ETH_WRB_AMAP), - type, 2, &pnob->tx_cq_obj, - &ex_params, &pnob->tx_q_obj); - - if (status != BE_SUCCESS) - goto error_ret; - - pnob->tx_q_id = pnob->tx_q_obj.bid; - pnob->tx_q_created = 1; - } - /* - * Now Eth Rx compl. queue. Always needed. - */ - rd.va = pnob->rx_cq; - rd.pa = pnob->rx_cq_bus; - rd.length = pnob->rx_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->rx_cq_len * sizeof(struct ETH_RX_COMPL_AMAP), - false, /* solicted events, */ - rx_no_delay, /* nodelay */ - rx_cmpl_wm, /* Watermark encodings */ - eq_objectp, &pnob->rx_cq_obj); - if (status != BE_SUCCESS) - goto error_ret; - - pnob->rx_cq_id = pnob->rx_cq_obj.cq_id; - pnob->rx_cq_created = 1; - - status = be_eth_rq_set_frag_size(pfob, pnob->rx_buf_size, - (u32 *) &set_rxbuf_size); - if (status != BE_SUCCESS) { - be_eth_rq_get_frag_size(pfob, (u32 *) &pnob->rx_buf_size); - if ((pnob->rx_buf_size != 2048) && (pnob->rx_buf_size != 4096) - && (pnob->rx_buf_size != 8192)) - goto error_ret; - } else { - if (pnob->rx_buf_size != set_rxbuf_size) - pnob->rx_buf_size = set_rxbuf_size; - } - /* - * Eth RX queue. be_eth_rq_create() always assumes 2 pages size - */ - rd.va = pnob->rx_q; - rd.pa = pnob->rx_q_bus; - rd.length = pnob->rx_q_size; - - status = be_eth_rq_create(pfob, &rd, &pnob->rx_cq_obj, - &pnob->rx_cq_obj, &pnob->rx_q_obj); - - if (status != BE_SUCCESS) - goto error_ret; - - pnob->rx_q_id = pnob->rx_q_obj.rid; - pnob->rx_q_created = 1; - - return BE_SUCCESS; /* All required queues created. */ - -error_ret: - be_destroy_netobj(pnob); - return status; -} - -static int be_nob_ring_init(struct be_adapter *adapter, - struct be_net_object *pnob) -{ - int status; - - pnob->event_q_tl = 0; - - pnob->tx_q_hd = 0; - pnob->tx_q_tl = 0; - - pnob->tx_cq_tl = 0; - - pnob->rx_cq_tl = 0; - - memset(pnob->event_q, 0, pnob->event_q_size); - memset(pnob->tx_cq, 0, pnob->tx_cq_size); - memset(pnob->tx_ctxt, 0, pnob->tx_q_len * sizeof(void **)); - memset(pnob->rx_ctxt, 0, pnob->rx_q_len * sizeof(void *)); - pnob->rx_pg_info_hd = 0; - pnob->rx_q_hd = 0; - atomic_set(&pnob->rx_q_posted, 0); - - status = be_create_netobj(pnob, adapter->csr_va, adapter->db_va, - adapter->pci_va); - if (status != BE_SUCCESS) - return -1; - - be_post_eth_rx_buffs(pnob); - return 0; -} - -/* This function handles async callback for link status */ -static void -be_link_status_async_callback(void *context, u32 event_code, void *event) -{ - struct ASYNC_EVENT_LINK_STATE_AMAP *link_status = event; - struct be_adapter *adapter = context; - bool link_enable = false; - struct be_net_object *pnob; - struct ASYNC_EVENT_TRAILER_AMAP *async_trailer; - struct net_device *netdev; - u32 async_event_code, async_event_type, active_port; - u32 port0_link_status, port1_link_status, port0_duplex, port1_duplex; - u32 port0_speed, port1_speed; - - if (event_code != ASYNC_EVENT_CODE_LINK_STATE) { - /* Not our event to handle */ - return; - } - async_trailer = (struct ASYNC_EVENT_TRAILER_AMAP *) - ((u8 *) event + sizeof(struct MCC_CQ_ENTRY_AMAP) - - sizeof(struct ASYNC_EVENT_TRAILER_AMAP)); - - async_event_code = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_code, - async_trailer); - BUG_ON(async_event_code != ASYNC_EVENT_CODE_LINK_STATE); - - pnob = adapter->net_obj; - netdev = pnob->netdev; - - /* Determine if this event is a switch VLD or a physical link event */ - async_event_type = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, event_type, - async_trailer); - active_port = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - active_port, link_status); - port0_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_link_status, link_status); - port1_link_status = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_link_status, link_status); - port0_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_duplex, link_status); - port1_duplex = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_duplex, link_status); - port0_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port0_speed, link_status); - port1_speed = AMAP_GET_BITS_PTR(ASYNC_EVENT_LINK_STATE, - port1_speed, link_status); - if (async_event_type == NTWK_LINK_TYPE_VIRTUAL) { - adapter->be_stat.bes_link_change_virtual++; - if (adapter->be_link_sts->active_port != active_port) { - dev_notice(&netdev->dev, - "Active port changed due to VLD on switch\n"); - } else { - dev_notice(&netdev->dev, "Link status update\n"); - } - - } else { - adapter->be_stat.bes_link_change_physical++; - if (adapter->be_link_sts->active_port != active_port) { - dev_notice(&netdev->dev, - "Active port changed due to port link" - " status change\n"); - } else { - dev_notice(&netdev->dev, "Link status update\n"); - } - } - - memset(adapter->be_link_sts, 0, sizeof(adapter->be_link_sts)); - - if ((port0_link_status == ASYNC_EVENT_LINK_UP) || - (port1_link_status == ASYNC_EVENT_LINK_UP)) { - if ((adapter->port0_link_sts == BE_PORT_LINK_DOWN) && - (adapter->port1_link_sts == BE_PORT_LINK_DOWN)) { - /* Earlier both the ports are down So link is up */ - link_enable = true; - } - - if (port0_link_status == ASYNC_EVENT_LINK_UP) { - adapter->port0_link_sts = BE_PORT_LINK_UP; - adapter->be_link_sts->mac0_duplex = port0_duplex; - adapter->be_link_sts->mac0_speed = port0_speed; - if (active_port == NTWK_PORT_A) - adapter->be_link_sts->active_port = 0; - } else - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - - if (port1_link_status == ASYNC_EVENT_LINK_UP) { - adapter->port1_link_sts = BE_PORT_LINK_UP; - adapter->be_link_sts->mac1_duplex = port1_duplex; - adapter->be_link_sts->mac1_speed = port1_speed; - if (active_port == NTWK_PORT_B) - adapter->be_link_sts->active_port = 1; - } else - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - - printk(KERN_INFO "Link Properties for %s:\n", netdev->name); - dev_info(&netdev->dev, "Link Properties:\n"); - be_print_link_info(adapter->be_link_sts); - - if (!link_enable) - return; - /* - * Both ports were down previously, but atleast one of - * them has come up if this netdevice's carrier is not up, - * then indicate to stack - */ - if (!netif_carrier_ok(netdev)) { - netif_start_queue(netdev); - netif_carrier_on(netdev); - } - return; - } - - /* Now both the ports are down. Tell the stack about it */ - dev_info(&netdev->dev, "Both ports are down\n"); - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - if (netif_carrier_ok(netdev)) { - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - return; -} - -static int be_mcc_create(struct be_adapter *adapter) -{ - struct be_net_object *pnob; - - pnob = adapter->net_obj; - /* - * Create the MCC ring so that all further communication with - * MCC can go thru the ring. we do this at the end since - * we do not want to be dealing with interrupts until the - * initialization is complete. - */ - pnob->mcc_q_len = MCC_Q_LEN; - pnob->mcc_q_size = pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP); - pnob->mcc_q = pci_alloc_consistent(adapter->pdev, pnob->mcc_q_size, - &pnob->mcc_q_bus); - if (!pnob->mcc_q_bus) - return -1; - /* - * space for MCC WRB context - */ - pnob->mcc_wrb_ctxtLen = MCC_Q_LEN; - pnob->mcc_wrb_ctxt_size = pnob->mcc_wrb_ctxtLen * - sizeof(struct be_mcc_wrb_context); - pnob->mcc_wrb_ctxt = (void *)__get_free_pages(GFP_KERNEL, - get_order(pnob->mcc_wrb_ctxt_size)); - if (pnob->mcc_wrb_ctxt == NULL) - return -1; - /* - * Space for MCC compl. ring - */ - pnob->mcc_cq_len = MCC_CQ_LEN; - pnob->mcc_cq_size = pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP); - pnob->mcc_cq = pci_alloc_consistent(adapter->pdev, pnob->mcc_cq_size, - &pnob->mcc_cq_bus); - if (!pnob->mcc_cq_bus) - return -1; - return 0; -} - -/* - This function creates the MCC request and completion ring required - for communicating with the ARM processor. The caller must have - allocated required amount of memory for the MCC ring and MCC - completion ring and posted the virtual address and number of - entries in the corresponding members (mcc_q and mcc_cq) in the - NetObject struture. - - When this call is completed, all further communication with - ARM will switch from mailbox to this ring. - - pnob - Pointer to the NetObject structure. This NetObject should - have been created using a previous call to be_create_netobj() -*/ -int be_create_mcc_rings(struct be_net_object *pnob) -{ - int status = 0; - struct ring_desc rd; - struct be_function_object *pfob = &pnob->fn_obj; - - memset(&rd, 0, sizeof(struct ring_desc)); - if (pnob->mcc_cq_len) { - rd.va = pnob->mcc_cq; - rd.pa = pnob->mcc_cq_bus; - rd.length = pnob->mcc_cq_size; - - status = be_cq_create(pfob, &rd, - pnob->mcc_cq_len * sizeof(struct MCC_CQ_ENTRY_AMAP), - false, /* solicted events, */ - true, /* nodelay */ - 0, /* 0 Watermark since Nodelay is true */ - &pnob->event_q_obj, - &pnob->mcc_cq_obj); - - if (status != BE_SUCCESS) - return status; - - pnob->mcc_cq_id = pnob->mcc_cq_obj.cq_id; - pnob->mcc_cq_created = 1; - } - if (pnob->mcc_q_len) { - rd.va = pnob->mcc_q; - rd.pa = pnob->mcc_q_bus; - rd.length = pnob->mcc_q_size; - - status = be_mcc_ring_create(pfob, &rd, - pnob->mcc_q_len * sizeof(struct MCC_WRB_AMAP), - pnob->mcc_wrb_ctxt, pnob->mcc_wrb_ctxtLen, - &pnob->mcc_cq_obj, &pnob->mcc_q_obj); - - if (status != BE_SUCCESS) - return status; - - pnob->mcc_q_created = 1; - } - return BE_SUCCESS; -} - -static int be_mcc_init(struct be_adapter *adapter) -{ - u32 r; - struct be_net_object *pnob; - - pnob = adapter->net_obj; - memset(pnob->mcc_q, 0, pnob->mcc_q_size); - pnob->mcc_q_hd = 0; - - memset(pnob->mcc_wrb_ctxt, 0, pnob->mcc_wrb_ctxt_size); - - memset(pnob->mcc_cq, 0, pnob->mcc_cq_size); - pnob->mcc_cq_tl = 0; - - r = be_create_mcc_rings(adapter->net_obj); - if (r != BE_SUCCESS) - return -1; - - return 0; -} - -static void be_remove(struct pci_dev *pdev) -{ - struct be_net_object *pnob; - struct be_adapter *adapter; - - adapter = pci_get_drvdata(pdev); - if (!adapter) - return; - - pci_set_drvdata(pdev, NULL); - pnob = (struct be_net_object *)adapter->net_obj; - - flush_scheduled_work(); - - if (pnob) { - /* Unregister async callback function for link status updates */ - if (pnob->mcc_q_created) - be_mcc_add_async_event_callback(&pnob->mcc_q_obj, - NULL, NULL); - netobject_cleanup(adapter, pnob); - } - - if (adapter->csr_va) - iounmap(adapter->csr_va); - if (adapter->db_va) - iounmap(adapter->db_va); - if (adapter->pci_va) - iounmap(adapter->pci_va); - - pci_release_regions(adapter->pdev); - pci_disable_device(adapter->pdev); - - kfree(adapter->be_link_sts); - kfree(adapter->eth_statsp); - - if (adapter->timer_ctxt.get_stats_timer.function) - del_timer_sync(&adapter->timer_ctxt.get_stats_timer); - kfree(adapter); -} - -/* - * This function is called by the PCI sub-system when it finds a PCI - * device with dev/vendor IDs that match with one of our devices. - * All of the driver initialization is done in this function. - */ -static int be_probe(struct pci_dev *pdev, const struct pci_device_id *pdev_id) -{ - int status = 0; - struct be_adapter *adapter; - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD get_fwv; - struct be_net_object *pnob; - struct net_device *netdev; - - status = pci_enable_device(pdev); - if (status) - goto error; - - status = pci_request_regions(pdev, be_driver_name); - if (status) - goto error_pci_req; - - pci_set_master(pdev); - adapter = kzalloc(sizeof(struct be_adapter), GFP_KERNEL); - if (adapter == NULL) { - status = -ENOMEM; - goto error_adapter; - } - adapter->dev_state = BE_DEV_STATE_NONE; - adapter->pdev = pdev; - pci_set_drvdata(pdev, adapter); - - adapter->enable_aic = 1; - adapter->max_eqd = MAX_EQD; - adapter->min_eqd = 0; - adapter->cur_eqd = 0; - - status = pci_set_dma_mask(pdev, DMA_64BIT_MASK); - if (!status) { - adapter->dma_64bit_cap = true; - } else { - adapter->dma_64bit_cap = false; - status = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (status != 0) { - printk(KERN_ERR "Could not set PCI DMA Mask\n"); - goto cleanup; - } - } - - status = init_pci_be_function(adapter, pdev); - if (status != 0) { - printk(KERN_ERR "Failed to map PCI BARS\n"); - status = -ENOMEM; - goto cleanup; - } - - be_trace_set_level(DL_ALWAYS | DL_ERR); - - adapter->be_link_sts = kmalloc(sizeof(struct BE_LINK_STATUS), - GFP_KERNEL); - if (adapter->be_link_sts == NULL) { - printk(KERN_ERR "Memory allocation for link status " - "buffer failed\n"); - goto cleanup; - } - spin_lock_init(&adapter->txq_lock); - - netdev = alloc_etherdev(sizeof(struct be_net_object)); - if (netdev == NULL) { - status = -ENOMEM; - goto cleanup; - } - pnob = netdev_priv(netdev); - adapter->net_obj = pnob; - adapter->netdevp = netdev; - pnob->adapter = adapter; - pnob->netdev = netdev; - - status = be_nob_ring_alloc(adapter, pnob); - if (status != 0) - goto cleanup; - - status = be_nob_ring_init(adapter, pnob); - if (status != 0) - goto cleanup; - - be_rxf_mac_address_read_write(&pnob->fn_obj, false, false, false, - false, false, netdev->dev_addr, NULL, NULL); - - netdev->init = &benet_init; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - SET_NETDEV_DEV(netdev, &(adapter->pdev->dev)); - - netif_napi_add(netdev, &pnob->napi, be_poll, 64); - - /* if the rx_frag size if 2K, one page is shared as two RX frags */ - pnob->rx_pg_shared = - (pnob->rx_buf_size <= PAGE_SIZE / 2) ? true : false; - if (pnob->rx_buf_size != rxbuf_size) { - printk(KERN_WARNING - "Could not set Rx buffer size to %d. Using %d\n", - rxbuf_size, pnob->rx_buf_size); - rxbuf_size = pnob->rx_buf_size; - } - - tasklet_init(&(adapter->sts_handler), be_process_intr, - (unsigned long)adapter); - adapter->tasklet_started = 1; - spin_lock_init(&(adapter->int_lock)); - - status = be_register_isr(adapter, pnob); - if (status != 0) - goto cleanup; - - adapter->rx_csum = 1; - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - memset(&get_fwv, 0, - sizeof(struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD)); - printk(KERN_INFO "BladeEngine Driver version:%s. " - "Copyright ServerEngines, Corporation 2005 - 2008\n", - be_drvr_ver); - status = be_function_get_fw_version(&pnob->fn_obj, &get_fwv, NULL, - NULL); - if (status == BE_SUCCESS) { - strncpy(be_fw_ver, get_fwv.firmware_version_string, 32); - printk(KERN_INFO "BladeEngine Firmware Version:%s\n", - get_fwv.firmware_version_string); - } else { - printk(KERN_WARNING "Unable to get BE Firmware Version\n"); - } - - sema_init(&adapter->get_eth_stat_sem, 0); - init_timer(&adapter->timer_ctxt.get_stats_timer); - atomic_set(&adapter->timer_ctxt.get_stat_flag, 0); - adapter->timer_ctxt.get_stats_timer.function = - &be_get_stats_timer_handler; - - status = be_mcc_create(adapter); - if (status < 0) - goto cleanup; - status = be_mcc_init(adapter); - if (status < 0) - goto cleanup; - - - status = be_mcc_add_async_event_callback(&adapter->net_obj->mcc_q_obj, - be_link_status_async_callback, (void *)adapter); - if (status != BE_SUCCESS) { - printk(KERN_WARNING "add_async_event_callback failed"); - printk(KERN_WARNING - "Link status changes may not be reflected\n"); - } - - status = register_netdev(netdev); - if (status != 0) - goto cleanup; - be_update_link_status(adapter); - adapter->dev_state = BE_DEV_STATE_INIT; - return 0; - -cleanup: - be_remove(pdev); - return status; -error_adapter: - pci_release_regions(pdev); -error_pci_req: - pci_disable_device(pdev); -error: - printk(KERN_ERR "BladeEngine initalization failed\n"); - return status; -} - -/* - * Get the current link status and print the status on console - */ -void be_update_link_status(struct be_adapter *adapter) -{ - int status; - struct be_net_object *pnob = adapter->net_obj; - - status = be_rxf_link_status(&pnob->fn_obj, adapter->be_link_sts, NULL, - NULL, NULL); - if (status == BE_SUCCESS) { - if (adapter->be_link_sts->mac0_speed && - adapter->be_link_sts->mac0_duplex) - adapter->port0_link_sts = BE_PORT_LINK_UP; - else - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - - if (adapter->be_link_sts->mac1_speed && - adapter->be_link_sts->mac1_duplex) - adapter->port1_link_sts = BE_PORT_LINK_UP; - else - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - - dev_info(&pnob->netdev->dev, "Link Properties:\n"); - be_print_link_info(adapter->be_link_sts); - return; - } - dev_info(&pnob->netdev->dev, "Could not get link status\n"); - return; -} - - -#ifdef CONFIG_PM -static void -be_pm_cleanup(struct be_adapter *adapter, - struct be_net_object *pnob, struct net_device *netdev) -{ - netif_carrier_off(netdev); - netif_stop_queue(netdev); - - be_wait_nic_tx_cmplx_cmpl(pnob); - be_disable_eq_intr(pnob); - - if (adapter->tasklet_started) { - tasklet_kill(&adapter->sts_handler); - adapter->tasklet_started = 0; - } - - be_unregister_isr(adapter); - be_disable_intr(pnob); - - be_tx_q_clean(pnob); - be_rx_q_clean(pnob); - - be_destroy_netobj(pnob); -} - -static int be_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct be_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdevp; - struct be_net_object *pnob = netdev_priv(netdev); - - adapter->dev_pm_state = adapter->dev_state; - adapter->dev_state = BE_DEV_STATE_SUSPEND; - - netif_device_detach(netdev); - if (netif_running(netdev)) - be_pm_cleanup(adapter, pnob, netdev); - - pci_enable_wake(pdev, 3, 1); - pci_enable_wake(pdev, 4, 1); /* D3 Cold = 4 */ - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static void be_up(struct be_adapter *adapter) -{ - struct be_net_object *pnob = adapter->net_obj; - - if (pnob->num_vlans != 0) - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); - -} - -static int be_resume(struct pci_dev *pdev) -{ - int status = 0; - struct be_adapter *adapter = pci_get_drvdata(pdev); - struct net_device *netdev = adapter->netdevp; - struct be_net_object *pnob = netdev_priv(netdev); - - netif_device_detach(netdev); - - status = pci_enable_device(pdev); - if (status) - return status; - - pci_set_power_state(pdev, 0); - pci_restore_state(pdev); - pci_enable_wake(pdev, 3, 0); - pci_enable_wake(pdev, 4, 0); /* 4 is D3 cold */ - - netif_carrier_on(netdev); - netif_start_queue(netdev); - - if (netif_running(netdev)) { - be_rxf_mac_address_read_write(&pnob->fn_obj, false, false, - false, true, false, netdev->dev_addr, NULL, NULL); - - status = be_nob_ring_init(adapter, pnob); - if (status < 0) - return status; - - tasklet_init(&(adapter->sts_handler), be_process_intr, - (unsigned long)adapter); - adapter->tasklet_started = 1; - - if (be_register_isr(adapter, pnob) != 0) { - printk(KERN_ERR "be_register_isr failed\n"); - return status; - } - - - status = be_mcc_init(adapter); - if (status < 0) { - printk(KERN_ERR "be_mcc_init failed\n"); - return status; - } - be_update_link_status(adapter); - /* - * Register async call back function to handle link - * status updates - */ - status = be_mcc_add_async_event_callback( - &adapter->net_obj->mcc_q_obj, - be_link_status_async_callback, (void *)adapter); - if (status != BE_SUCCESS) { - printk(KERN_WARNING "add_async_event_callback failed"); - printk(KERN_WARNING - "Link status changes may not be reflected\n"); - } - be_enable_intr(pnob); - be_enable_eq_intr(pnob); - be_up(adapter); - } - netif_device_attach(netdev); - adapter->dev_state = adapter->dev_pm_state; - return 0; - -} - -#endif - -/* Wait until no more pending transmits */ -void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *pnob) -{ - int i; - - /* Wait for 20us * 50000 (= 1s) and no more */ - i = 0; - while ((pnob->tx_q_tl != pnob->tx_q_hd) && (i < 50000)) { - ++i; - udelay(20); - } - - /* Check for no more pending transmits */ - if (i >= 50000) { - printk(KERN_WARNING - "Did not receive completions for all TX requests\n"); - } -} - -static struct pci_driver be_driver = { - .name = be_driver_name, - .id_table = be_device_id_table, - .probe = be_probe, -#ifdef CONFIG_PM - .suspend = be_suspend, - .resume = be_resume, -#endif - .remove = be_remove -}; - -/* - * Module init entry point. Registers our our device and return. - * Our probe will be called if the device is found. - */ -static int __init be_init_module(void) -{ - int ret; - - if (rxbuf_size != 8192 && rxbuf_size != 4096 && rxbuf_size != 2048) { - printk(KERN_WARNING - "Unsupported receive buffer size (%d) requested\n", - rxbuf_size); - printk(KERN_WARNING - "Must be 2048, 4096 or 8192. Defaulting to 2048\n"); - rxbuf_size = 2048; - } - - ret = pci_register_driver(&be_driver); - - return ret; -} - -module_init(be_init_module); - -/* - * be_exit_module - Driver Exit Cleanup Routine - */ -static void __exit be_exit_module(void) -{ - pci_unregister_driver(&be_driver); -} - -module_exit(be_exit_module); diff --git a/drivers/staging/benet/be_int.c b/drivers/staging/benet/be_int.c deleted file mode 100644 index cba95d09a8b..00000000000 --- a/drivers/staging/benet/be_int.c +++ /dev/null @@ -1,863 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include - -#include "benet.h" - -/* number of bytes of RX frame that are copied to skb->data */ -#define BE_HDR_LEN 64 - -#define NETIF_RX(skb) netif_receive_skb(skb) -#define VLAN_ACCEL_RX(skb, pnob, vt) \ - vlan_hwaccel_rx(skb, pnob->vlan_grp, vt) - -/* - This function notifies BladeEngine of the number of completion - entries processed from the specified completion queue by writing - the number of popped entries to the door bell. - - pnob - Pointer to the NetObject structure - n - Number of completion entries processed - cq_id - Queue ID of the completion queue for which notification - is being done. - re_arm - 1 - rearm the completion ring to generate an event. - - 0 - dont rearm the completion ring to generate an event -*/ -void be_notify_cmpl(struct be_net_object *pnob, int n, int cq_id, int re_arm) -{ - struct CQ_DB_AMAP cqdb; - - cqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(CQ_DB, qid, &cqdb, cq_id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &cqdb, re_arm); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &cqdb, n); - PD_WRITE(&pnob->fn_obj, cq_db, cqdb.dw[0]); -} - -/* - * adds additional receive frags indicated by BE starting from given - * frag index (fi) to specified skb's frag list - */ -static void -add_skb_frags(struct be_net_object *pnob, struct sk_buff *skb, - u32 nresid, u32 fi) -{ - struct be_adapter *adapter = pnob->adapter; - u32 sk_frag_idx, n; - struct be_rx_page_info *rx_page_info; - u32 frag_sz = pnob->rx_buf_size; - - sk_frag_idx = skb_shinfo(skb)->nr_frags; - while (nresid) { - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = NULL; - if ((rx_page_info->page_offset) || - (pnob->rx_pg_shared == false)) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - n = min(nresid, frag_sz); - skb_shinfo(skb)->frags[sk_frag_idx].page = rx_page_info->page; - skb_shinfo(skb)->frags[sk_frag_idx].page_offset - = rx_page_info->page_offset; - skb_shinfo(skb)->frags[sk_frag_idx].size = n; - - sk_frag_idx++; - skb->len += n; - skb->data_len += n; - skb_shinfo(skb)->nr_frags++; - nresid -= n; - - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } -} - -/* - * This function processes incoming nic packets over various Rx queues. - * This function takes the adapter, the current Rx status descriptor - * entry and the Rx completion queue ID as argument. - */ -static inline int process_nic_rx_completion(struct be_net_object *pnob, - struct ETH_RX_COMPL_AMAP *rxcp) -{ - struct be_adapter *adapter = pnob->adapter; - struct sk_buff *skb; - int udpcksm, tcpcksm; - int n; - u32 nresid, fi; - u32 frag_sz = pnob->rx_buf_size; - u8 *va; - struct be_rx_page_info *rx_page_info; - u32 numfrags, vtp, vtm, vlan_tag, pktsize; - - fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp); - BUG_ON(fi >= (int)pnob->rx_q_len); - BUG_ON(fi < 0); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - BUG_ON(!rx_page_info->page); - pnob->rx_ctxt[fi] = NULL; - - /* - * If one page is used per fragment or if this is the second half of - * of the page, unmap the page here - */ - if ((rx_page_info->page_offset) || (pnob->rx_pg_shared == false)) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), frag_sz, - PCI_DMA_FROMDEVICE); - } - - atomic_dec(&pnob->rx_q_posted); - udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp); - tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - /* - * get rid of RX flush completions first. - */ - if ((tcpcksm) && (udpcksm) && (pktsize == 32)) { - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - return 0; - } - skb = netdev_alloc_skb(pnob->netdev, BE_HDR_LEN + NET_IP_ALIGN); - if (skb == NULL) { - dev_info(&pnob->netdev->dev, "alloc_skb() failed\n"); - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - goto free_frags; - } - skb_reserve(skb, NET_IP_ALIGN); - - skb->dev = pnob->netdev; - - n = min(pktsize, frag_sz); - - va = page_address(rx_page_info->page) + rx_page_info->page_offset; - prefetch(va); - - skb->len = n; - skb->data_len = n; - if (n <= BE_HDR_LEN) { - memcpy(skb->data, va, n); - put_page(rx_page_info->page); - skb->data_len -= n; - skb->tail += n; - } else { - - /* Setup the SKB with page buffer information */ - skb_shinfo(skb)->frags[0].page = rx_page_info->page; - skb_shinfo(skb)->nr_frags++; - - /* Copy the header into the skb_data */ - memcpy(skb->data, va, BE_HDR_LEN); - skb_shinfo(skb)->frags[0].page_offset = - rx_page_info->page_offset + BE_HDR_LEN; - skb_shinfo(skb)->frags[0].size = n - BE_HDR_LEN; - skb->data_len -= BE_HDR_LEN; - skb->tail += BE_HDR_LEN; - } - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - nresid = pktsize - n; - - skb->protocol = eth_type_trans(skb, pnob->netdev); - - if ((tcpcksm || udpcksm) && adapter->rx_csum) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - /* - * if we have more bytes left, the frame has been - * given to us in multiple fragments. This happens - * with Jumbo frames. Add the remaining fragments to - * skb->frags[] array. - */ - if (nresid) - add_skb_frags(pnob, skb, nresid, fi); - - /* update the the true size of the skb. */ - skb->truesize = skb->len + sizeof(struct sk_buff); - - /* - * If a 802.3 frame or 802.2 LLC frame - * (i.e) contains length field in MAC Hdr - * and frame len is greater than 64 bytes - */ - if (((skb->protocol == ntohs(ETH_P_802_2)) || - (skb->protocol == ntohs(ETH_P_802_3))) - && (pktsize > BE_HDR_LEN)) { - /* - * If the length given in Mac Hdr is less than frame size - * Erraneous frame, Drop it - */ - if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) < pktsize) { - /* Increment Non Ether type II frames dropped */ - adapter->be_stat.bes_802_3_dropped_frames++; - - kfree_skb(skb); - return 0; - } - /* - * else if the length given in Mac Hdr is greater than - * frame size, should not be seeing this sort of frames - * dump the pkt and pass to stack - */ - else if ((ntohs(*(u16 *) (va + 12)) + ETH_HLEN) > pktsize) { - /* Increment Non Ether type II frames malformed */ - adapter->be_stat.bes_802_3_malformed_frames++; - } - } - - vtp = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp); - vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp); - if (vtp && vtm) { - /* Vlan tag present in pkt and BE found - * that the tag matched an entry in VLAN table - */ - if (!pnob->vlan_grp || pnob->num_vlans == 0) { - /* But we have no VLANs configured. - * This should never happen. Drop the packet. - */ - dev_info(&pnob->netdev->dev, - "BladeEngine: Unexpected vlan tagged packet\n"); - kfree_skb(skb); - return 0; - } - /* pass the VLAN packet to stack */ - vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp); - VLAN_ACCEL_RX(skb, pnob, be16_to_cpu(vlan_tag)); - - } else { - NETIF_RX(skb); - } - return 0; - -free_frags: - /* free all frags associated with the current rxcp */ - numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp); - while (numfrags-- > 1) { - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *) - pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = (void *)NULL; - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } - return -ENOMEM; -} - -static void process_nic_rx_completion_lro(struct be_net_object *pnob, - struct ETH_RX_COMPL_AMAP *rxcp) -{ - struct be_adapter *adapter = pnob->adapter; - struct skb_frag_struct rx_frags[BE_MAX_FRAGS_PER_FRAME]; - unsigned int udpcksm, tcpcksm; - u32 numfrags, vlanf, vtm, vlan_tag, nresid; - u16 vlant; - unsigned int fi, idx, n; - struct be_rx_page_info *rx_page_info; - u32 frag_sz = pnob->rx_buf_size, pktsize; - bool rx_coal = (adapter->max_rx_coal <= 1) ? 0 : 1; - u8 err, *va; - __wsum csum = 0; - - if (AMAP_GET_BITS_PTR(ETH_RX_COMPL, ipsec, rxcp)) { - /* Drop the pkt and move to the next completion. */ - adapter->be_stat.bes_rx_misc_pkts++; - return; - } - err = AMAP_GET_BITS_PTR(ETH_RX_COMPL, err, rxcp); - if (err || !rx_coal) { - /* We won't coalesce Rx pkts if the err bit set. - * take the path of normal completion processing */ - process_nic_rx_completion(pnob, rxcp); - return; - } - - fi = AMAP_GET_BITS_PTR(ETH_RX_COMPL, fragndx, rxcp); - BUG_ON(fi >= (int)pnob->rx_q_len); - BUG_ON(fi < 0); - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - BUG_ON(!rx_page_info->page); - pnob->rx_ctxt[fi] = (void *)NULL; - /* If one page is used per fragment or if this is the - * second half of the page, unmap the page here - */ - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - numfrags = AMAP_GET_BITS_PTR(ETH_RX_COMPL, numfrags, rxcp); - udpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, udpcksm, rxcp); - tcpcksm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, tcpcksm, rxcp); - vlan_tag = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vlan_tag, rxcp); - vlant = be16_to_cpu(vlan_tag); - vlanf = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtp, rxcp); - vtm = AMAP_GET_BITS_PTR(ETH_RX_COMPL, vtm, rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - - atomic_dec(&pnob->rx_q_posted); - - if (tcpcksm && udpcksm && pktsize == 32) { - /* flush completion entries */ - put_page(rx_page_info->page); - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - return; - } - /* Only one of udpcksum and tcpcksum can be set */ - BUG_ON(udpcksm && tcpcksm); - - /* jumbo frames could come in multiple fragments */ - BUG_ON(numfrags != ((pktsize + (frag_sz - 1)) / frag_sz)); - n = min(pktsize, frag_sz); - nresid = pktsize - n; /* will be useful for jumbo pkts */ - idx = 0; - - va = page_address(rx_page_info->page) + rx_page_info->page_offset; - prefetch(va); - rx_frags[idx].page = rx_page_info->page; - rx_frags[idx].page_offset = (rx_page_info->page_offset); - rx_frags[idx].size = n; - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - - /* If we got multiple fragments, we have more data. */ - while (nresid) { - idx++; - index_inc(&fi, pnob->rx_q_len); - - rx_page_info = (struct be_rx_page_info *)pnob->rx_ctxt[fi]; - pnob->rx_ctxt[fi] = (void *)NULL; - if (rx_page_info->page_offset || !pnob->rx_pg_shared) { - pci_unmap_page(adapter->pdev, - pci_unmap_addr(rx_page_info, bus), - frag_sz, PCI_DMA_FROMDEVICE); - } - - n = min(nresid, frag_sz); - rx_frags[idx].page = rx_page_info->page; - rx_frags[idx].page_offset = (rx_page_info->page_offset); - rx_frags[idx].size = n; - - nresid -= n; - memset(rx_page_info, 0, sizeof(struct be_rx_page_info)); - atomic_dec(&pnob->rx_q_posted); - } - - if (likely(!(vlanf && vtm))) { - lro_receive_frags(&pnob->lro_mgr, rx_frags, - pktsize, pktsize, - (void *)(unsigned long)csum, csum); - } else { - /* Vlan tag present in pkt and BE found - * that the tag matched an entry in VLAN table - */ - if (unlikely(!pnob->vlan_grp || pnob->num_vlans == 0)) { - /* But we have no VLANs configured. - * This should never happen. Drop the packet. - */ - dev_info(&pnob->netdev->dev, - "BladeEngine: Unexpected vlan tagged packet\n"); - return; - } - /* pass the VLAN packet to stack */ - lro_vlan_hwaccel_receive_frags(&pnob->lro_mgr, - rx_frags, pktsize, pktsize, - pnob->vlan_grp, vlant, - (void *)(unsigned long)csum, - csum); - } - - adapter->be_stat.bes_rx_coal++; -} - -struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *pnob) -{ - struct ETH_RX_COMPL_AMAP *rxcp = &pnob->rx_cq[pnob->rx_cq_tl]; - u32 valid, ct; - - valid = AMAP_GET_BITS_PTR(ETH_RX_COMPL, valid, rxcp); - if (valid == 0) - return NULL; - - ct = AMAP_GET_BITS_PTR(ETH_RX_COMPL, ct, rxcp); - if (ct != 0) { - /* Invalid chute #. treat as error */ - AMAP_SET_BITS_PTR(ETH_RX_COMPL, err, rxcp, 1); - } - - be_adv_rxcq_tl(pnob); - AMAP_SET_BITS_PTR(ETH_RX_COMPL, valid, rxcp, 0); - return rxcp; -} - -static void update_rx_rate(struct be_adapter *adapter) -{ - /* update the rate once in two seconds */ - if ((jiffies - adapter->eth_rx_jiffies) > 2 * (HZ)) { - u32 r; - r = adapter->eth_rx_bytes / - ((jiffies - adapter->eth_rx_jiffies) / (HZ)); - r = (r / 1000000); /* MB/Sec */ - - /* Mega Bits/Sec */ - adapter->be_stat.bes_eth_rx_rate = (r * 8); - adapter->eth_rx_jiffies = jiffies; - adapter->eth_rx_bytes = 0; - } -} - -static int process_rx_completions(struct be_net_object *pnob, int max_work) -{ - struct be_adapter *adapter = pnob->adapter; - struct ETH_RX_COMPL_AMAP *rxcp; - u32 nc = 0; - unsigned int pktsize; - - while (max_work && (rxcp = be_get_rx_cmpl(pnob))) { - prefetch(rxcp); - pktsize = AMAP_GET_BITS_PTR(ETH_RX_COMPL, pktsize, rxcp); - process_nic_rx_completion_lro(pnob, rxcp); - adapter->eth_rx_bytes += pktsize; - update_rx_rate(adapter); - nc++; - max_work--; - adapter->be_stat.bes_rx_compl++; - } - if (likely(adapter->max_rx_coal > 1)) { - adapter->be_stat.bes_rx_flush++; - lro_flush_all(&pnob->lro_mgr); - } - - /* Refill the queue */ - if (atomic_read(&pnob->rx_q_posted) < 900) - be_post_eth_rx_buffs(pnob); - - return nc; -} - -static struct ETH_TX_COMPL_AMAP *be_get_tx_cmpl(struct be_net_object *pnob) -{ - struct ETH_TX_COMPL_AMAP *txcp = &pnob->tx_cq[pnob->tx_cq_tl]; - u32 valid; - - valid = AMAP_GET_BITS_PTR(ETH_TX_COMPL, valid, txcp); - if (valid == 0) - return NULL; - - AMAP_SET_BITS_PTR(ETH_TX_COMPL, valid, txcp, 0); - be_adv_txcq_tl(pnob); - return txcp; - -} - -void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx) -{ - struct be_adapter *adapter = pnob->adapter; - int cur_index, tx_wrbs_completed = 0; - struct sk_buff *skb; - u64 busaddr, pa, pa_lo, pa_hi; - struct ETH_WRB_AMAP *wrb; - u32 frag_len, last_index, j; - - last_index = tx_compl_lastwrb_idx_get(pnob); - BUG_ON(last_index != end_idx); - pnob->tx_ctxt[pnob->tx_q_tl] = NULL; - do { - cur_index = pnob->tx_q_tl; - wrb = &pnob->tx_q[cur_index]; - pa_hi = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb); - pa_lo = AMAP_GET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb); - frag_len = AMAP_GET_BITS_PTR(ETH_WRB, frag_len, wrb); - busaddr = (pa_hi << 32) | pa_lo; - if (busaddr != 0) { - pa = le64_to_cpu(busaddr); - pci_unmap_single(adapter->pdev, pa, - frag_len, PCI_DMA_TODEVICE); - } - if (cur_index == last_index) { - skb = (struct sk_buff *)pnob->tx_ctxt[cur_index]; - BUG_ON(!skb); - for (j = 0; j < skb_shinfo(skb)->nr_frags; j++) { - struct skb_frag_struct *frag; - frag = &skb_shinfo(skb)->frags[j]; - pci_unmap_page(adapter->pdev, - (ulong) frag->page, frag->size, - PCI_DMA_TODEVICE); - } - kfree_skb(skb); - pnob->tx_ctxt[cur_index] = NULL; - } else { - BUG_ON(pnob->tx_ctxt[cur_index]); - } - tx_wrbs_completed++; - be_adv_txq_tl(pnob); - } while (cur_index != last_index); - atomic_sub(tx_wrbs_completed, &pnob->tx_q_used); -} - -/* there is no need to take an SMP lock here since currently - * we have only one instance of the tasklet that does completion - * processing. - */ -static void process_nic_tx_completions(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - struct ETH_TX_COMPL_AMAP *txcp; - struct net_device *netdev = pnob->netdev; - u32 end_idx, num_processed = 0; - - adapter->be_stat.bes_tx_events++; - - while ((txcp = be_get_tx_cmpl(pnob))) { - end_idx = AMAP_GET_BITS_PTR(ETH_TX_COMPL, wrb_index, txcp); - process_one_tx_compl(pnob, end_idx); - num_processed++; - adapter->be_stat.bes_tx_compl++; - } - be_notify_cmpl(pnob, num_processed, pnob->tx_cq_id, 1); - /* - * We got Tx completions and have usable WRBs. - * If the netdev's queue has been stopped - * because we had run out of WRBs, wake it now. - */ - spin_lock(&adapter->txq_lock); - if (netif_queue_stopped(netdev) - && atomic_read(&pnob->tx_q_used) < pnob->tx_q_len / 2) { - netif_wake_queue(netdev); - } - spin_unlock(&adapter->txq_lock); -} - -static u32 post_rx_buffs(struct be_net_object *pnob, struct list_head *rxbl) -{ - u32 nposted = 0; - struct ETH_RX_D_AMAP *rxd = NULL; - struct be_recv_buffer *rxbp; - void **rx_ctxp; - struct RQ_DB_AMAP rqdb; - - rx_ctxp = pnob->rx_ctxt; - - while (!list_empty(rxbl) && - (rx_ctxp[pnob->rx_q_hd] == NULL) && nposted < 255) { - - rxbp = list_first_entry(rxbl, struct be_recv_buffer, rxb_list); - list_del(&rxbp->rxb_list); - rxd = pnob->rx_q + pnob->rx_q_hd; - AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_lo, rxd, rxbp->rxb_pa_lo); - AMAP_SET_BITS_PTR(ETH_RX_D, fragpa_hi, rxd, rxbp->rxb_pa_hi); - - rx_ctxp[pnob->rx_q_hd] = rxbp->rxb_ctxt; - be_adv_rxq_hd(pnob); - nposted++; - } - - if (nposted) { - /* Now press the door bell to notify BladeEngine. */ - rqdb.dw[0] = 0; - AMAP_SET_BITS_PTR(RQ_DB, numPosted, &rqdb, nposted); - AMAP_SET_BITS_PTR(RQ_DB, rq, &rqdb, pnob->rx_q_id); - PD_WRITE(&pnob->fn_obj, erx_rq_db, rqdb.dw[0]); - } - atomic_add(nposted, &pnob->rx_q_posted); - return nposted; -} - -void be_post_eth_rx_buffs(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - u32 num_bufs, r; - u64 busaddr = 0, tmp_pa; - u32 max_bufs, pg_hd; - u32 frag_size; - struct be_recv_buffer *rxbp; - struct list_head rxbl; - struct be_rx_page_info *rx_page_info; - struct page *page = NULL; - u32 page_order = 0; - gfp_t alloc_flags = GFP_ATOMIC; - - BUG_ON(!adapter); - - max_bufs = 64; /* should be even # <= 255. */ - - frag_size = pnob->rx_buf_size; - page_order = get_order(frag_size); - - if (frag_size == 8192) - alloc_flags |= (gfp_t) __GFP_COMP; - /* - * Form a linked list of RECV_BUFFFER structure to be be posted. - * We will post even number of buffer so that pages can be - * shared. - */ - INIT_LIST_HEAD(&rxbl); - - for (num_bufs = 0; num_bufs < max_bufs && - !pnob->rx_page_info[pnob->rx_pg_info_hd].page; ++num_bufs) { - - rxbp = &pnob->eth_rx_bufs[num_bufs]; - pg_hd = pnob->rx_pg_info_hd; - rx_page_info = &pnob->rx_page_info[pg_hd]; - - if (!page) { - page = alloc_pages(alloc_flags, page_order); - if (unlikely(page == NULL)) { - adapter->be_stat.bes_ethrx_post_fail++; - pnob->rxbuf_post_fail++; - break; - } - pnob->rxbuf_post_fail = 0; - busaddr = pci_map_page(adapter->pdev, page, 0, - frag_size, PCI_DMA_FROMDEVICE); - rx_page_info->page_offset = 0; - rx_page_info->page = page; - /* - * If we are sharing a page among two skbs, - * alloc a new one on the next iteration - */ - if (pnob->rx_pg_shared == false) - page = NULL; - } else { - get_page(page); - rx_page_info->page_offset += frag_size; - rx_page_info->page = page; - /* - * We are finished with the alloced page, - * Alloc a new one on the next iteration - */ - page = NULL; - } - rxbp->rxb_ctxt = (void *)rx_page_info; - index_inc(&pnob->rx_pg_info_hd, pnob->rx_q_len); - - pci_unmap_addr_set(rx_page_info, bus, busaddr); - tmp_pa = busaddr + rx_page_info->page_offset; - rxbp->rxb_pa_lo = (tmp_pa & 0xFFFFFFFF); - rxbp->rxb_pa_hi = (tmp_pa >> 32); - rxbp->rxb_len = frag_size; - list_add_tail(&rxbp->rxb_list, &rxbl); - } /* End of for */ - - r = post_rx_buffs(pnob, &rxbl); - BUG_ON(r != num_bufs); - return; -} - -/* - * Interrupt service for network function. We just schedule the - * tasklet which does all completion processing. - */ -irqreturn_t be_int(int irq, void *dev) -{ - struct net_device *netdev = dev; - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - u32 isr; - - isr = CSR_READ(&pnob->fn_obj, cev.isr1); - if (unlikely(!isr)) - return IRQ_NONE; - - spin_lock(&adapter->int_lock); - adapter->isr |= isr; - spin_unlock(&adapter->int_lock); - - adapter->be_stat.bes_ints++; - - tasklet_schedule(&adapter->sts_handler); - return IRQ_HANDLED; -} - -/* - * Poll function called by NAPI with a work budget. - * We process as many UC. BC and MC receive completions - * as the budget allows and return the actual number of - * RX ststutses processed. - */ -int be_poll(struct napi_struct *napi, int budget) -{ - struct be_net_object *pnob = - container_of(napi, struct be_net_object, napi); - u32 work_done; - - pnob->adapter->be_stat.bes_polls++; - work_done = process_rx_completions(pnob, budget); - BUG_ON(work_done > budget); - - /* All consumed */ - if (work_done < budget) { - netif_rx_complete(napi); - /* enable intr */ - be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 1); - } else { - /* More to be consumed; continue with interrupts disabled */ - be_notify_cmpl(pnob, work_done, pnob->rx_cq_id, 0); - } - return work_done; -} - -static struct EQ_ENTRY_AMAP *get_event(struct be_net_object *pnob) -{ - struct EQ_ENTRY_AMAP *eqp = &(pnob->event_q[pnob->event_q_tl]); - if (!AMAP_GET_BITS_PTR(EQ_ENTRY, Valid, eqp)) - return NULL; - be_adv_eq_tl(pnob); - return eqp; -} - -/* - * Processes all valid events in the event ring associated with given - * NetObject. Also, notifies BE the number of events processed. - */ -static inline u32 process_events(struct be_net_object *pnob) -{ - struct be_adapter *adapter = pnob->adapter; - struct EQ_ENTRY_AMAP *eqp; - u32 rid, num_events = 0; - struct net_device *netdev = pnob->netdev; - - while ((eqp = get_event(pnob)) != NULL) { - adapter->be_stat.bes_events++; - rid = AMAP_GET_BITS_PTR(EQ_ENTRY, ResourceID, eqp); - if (rid == pnob->rx_cq_id) { - adapter->be_stat.bes_rx_events++; - netif_rx_schedule(&pnob->napi); - } else if (rid == pnob->tx_cq_id) { - process_nic_tx_completions(pnob); - } else if (rid == pnob->mcc_cq_id) { - be_mcc_process_cq(&pnob->mcc_q_obj, 1); - } else { - dev_info(&netdev->dev, - "Invalid EQ ResourceID %d\n", rid); - } - AMAP_SET_BITS_PTR(EQ_ENTRY, Valid, eqp, 0); - AMAP_SET_BITS_PTR(EQ_ENTRY, ResourceID, eqp, 0); - num_events++; - } - return num_events; -} - -static void update_eqd(struct be_adapter *adapter, struct be_net_object *pnob) -{ - int status; - struct be_eq_object *eq_objectp; - - /* update once a second */ - if ((jiffies - adapter->ips_jiffies) > 1 * (HZ)) { - /* One second elapsed since last update */ - u32 r, new_eqd = -1; - r = adapter->be_stat.bes_ints - adapter->be_stat.bes_prev_ints; - r = r / ((jiffies - adapter->ips_jiffies) / (HZ)); - adapter->be_stat.bes_ips = r; - adapter->ips_jiffies = jiffies; - adapter->be_stat.bes_prev_ints = adapter->be_stat.bes_ints; - if (r > IPS_HI_WM && adapter->cur_eqd < adapter->max_eqd) - new_eqd = (adapter->cur_eqd + 8); - if (r < IPS_LO_WM && adapter->cur_eqd > adapter->min_eqd) - new_eqd = (adapter->cur_eqd - 8); - if (adapter->enable_aic && new_eqd != -1) { - eq_objectp = &pnob->event_q_obj; - status = be_eq_modify_delay(&pnob->fn_obj, 1, - &eq_objectp, &new_eqd, NULL, - NULL, NULL); - if (status == BE_SUCCESS) - adapter->cur_eqd = new_eqd; - } - } -} - -/* - This function notifies BladeEngine of how many events were processed - from the event queue by ringing the corresponding door bell and - optionally re-arms the event queue. - n - number of events processed - re_arm - 1 - re-arm the EQ, 0 - do not re-arm the EQ - -*/ -static void be_notify_event(struct be_net_object *pnob, int n, int re_arm) -{ - struct CQ_DB_AMAP eqdb; - eqdb.dw[0] = 0; - - AMAP_SET_BITS_PTR(CQ_DB, qid, &eqdb, pnob->event_q_id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &eqdb, re_arm); - AMAP_SET_BITS_PTR(CQ_DB, event, &eqdb, 1); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &eqdb, n); - /* - * Under some situations we see an interrupt and no valid - * EQ entry. To keep going, we need to ring the DB even if - * numPOsted is 0. - */ - PD_WRITE(&pnob->fn_obj, cq_db, eqdb.dw[0]); - return; -} - -/* - * Called from the tasklet scheduled by ISR. All real interrupt processing - * is done here. - */ -void be_process_intr(unsigned long context) -{ - struct be_adapter *adapter = (struct be_adapter *)context; - struct be_net_object *pnob = adapter->net_obj; - u32 isr, n; - ulong flags = 0; - - isr = adapter->isr; - - /* - * we create only one NIC event queue in Linux. Event is - * expected only in the first event queue - */ - BUG_ON(isr & 0xfffffffe); - if ((isr & 1) == 0) - return; /* not our interrupt */ - n = process_events(pnob); - /* - * Clear the event bit. adapter->isr is set by - * hard interrupt. Prevent race with lock. - */ - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->isr &= ~1; - spin_unlock_irqrestore(&adapter->int_lock, flags); - be_notify_event(pnob, n, 1); - /* - * If previous allocation attempts had failed and - * BE has used up all posted buffers, post RX buffers here - */ - if (pnob->rxbuf_post_fail && atomic_read(&pnob->rx_q_posted) == 0) - be_post_eth_rx_buffs(pnob); - update_eqd(adapter, pnob); - return; -} diff --git a/drivers/staging/benet/be_netif.c b/drivers/staging/benet/be_netif.c deleted file mode 100644 index 2b8daf63dc7..00000000000 --- a/drivers/staging/benet/be_netif.c +++ /dev/null @@ -1,705 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * be_netif.c - * - * This file contains various entry points of drivers seen by tcp/ip stack. - */ - -#include -#include -#include "benet.h" -#include -#include - -/* Strings to print Link properties */ -static const char *link_speed[] = { - "Invalid link Speed Value", - "10 Mbps", - "100 Mbps", - "1 Gbps", - "10 Gbps" -}; - -static const char *link_duplex[] = { - "Invalid Duplex Value", - "Half Duplex", - "Full Duplex" -}; - -static const char *link_state[] = { - "", - "(active)" -}; - -void be_print_link_info(struct BE_LINK_STATUS *lnk_status) -{ - u16 si, di, ai; - - /* Port 0 */ - if (lnk_status->mac0_speed && lnk_status->mac0_duplex) { - /* Port is up and running */ - si = (lnk_status->mac0_speed < 5) ? lnk_status->mac0_speed : 0; - di = (lnk_status->mac0_duplex < 3) ? - lnk_status->mac0_duplex : 0; - ai = (lnk_status->active_port == 0) ? 1 : 0; - printk(KERN_INFO "PortNo. 0: Speed - %s %s %s\n", - link_speed[si], link_duplex[di], link_state[ai]); - } else - printk(KERN_INFO "PortNo. 0: Down\n"); - - /* Port 1 */ - if (lnk_status->mac1_speed && lnk_status->mac1_duplex) { - /* Port is up and running */ - si = (lnk_status->mac1_speed < 5) ? lnk_status->mac1_speed : 0; - di = (lnk_status->mac1_duplex < 3) ? - lnk_status->mac1_duplex : 0; - ai = (lnk_status->active_port == 0) ? 1 : 0; - printk(KERN_INFO "PortNo. 1: Speed - %s %s %s\n", - link_speed[si], link_duplex[di], link_state[ai]); - } else - printk(KERN_INFO "PortNo. 1: Down\n"); - - return; -} - -static int -be_get_frag_header(struct skb_frag_struct *frag, void **mac_hdr, - void **ip_hdr, void **tcpudp_hdr, - u64 *hdr_flags, void *priv) -{ - struct ethhdr *eh; - struct vlan_ethhdr *veh; - struct iphdr *iph; - u8 *va = page_address(frag->page) + frag->page_offset; - unsigned long ll_hlen; - - /* find the mac header, abort if not IPv4 */ - - prefetch(va); - eh = (struct ethhdr *)va; - *mac_hdr = eh; - ll_hlen = ETH_HLEN; - if (eh->h_proto != htons(ETH_P_IP)) { - if (eh->h_proto == htons(ETH_P_8021Q)) { - veh = (struct vlan_ethhdr *)va; - if (veh->h_vlan_encapsulated_proto != htons(ETH_P_IP)) - return -1; - - ll_hlen += VLAN_HLEN; - - } else { - return -1; - } - } - *hdr_flags = LRO_IPV4; - - iph = (struct iphdr *)(va + ll_hlen); - *ip_hdr = iph; - if (iph->protocol != IPPROTO_TCP) - return -1; - *hdr_flags |= LRO_TCP; - *tcpudp_hdr = (u8 *) (*ip_hdr) + (iph->ihl << 2); - - return 0; -} - -static int benet_open(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - struct net_lro_mgr *lro_mgr; - - if (adapter->dev_state < BE_DEV_STATE_INIT) - return -EAGAIN; - - lro_mgr = &pnob->lro_mgr; - lro_mgr->dev = netdev; - - lro_mgr->features = LRO_F_NAPI; - lro_mgr->ip_summed = CHECKSUM_UNNECESSARY; - lro_mgr->ip_summed_aggr = CHECKSUM_UNNECESSARY; - lro_mgr->max_desc = BE_MAX_LRO_DESCRIPTORS; - lro_mgr->lro_arr = pnob->lro_desc; - lro_mgr->get_frag_header = be_get_frag_header; - lro_mgr->max_aggr = adapter->max_rx_coal; - lro_mgr->frag_align_pad = 2; - if (lro_mgr->max_aggr > MAX_SKB_FRAGS) - lro_mgr->max_aggr = MAX_SKB_FRAGS; - - adapter->max_rx_coal = BE_LRO_MAX_PKTS; - - be_update_link_status(adapter); - - /* - * Set carrier on only if Physical Link up - * Either of the port link status up signifies this - */ - if ((adapter->port0_link_sts == BE_PORT_LINK_UP) || - (adapter->port1_link_sts == BE_PORT_LINK_UP)) { - netif_start_queue(netdev); - netif_carrier_on(netdev); - } - - adapter->dev_state = BE_DEV_STATE_OPEN; - napi_enable(&pnob->napi); - be_enable_intr(pnob); - be_enable_eq_intr(pnob); - /* - * RX completion queue may be in dis-armed state. Arm it. - */ - be_notify_cmpl(pnob, 0, pnob->rx_cq_id, 1); - - return 0; -} - -static int benet_close(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - netif_stop_queue(netdev); - synchronize_irq(netdev->irq); - - be_wait_nic_tx_cmplx_cmpl(pnob); - adapter->dev_state = BE_DEV_STATE_INIT; - netif_carrier_off(netdev); - - adapter->port0_link_sts = BE_PORT_LINK_DOWN; - adapter->port1_link_sts = BE_PORT_LINK_DOWN; - be_disable_intr(pnob); - be_disable_eq_intr(pnob); - napi_disable(&pnob->napi); - - return 0; -} - -/* - * Setting a Mac Address for BE - * Takes netdev and a void pointer as arguments. - * The pointer holds the new addres to be used. - */ -static int benet_set_mac_addr(struct net_device *netdev, void *p) -{ - struct sockaddr *addr = p; - struct be_net_object *pnob = netdev_priv(netdev); - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - be_rxf_mac_address_read_write(&pnob->fn_obj, 0, 0, false, true, false, - netdev->dev_addr, NULL, NULL); - /* - * Since we are doing Active-Passive failover, both - * ports should have matching MAC addresses everytime. - */ - be_rxf_mac_address_read_write(&pnob->fn_obj, 1, 0, false, true, false, - netdev->dev_addr, NULL, NULL); - - return 0; -} - -void be_get_stats_timer_handler(unsigned long context) -{ - struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context; - - if (atomic_read(&ctxt->get_stat_flag)) { - atomic_dec(&ctxt->get_stat_flag); - up((void *)ctxt->get_stat_sem_addr); - } - del_timer(&ctxt->get_stats_timer); - return; -} - -void be_get_stat_cb(void *context, int status, - struct MCC_WRB_AMAP *optional_wrb) -{ - struct be_timer_ctxt *ctxt = (struct be_timer_ctxt *)context; - /* - * just up the semaphore if the get_stat_flag - * reads 1. so that the waiter can continue. - * If it is 0, then it was handled by the timer handler. - */ - del_timer(&ctxt->get_stats_timer); - if (atomic_read(&ctxt->get_stat_flag)) { - atomic_dec(&ctxt->get_stat_flag); - up((void *)ctxt->get_stat_sem_addr); - } -} - -struct net_device_stats *benet_get_stats(struct net_device *dev) -{ - struct be_net_object *pnob = netdev_priv(dev); - struct be_adapter *adapter = pnob->adapter; - u64 pa; - struct be_timer_ctxt *ctxt = &adapter->timer_ctxt; - - if (adapter->dev_state != BE_DEV_STATE_OPEN) { - /* Return previously read stats */ - return &(adapter->benet_stats); - } - /* Get Physical Addr */ - pa = pci_map_single(adapter->pdev, adapter->eth_statsp, - sizeof(struct FWCMD_ETH_GET_STATISTICS), - PCI_DMA_FROMDEVICE); - ctxt->get_stat_sem_addr = (unsigned long)&adapter->get_eth_stat_sem; - atomic_inc(&ctxt->get_stat_flag); - - be_rxf_query_eth_statistics(&pnob->fn_obj, adapter->eth_statsp, - cpu_to_le64(pa), be_get_stat_cb, ctxt, - NULL); - - ctxt->get_stats_timer.data = (unsigned long)ctxt; - mod_timer(&ctxt->get_stats_timer, (jiffies + (HZ * 2))); - down((void *)ctxt->get_stat_sem_addr); /* callback will unblock us */ - - /* Adding port0 and port1 stats. */ - adapter->benet_stats.rx_packets = - adapter->eth_statsp->params.response.p0recvdtotalframes + - adapter->eth_statsp->params.response.p1recvdtotalframes; - adapter->benet_stats.tx_packets = - adapter->eth_statsp->params.response.p0xmitunicastframes + - adapter->eth_statsp->params.response.p1xmitunicastframes; - adapter->benet_stats.tx_bytes = - adapter->eth_statsp->params.response.p0xmitbyteslsd + - adapter->eth_statsp->params.response.p1xmitbyteslsd; - adapter->benet_stats.rx_errors = - adapter->eth_statsp->params.response.p0crcerrors + - adapter->eth_statsp->params.response.p1crcerrors; - adapter->benet_stats.rx_errors += - adapter->eth_statsp->params.response.p0alignmentsymerrs + - adapter->eth_statsp->params.response.p1alignmentsymerrs; - adapter->benet_stats.rx_errors += - adapter->eth_statsp->params.response.p0inrangelenerrors + - adapter->eth_statsp->params.response.p1inrangelenerrors; - adapter->benet_stats.rx_bytes = - adapter->eth_statsp->params.response.p0recvdtotalbytesLSD + - adapter->eth_statsp->params.response.p1recvdtotalbytesLSD; - adapter->benet_stats.rx_crc_errors = - adapter->eth_statsp->params.response.p0crcerrors + - adapter->eth_statsp->params.response.p1crcerrors; - - adapter->benet_stats.tx_packets += - adapter->eth_statsp->params.response.p0xmitmulticastframes + - adapter->eth_statsp->params.response.p1xmitmulticastframes; - adapter->benet_stats.tx_packets += - adapter->eth_statsp->params.response.p0xmitbroadcastframes + - adapter->eth_statsp->params.response.p1xmitbroadcastframes; - adapter->benet_stats.tx_errors = 0; - - adapter->benet_stats.multicast = - adapter->eth_statsp->params.response.p0xmitmulticastframes + - adapter->eth_statsp->params.response.p1xmitmulticastframes; - - adapter->benet_stats.rx_fifo_errors = - adapter->eth_statsp->params.response.p0rxfifooverflowdropped + - adapter->eth_statsp->params.response.p1rxfifooverflowdropped; - adapter->benet_stats.rx_frame_errors = - adapter->eth_statsp->params.response.p0alignmentsymerrs + - adapter->eth_statsp->params.response.p1alignmentsymerrs; - adapter->benet_stats.rx_length_errors = - adapter->eth_statsp->params.response.p0inrangelenerrors + - adapter->eth_statsp->params.response.p1inrangelenerrors; - adapter->benet_stats.rx_length_errors += - adapter->eth_statsp->params.response.p0outrangeerrors + - adapter->eth_statsp->params.response.p1outrangeerrors; - adapter->benet_stats.rx_length_errors += - adapter->eth_statsp->params.response.p0frametoolongerrors + - adapter->eth_statsp->params.response.p1frametoolongerrors; - - pci_unmap_single(adapter->pdev, (ulong) adapter->eth_statsp, - sizeof(struct FWCMD_ETH_GET_STATISTICS), - PCI_DMA_FROMDEVICE); - return &(adapter->benet_stats); - -} - -static void be_start_tx(struct be_net_object *pnob, u32 nposted) -{ -#define CSR_ETH_MAX_SQPOSTS 255 - struct SQ_DB_AMAP sqdb; - - sqdb.dw[0] = 0; - - AMAP_SET_BITS_PTR(SQ_DB, cid, &sqdb, pnob->tx_q_id); - while (nposted) { - if (nposted > CSR_ETH_MAX_SQPOSTS) { - AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb, - CSR_ETH_MAX_SQPOSTS); - nposted -= CSR_ETH_MAX_SQPOSTS; - } else { - AMAP_SET_BITS_PTR(SQ_DB, numPosted, &sqdb, nposted); - nposted = 0; - } - PD_WRITE(&pnob->fn_obj, etx_sq_db, sqdb.dw[0]); - } - - return; -} - -static void update_tx_rate(struct be_adapter *adapter) -{ - /* update the rate once in two seconds */ - if ((jiffies - adapter->eth_tx_jiffies) > 2 * (HZ)) { - u32 r; - r = adapter->eth_tx_bytes / - ((jiffies - adapter->eth_tx_jiffies) / (HZ)); - r = (r / 1000000); /* M bytes/s */ - adapter->be_stat.bes_eth_tx_rate = (r * 8); /* M bits/s */ - adapter->eth_tx_jiffies = jiffies; - adapter->eth_tx_bytes = 0; - } -} - -static int wrb_cnt_in_skb(struct sk_buff *skb) -{ - int cnt = 0; - while (skb) { - if (skb->len > skb->data_len) - cnt++; - cnt += skb_shinfo(skb)->nr_frags; - skb = skb_shinfo(skb)->frag_list; - } - BUG_ON(cnt > BE_MAX_TX_FRAG_COUNT); - return cnt; -} - -static void wrb_fill(struct ETH_WRB_AMAP *wrb, u64 addr, int len) -{ - AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_hi, wrb, addr >> 32); - AMAP_SET_BITS_PTR(ETH_WRB, frag_pa_lo, wrb, addr & 0xFFFFFFFF); - AMAP_SET_BITS_PTR(ETH_WRB, frag_len, wrb, len); -} - -static void wrb_fill_extra(struct ETH_WRB_AMAP *wrb, struct sk_buff *skb, - struct be_net_object *pnob) -{ - wrb->dw[2] = 0; - wrb->dw[3] = 0; - AMAP_SET_BITS_PTR(ETH_WRB, crc, wrb, 1); - if (skb_shinfo(skb)->gso_segs > 1 && skb_shinfo(skb)->gso_size) { - AMAP_SET_BITS_PTR(ETH_WRB, lso, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, lso_mss, wrb, - skb_shinfo(skb)->gso_size); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - u8 proto = ((struct iphdr *)ip_hdr(skb))->protocol; - if (proto == IPPROTO_TCP) - AMAP_SET_BITS_PTR(ETH_WRB, tcpcs, wrb, 1); - else if (proto == IPPROTO_UDP) - AMAP_SET_BITS_PTR(ETH_WRB, udpcs, wrb, 1); - } - if (pnob->vlan_grp && vlan_tx_tag_present(skb)) { - AMAP_SET_BITS_PTR(ETH_WRB, vlan, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, vlan_tag, wrb, vlan_tx_tag_get(skb)); - } -} - -static inline void wrb_copy_extra(struct ETH_WRB_AMAP *to, - struct ETH_WRB_AMAP *from) -{ - - to->dw[2] = from->dw[2]; - to->dw[3] = from->dw[3]; -} - -/* Returns the actual count of wrbs used including a possible dummy */ -static int copy_skb_to_txq(struct be_net_object *pnob, struct sk_buff *skb, - u32 wrb_cnt, u32 *copied) -{ - u64 busaddr; - struct ETH_WRB_AMAP *wrb = NULL, *first = NULL; - u32 i; - bool dummy = true; - struct pci_dev *pdev = pnob->adapter->pdev; - - if (wrb_cnt & 1) - wrb_cnt++; - else - dummy = false; - - atomic_add(wrb_cnt, &pnob->tx_q_used); - - while (skb) { - if (skb->len > skb->data_len) { - int len = skb->len - skb->data_len; - busaddr = pci_map_single(pdev, skb->data, len, - PCI_DMA_TODEVICE); - busaddr = cpu_to_le64(busaddr); - wrb = &pnob->tx_q[pnob->tx_q_hd]; - if (first == NULL) { - wrb_fill_extra(wrb, skb, pnob); - first = wrb; - } else { - wrb_copy_extra(wrb, first); - } - wrb_fill(wrb, busaddr, len); - be_adv_txq_hd(pnob); - *copied += len; - } - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - struct skb_frag_struct *frag = - &skb_shinfo(skb)->frags[i]; - busaddr = pci_map_page(pdev, frag->page, - frag->page_offset, frag->size, - PCI_DMA_TODEVICE); - busaddr = cpu_to_le64(busaddr); - wrb = &pnob->tx_q[pnob->tx_q_hd]; - if (first == NULL) { - wrb_fill_extra(wrb, skb, pnob); - first = wrb; - } else { - wrb_copy_extra(wrb, first); - } - wrb_fill(wrb, busaddr, frag->size); - be_adv_txq_hd(pnob); - *copied += frag->size; - } - skb = skb_shinfo(skb)->frag_list; - } - - if (dummy) { - wrb = &pnob->tx_q[pnob->tx_q_hd]; - BUG_ON(first == NULL); - wrb_copy_extra(wrb, first); - wrb_fill(wrb, 0, 0); - be_adv_txq_hd(pnob); - } - AMAP_SET_BITS_PTR(ETH_WRB, complete, wrb, 1); - AMAP_SET_BITS_PTR(ETH_WRB, last, wrb, 1); - return wrb_cnt; -} - -/* For each skb transmitted, tx_ctxt stores the num of wrbs in the - * start index and skb pointer in the end index - */ -static inline void be_tx_wrb_info_remember(struct be_net_object *pnob, - struct sk_buff *skb, int wrb_cnt, - u32 start) -{ - *(u32 *) (&pnob->tx_ctxt[start]) = wrb_cnt; - index_adv(&start, wrb_cnt - 1, pnob->tx_q_len); - pnob->tx_ctxt[start] = skb; -} - -static int benet_xmit(struct sk_buff *skb, struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - u32 wrb_cnt, copied = 0; - u32 start = pnob->tx_q_hd; - - adapter->be_stat.bes_tx_reqs++; - - wrb_cnt = wrb_cnt_in_skb(skb); - spin_lock_bh(&adapter->txq_lock); - if ((pnob->tx_q_len - 2 - atomic_read(&pnob->tx_q_used)) <= wrb_cnt) { - netif_stop_queue(pnob->netdev); - spin_unlock_bh(&adapter->txq_lock); - adapter->be_stat.bes_tx_fails++; - return NETDEV_TX_BUSY; - } - spin_unlock_bh(&adapter->txq_lock); - - wrb_cnt = copy_skb_to_txq(pnob, skb, wrb_cnt, &copied); - be_tx_wrb_info_remember(pnob, skb, wrb_cnt, start); - - be_start_tx(pnob, wrb_cnt); - - adapter->eth_tx_bytes += copied; - adapter->be_stat.bes_tx_wrbs += wrb_cnt; - update_tx_rate(adapter); - netdev->trans_start = jiffies; - - return NETDEV_TX_OK; -} - -/* - * This is the driver entry point to change the mtu of the device - * Returns 0 for success and errno for failure. - */ -static int benet_change_mtu(struct net_device *netdev, int new_mtu) -{ - /* - * BE supports jumbo frame size upto 9000 bytes including the link layer - * header. Considering the different variants of frame formats possible - * like VLAN, SNAP/LLC, the maximum possible value for MTU is 8974 bytes - */ - - if (new_mtu < (ETH_ZLEN + ETH_FCS_LEN) || (new_mtu > BE_MAX_MTU)) { - dev_info(&netdev->dev, "Invalid MTU requested. " - "Must be between %d and %d bytes\n", - (ETH_ZLEN + ETH_FCS_LEN), BE_MAX_MTU); - return -EINVAL; - } - dev_info(&netdev->dev, "MTU changed from %d to %d\n", - netdev->mtu, new_mtu); - netdev->mtu = new_mtu; - return 0; -} - -/* - * This is the driver entry point to register a vlan with the device - */ -static void benet_vlan_register(struct net_device *netdev, - struct vlan_group *grp) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - be_disable_eq_intr(pnob); - pnob->vlan_grp = grp; - pnob->num_vlans = 0; - be_enable_eq_intr(pnob); -} - -/* - * This is the driver entry point to add a vlan vlan_id - * with the device netdev - */ -static void benet_vlan_add_vid(struct net_device *netdev, u16 vlan_id) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - if (pnob->num_vlans == (BE_NUM_VLAN_SUPPORTED - 1)) { - /* no way to return an error */ - dev_info(&netdev->dev, - "BladeEngine: Cannot configure more than %d Vlans\n", - BE_NUM_VLAN_SUPPORTED); - return; - } - /* The new vlan tag will be in the slot indicated by num_vlans. */ - pnob->vlan_tag[pnob->num_vlans++] = vlan_id; - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); -} - -/* - * This is the driver entry point to remove a vlan vlan_id - * with the device netdev - */ -static void benet_vlan_rem_vid(struct net_device *netdev, u16 vlan_id) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - u32 i, value; - - /* - * In Blade Engine, we support 32 vlan tag filters across both ports. - * To program a vlan tag, the RXF_RTPR_CSR register is used. - * Each 32-bit value of RXF_RTDR_CSR can address 2 vlan tag entries. - * The Vlan table is of depth 16. thus we support 32 tags. - */ - - value = vlan_id | VLAN_VALID_BIT; - for (i = 0; i < BE_NUM_VLAN_SUPPORTED; i++) { - if (pnob->vlan_tag[i] == vlan_id) - break; - } - - if (i == BE_NUM_VLAN_SUPPORTED) - return; - /* Now compact the vlan tag array by removing hole created. */ - while ((i + 1) < BE_NUM_VLAN_SUPPORTED) { - pnob->vlan_tag[i] = pnob->vlan_tag[i + 1]; - i++; - } - if ((i + 1) == BE_NUM_VLAN_SUPPORTED) - pnob->vlan_tag[i] = (u16) 0x0; - pnob->num_vlans--; - be_rxf_vlan_config(&pnob->fn_obj, false, pnob->num_vlans, - pnob->vlan_tag, NULL, NULL, NULL); -} - -/* - * This function is called to program multicast - * address in the multicast filter of the ASIC. - */ -static void be_set_multicast_filter(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct dev_mc_list *mc_ptr; - u8 mac_addr[32][ETH_ALEN]; - int i; - - if (netdev->flags & IFF_ALLMULTI) { - /* set BE in Multicast promiscuous */ - be_rxf_multicast_config(&pnob->fn_obj, true, 0, NULL, NULL, - NULL, NULL); - return; - } - - for (mc_ptr = netdev->mc_list, i = 0; mc_ptr; - mc_ptr = mc_ptr->next, i++) { - memcpy(&mac_addr[i][0], mc_ptr->dmi_addr, ETH_ALEN); - } - - /* reset the promiscuous mode also. */ - be_rxf_multicast_config(&pnob->fn_obj, false, i, - &mac_addr[0][0], NULL, NULL, NULL); -} - -/* - * This is the driver entry point to set multicast list - * with the device netdev. This function will be used to - * set promiscuous mode or multicast promiscuous mode - * or multicast mode.... - */ -static void benet_set_multicast_list(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - - if (netdev->flags & IFF_PROMISC) { - be_rxf_promiscuous(&pnob->fn_obj, 1, 1, NULL, NULL, NULL); - } else { - be_rxf_promiscuous(&pnob->fn_obj, 0, 0, NULL, NULL, NULL); - be_set_multicast_filter(netdev); - } -} - -int benet_init(struct net_device *netdev) -{ - struct be_net_object *pnob = netdev_priv(netdev); - struct be_adapter *adapter = pnob->adapter; - - ether_setup(netdev); - - netdev->open = &benet_open; - netdev->stop = &benet_close; - netdev->hard_start_xmit = &benet_xmit; - - netdev->get_stats = &benet_get_stats; - - netdev->set_multicast_list = &benet_set_multicast_list; - - netdev->change_mtu = &benet_change_mtu; - netdev->set_mac_address = &benet_set_mac_addr; - - netdev->vlan_rx_register = benet_vlan_register; - netdev->vlan_rx_add_vid = benet_vlan_add_vid; - netdev->vlan_rx_kill_vid = benet_vlan_rem_vid; - - netdev->features = - NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_HW_VLAN_RX | NETIF_F_TSO | - NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_FILTER | NETIF_F_IP_CSUM; - - netdev->flags |= IFF_MULTICAST; - - /* If device is DAC Capable, set the HIGHDMA flag for netdevice. */ - if (adapter->dma_64bit_cap) - netdev->features |= NETIF_F_HIGHDMA; - - SET_ETHTOOL_OPS(netdev, &be_ethtool_ops); - return 0; -} diff --git a/drivers/staging/benet/benet.h b/drivers/staging/benet/benet.h deleted file mode 100644 index 09a1f081772..00000000000 --- a/drivers/staging/benet/benet.h +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef _BENET_H_ -#define _BENET_H_ - -#include -#include -#include -#include "hwlib.h" - -#define _SA_MODULE_NAME "net-driver" - -#define VLAN_VALID_BIT 0x8000 -#define BE_NUM_VLAN_SUPPORTED 32 -#define BE_PORT_LINK_DOWN 0000 -#define BE_PORT_LINK_UP 0001 -#define BE_MAX_TX_FRAG_COUNT (30) - -/* Flag bits for send operation */ -#define IPCS (1 << 0) /* Enable IP checksum offload */ -#define UDPCS (1 << 1) /* Enable UDP checksum offload */ -#define TCPCS (1 << 2) /* Enable TCP checksum offload */ -#define LSO (1 << 3) /* Enable Large Segment offload */ -#define ETHVLAN (1 << 4) /* Enable VLAN insert */ -#define ETHEVENT (1 << 5) /* Generate event on completion */ -#define ETHCOMPLETE (1 << 6) /* Generate completion when done */ -#define IPSEC (1 << 7) /* Enable IPSEC */ -#define FORWARD (1 << 8) /* Send the packet in forwarding path */ -#define FIN (1 << 9) /* Issue FIN segment */ - -#define BE_MAX_MTU 8974 - -#define BE_MAX_LRO_DESCRIPTORS 8 -#define BE_LRO_MAX_PKTS 64 -#define BE_MAX_FRAGS_PER_FRAME 6 - -extern const char be_drvr_ver[]; -extern char be_fw_ver[]; -extern char be_driver_name[]; - -extern struct ethtool_ops be_ethtool_ops; - -#define BE_DEV_STATE_NONE 0 -#define BE_DEV_STATE_INIT 1 -#define BE_DEV_STATE_OPEN 2 -#define BE_DEV_STATE_SUSPEND 3 - -/* This structure is used to describe physical fragments to use - * for DMAing data from NIC. - */ -struct be_recv_buffer { - struct list_head rxb_list; /* for maintaining a linked list */ - void *rxb_va; /* buffer virtual address */ - u32 rxb_pa_lo; /* low part of physical address */ - u32 rxb_pa_hi; /* high part of physical address */ - u32 rxb_len; /* length of recv buffer */ - void *rxb_ctxt; /* context for OSM driver to use */ -}; - -/* - * fragment list to describe scattered data. - */ -struct be_tx_frag_list { - u32 txb_len; /* Size of this fragment */ - u32 txb_pa_lo; /* Lower 32 bits of 64 bit physical addr */ - u32 txb_pa_hi; /* Higher 32 bits of 64 bit physical addr */ -}; - -struct be_rx_page_info { - struct page *page; - dma_addr_t bus; - u16 page_offset; -}; - -/* - * This structure is the main tracking structure for a NIC interface. - */ -struct be_net_object { - /* MCC Ring - used to send fwcmds to embedded ARM processor */ - struct MCC_WRB_AMAP *mcc_q; /* VA of the start of the ring */ - u32 mcc_q_len; /* # of WRB entries in this ring */ - u32 mcc_q_size; - u32 mcc_q_hd; /* MCC ring head */ - u8 mcc_q_created; /* flag to help cleanup */ - struct be_mcc_object mcc_q_obj; /* BECLIB's MCC ring Object */ - dma_addr_t mcc_q_bus; /* DMA'ble bus address */ - - /* MCC Completion Ring - FW responses to fwcmds sent from MCC ring */ - struct MCC_CQ_ENTRY_AMAP *mcc_cq; /* VA of the start of the ring */ - u32 mcc_cq_len; /* # of compl. entries in this ring */ - u32 mcc_cq_size; - u32 mcc_cq_tl; /* compl. ring tail */ - u8 mcc_cq_created; /* flag to help cleanup */ - struct be_cq_object mcc_cq_obj; /* BECLIB's MCC compl. ring object */ - u32 mcc_cq_id; /* MCC ring ID */ - dma_addr_t mcc_cq_bus; /* DMA'ble bus address */ - - struct ring_desc mb_rd; /* RD for MCC_MAIL_BOX */ - void *mb_ptr; /* mailbox ptr to be freed */ - dma_addr_t mb_bus; /* DMA'ble bus address */ - u32 mb_size; - - /* BEClib uses an array of context objects to track outstanding - * requests to the MCC. We need allocate the same number of - * conext entries as the number of entries in the MCC WRB ring - */ - u32 mcc_wrb_ctxt_size; - void *mcc_wrb_ctxt; /* pointer to the context area */ - u32 mcc_wrb_ctxtLen; /* Number of entries in the context */ - /* - * NIC send request ring - used for xmitting raw ether frames. - */ - struct ETH_WRB_AMAP *tx_q; /* VA of the start of the ring */ - u32 tx_q_len; /* # if entries in the send ring */ - u32 tx_q_size; - u32 tx_q_hd; /* Head index. Next req. goes here */ - u32 tx_q_tl; /* Tail indx. oldest outstanding req. */ - u8 tx_q_created; /* flag to help cleanup */ - struct be_ethsq_object tx_q_obj;/* BECLIB's send Q handle */ - dma_addr_t tx_q_bus; /* DMA'ble bus address */ - u32 tx_q_id; /* send queue ring ID */ - u32 tx_q_port; /* 0 no binding, 1 port A, 2 port B */ - atomic_t tx_q_used; /* # of WRBs used */ - /* ptr to an array in which we store context info for each send req. */ - void **tx_ctxt; - /* - * NIC Send compl. ring - completion status for all NIC frames xmitted. - */ - struct ETH_TX_COMPL_AMAP *tx_cq;/* VA of start of the ring */ - u32 txcq_len; /* # of entries in the ring */ - u32 tx_cq_size; - /* - * index into compl ring where the host expects next completion entry - */ - u32 tx_cq_tl; - u32 tx_cq_id; /* completion queue id */ - u8 tx_cq_created; /* flag to help cleanup */ - struct be_cq_object tx_cq_obj; - dma_addr_t tx_cq_bus; /* DMA'ble bus address */ - /* - * Event Queue - all completion entries post events here. - */ - struct EQ_ENTRY_AMAP *event_q; /* VA of start of event queue */ - u32 event_q_len; /* # of entries */ - u32 event_q_size; - u32 event_q_tl; /* Tail of the event queue */ - u32 event_q_id; /* Event queue ID */ - u8 event_q_created; /* flag to help cleanup */ - struct be_eq_object event_q_obj; /* Queue handle */ - dma_addr_t event_q_bus; /* DMA'ble bus address */ - /* - * NIC receive queue - Data buffers to be used for receiving unicast, - * broadcast and multi-cast frames are posted here. - */ - struct ETH_RX_D_AMAP *rx_q; /* VA of start of the queue */ - u32 rx_q_len; /* # of entries */ - u32 rx_q_size; - u32 rx_q_hd; /* Head of the queue */ - atomic_t rx_q_posted; /* number of posted buffers */ - u32 rx_q_id; /* queue ID */ - u8 rx_q_created; /* flag to help cleanup */ - struct be_ethrq_object rx_q_obj; /* NIC RX queue handle */ - dma_addr_t rx_q_bus; /* DMA'ble bus address */ - /* - * Pointer to an array of opaque context object for use by OSM driver - */ - void **rx_ctxt; - /* - * NIC unicast RX completion queue - all unicast ether frame completion - * statuses from BE come here. - */ - struct ETH_RX_COMPL_AMAP *rx_cq; /* VA of start of the queue */ - u32 rx_cq_len; /* # of entries */ - u32 rx_cq_size; - u32 rx_cq_tl; /* Tail of the queue */ - u32 rx_cq_id; /* queue ID */ - u8 rx_cq_created; /* flag to help cleanup */ - struct be_cq_object rx_cq_obj; /* queue handle */ - dma_addr_t rx_cq_bus; /* DMA'ble bus address */ - struct be_function_object fn_obj; /* function object */ - bool fn_obj_created; - u32 rx_buf_size; /* Size of the RX buffers */ - - struct net_device *netdev; - struct be_recv_buffer eth_rx_bufs[256]; /* to pass Rx buffer - addresses */ - struct be_adapter *adapter; /* Pointer to OSM adapter */ - u32 devno; /* OSM, network dev no. */ - u32 use_port; /* Current active port */ - struct be_rx_page_info *rx_page_info; /* Array of Rx buf pages */ - u32 rx_pg_info_hd; /* Head of queue */ - int rxbuf_post_fail; /* RxBuff posting fail count */ - bool rx_pg_shared; /* Is an allocsted page shared as two frags ? */ - struct vlan_group *vlan_grp; - u32 num_vlans; /* Number of vlans in BE's filter */ - u16 vlan_tag[BE_NUM_VLAN_SUPPORTED]; /* vlans currently configured */ - struct napi_struct napi; - struct net_lro_mgr lro_mgr; - struct net_lro_desc lro_desc[BE_MAX_LRO_DESCRIPTORS]; -}; - -#define NET_FH(np) (&(np)->fn_obj) - -/* - * BE driver statistics. - */ -struct be_drvr_stat { - u32 bes_tx_reqs; /* number of TX requests initiated */ - u32 bes_tx_fails; /* number of TX requests that failed */ - u32 bes_fwd_reqs; /* number of send reqs through forwarding i/f */ - u32 bes_tx_wrbs; /* number of tx WRBs used */ - - u32 bes_ints; /* number of interrupts */ - u32 bes_polls; /* number of times NAPI called poll function */ - u32 bes_events; /* total evet entries processed */ - u32 bes_tx_events; /* number of tx completion events */ - u32 bes_rx_events; /* number of ucast rx completion events */ - u32 bes_tx_compl; /* number of tx completion entries processed */ - u32 bes_rx_compl; /* number of rx completion entries - processed */ - u32 bes_ethrx_post_fail; /* number of ethrx buffer alloc - failures */ - /* - * number of non ether type II frames dropped where - * frame len > length field of Mac Hdr - */ - u32 bes_802_3_dropped_frames; - /* - * number of non ether type II frames malformed where - * in frame len < length field of Mac Hdr - */ - u32 bes_802_3_malformed_frames; - u32 bes_ips; /* interrupts / sec */ - u32 bes_prev_ints; /* bes_ints at last IPS calculation */ - u16 bes_eth_tx_rate; /* ETH TX rate - Mb/sec */ - u16 bes_eth_rx_rate; /* ETH RX rate - Mb/sec */ - u32 bes_rx_coal; /* Num pkts coalasced */ - u32 bes_rx_flush; /* Num times coalasced */ - u32 bes_link_change_physical; /*Num of times physical link changed */ - u32 bes_link_change_virtual; /*Num of times virtual link changed */ - u32 bes_rx_misc_pkts; /* Misc pkts received */ -}; - -/* Maximum interrupt delay (in microseconds) allowed */ -#define MAX_EQD 120 - -/* - * timer to prevent system shutdown hang for ever if h/w stops responding - */ -struct be_timer_ctxt { - atomic_t get_stat_flag; - struct timer_list get_stats_timer; - unsigned long get_stat_sem_addr; -} ; - -/* This structure is the main BladeEngine driver context. */ -struct be_adapter { - struct net_device *netdevp; - struct be_drvr_stat be_stat; - struct net_device_stats benet_stats; - - /* PCI BAR mapped addresses */ - u8 __iomem *csr_va; /* CSR */ - u8 __iomem *db_va; /* Door Bell */ - u8 __iomem *pci_va; /* PCI Config */ - - struct tasklet_struct sts_handler; - struct timer_list cq_timer; - spinlock_t int_lock; /* to protect the isr field in adapter */ - - struct FWCMD_ETH_GET_STATISTICS *eth_statsp; - /* - * This will enable the use of ethtool to enable or disable - * Checksum on Rx pkts to be obeyed or disobeyed. - * If this is true = 1, then whatever is the checksum on the - * Received pkt as per BE, it will be given to the stack. - * Else the stack will re calculate it. - */ - bool rx_csum; - /* - * This will enable the use of ethtool to enable or disable - * Coalese on Rx pkts to be obeyed or disobeyed. - * If this is grater than 0 and less than 16 then coalascing - * is enabled else it is disabled - */ - u32 max_rx_coal; - struct pci_dev *pdev; /* Pointer to OS's PCI dvice */ - - spinlock_t txq_lock; /* to stop/wake queue based on tx_q_used */ - - u32 isr; /* copy of Intr status reg. */ - - u32 port0_link_sts; /* Port 0 link status */ - u32 port1_link_sts; /* port 1 list status */ - struct BE_LINK_STATUS *be_link_sts; - - /* pointer to the first netobject of this adapter */ - struct be_net_object *net_obj; - - /* Flags to indicate what to clean up */ - bool tasklet_started; - bool isr_registered; - /* - * adaptive interrupt coalescing (AIC) related - */ - bool enable_aic; /* 1 if AIC is enabled */ - u16 min_eqd; /* minimum EQ delay in usec */ - u16 max_eqd; /* minimum EQ delay in usec */ - u16 cur_eqd; /* current EQ delay in usec */ - /* - * book keeping for interrupt / sec and TX/RX rate calculation - */ - ulong ips_jiffies; /* jiffies at last IPS calc */ - u32 eth_tx_bytes; - ulong eth_tx_jiffies; - u32 eth_rx_bytes; - ulong eth_rx_jiffies; - - struct semaphore get_eth_stat_sem; - - /* timer ctxt to prevent shutdown hanging due to un-responsive BE */ - struct be_timer_ctxt timer_ctxt; - -#define BE_MAX_MSIX_VECTORS 32 -#define BE_MAX_REQ_MSIX_VECTORS 1 /* only one EQ in Linux driver */ - struct msix_entry msix_entries[BE_MAX_MSIX_VECTORS]; - bool msix_enabled; - bool dma_64bit_cap; /* the Device DAC capable or not */ - u8 dev_state; /* The current state of the device */ - u8 dev_pm_state; /* The State of device before going to suspend */ -}; - -/* - * Every second we look at the ints/sec and adjust eq_delay - * between adapter->min_eqd and adapter->max_eqd to keep the ints/sec between - * IPS_HI_WM and IPS_LO_WM. - */ -#define IPS_HI_WM 18000 -#define IPS_LO_WM 8000 - - -static inline void index_adv(u32 *index, u32 val, u32 limit) -{ - BUG_ON(limit & (limit-1)); - *index = (*index + val) & (limit - 1); -} - -static inline void index_inc(u32 *index, u32 limit) -{ - BUG_ON(limit & (limit-1)); - *index = (*index + 1) & (limit - 1); -} - -static inline void be_adv_eq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->event_q_tl, pnob->event_q_len); -} - -static inline void be_adv_txq_hd(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_q_hd, pnob->tx_q_len); -} - -static inline void be_adv_txq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_q_tl, pnob->tx_q_len); -} - -static inline void be_adv_txcq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->tx_cq_tl, pnob->txcq_len); -} - -static inline void be_adv_rxq_hd(struct be_net_object *pnob) -{ - index_inc(&pnob->rx_q_hd, pnob->rx_q_len); -} - -static inline void be_adv_rxcq_tl(struct be_net_object *pnob) -{ - index_inc(&pnob->rx_cq_tl, pnob->rx_cq_len); -} - -static inline u32 tx_compl_lastwrb_idx_get(struct be_net_object *pnob) -{ - return (pnob->tx_q_tl + *(u32 *)&pnob->tx_ctxt[pnob->tx_q_tl] - 1) - & (pnob->tx_q_len - 1); -} - -int benet_init(struct net_device *); -int be_ethtool_ioctl(struct net_device *, struct ifreq *); -struct net_device_stats *benet_get_stats(struct net_device *); -void be_process_intr(unsigned long context); -irqreturn_t be_int(int irq, void *dev); -void be_post_eth_rx_buffs(struct be_net_object *); -void be_get_stat_cb(void *, int, struct MCC_WRB_AMAP *); -void be_get_stats_timer_handler(unsigned long); -void be_wait_nic_tx_cmplx_cmpl(struct be_net_object *); -void be_print_link_info(struct BE_LINK_STATUS *); -void be_update_link_status(struct be_adapter *); -void be_init_procfs(struct be_adapter *); -void be_cleanup_procfs(struct be_adapter *); -int be_poll(struct napi_struct *, int); -struct ETH_RX_COMPL_AMAP *be_get_rx_cmpl(struct be_net_object *); -void be_notify_cmpl(struct be_net_object *, int, int, int); -void be_enable_intr(struct be_net_object *); -void be_enable_eq_intr(struct be_net_object *); -void be_disable_intr(struct be_net_object *); -void be_disable_eq_intr(struct be_net_object *); -int be_set_uc_mac_adr(struct be_net_object *, u8, u8, u8, - u8 *, mcc_wrb_cqe_callback, void *); -int be_get_flow_ctl(struct be_function_object *pFnObj, bool *, bool *); -void process_one_tx_compl(struct be_net_object *pnob, u32 end_idx); - -#endif /* _BENET_H_ */ diff --git a/drivers/staging/benet/bestatus.h b/drivers/staging/benet/bestatus.h deleted file mode 100644 index 59c7a4b6222..00000000000 --- a/drivers/staging/benet/bestatus.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef _BESTATUS_H_ -#define _BESTATUS_H_ - -#define BE_SUCCESS (0x00000000L) -/* - * MessageId: BE_PENDING - * The BladeEngine Driver call succeeded, and pended operation. - */ -#define BE_PENDING (0x20070001L) -#define BE_STATUS_PENDING (BE_PENDING) -/* - * MessageId: BE_NOT_OK - * An error occurred. - */ -#define BE_NOT_OK (0xE0070002L) -/* - * MessageId: BE_STATUS_SYSTEM_RESOURCES - * Insufficient host system resources exist to complete the API. - */ -#define BE_STATUS_SYSTEM_RESOURCES (0xE0070003L) -/* - * MessageId: BE_STATUS_CHIP_RESOURCES - * Insufficient chip resources exist to complete the API. - */ -#define BE_STATUS_CHIP_RESOURCES (0xE0070004L) -/* - * MessageId: BE_STATUS_NO_RESOURCE - * Insufficient resources to complete request. - */ -#define BE_STATUS_NO_RESOURCE (0xE0070005L) -/* - * MessageId: BE_STATUS_BUSY - * Resource is currently busy. - */ -#define BE_STATUS_BUSY (0xE0070006L) -/* - * MessageId: BE_STATUS_INVALID_PARAMETER - * Invalid Parameter in request. - */ -#define BE_STATUS_INVALID_PARAMETER (0xE0000007L) -/* - * MessageId: BE_STATUS_NOT_SUPPORTED - * Requested operation is not supported. - */ -#define BE_STATUS_NOT_SUPPORTED (0xE000000DL) - -/* - * *************************************************************************** - * E T H E R N E T S T A T U S - * *************************************************************************** - */ - -/* - * MessageId: BE_ETH_TX_ERROR - * The Ethernet device driver failed to transmit a packet. - */ -#define BE_ETH_TX_ERROR (0xE0070101L) - -/* - * *************************************************************************** - * S H A R E D S T A T U S - * *************************************************************************** - */ - -/* - * MessageId: BE_STATUS_VBD_INVALID_VERSION - * The device driver is not compatible with this version of the VBD. - */ -#define BE_STATUS_INVALID_VERSION (0xE0070402L) -/* - * MessageId: BE_STATUS_DOMAIN_DENIED - * The operation failed to complete due to insufficient access - * rights for the requesting domain. - */ -#define BE_STATUS_DOMAIN_DENIED (0xE0070403L) -/* - * MessageId: BE_STATUS_TCP_NOT_STARTED - * The embedded TCP/IP stack has not been started. - */ -#define BE_STATUS_TCP_NOT_STARTED (0xE0070409L) -/* - * MessageId: BE_STATUS_NO_MCC_WRB - * No free MCC WRB are available for posting the request. - */ -#define BE_STATUS_NO_MCC_WRB (0xE0070414L) - -#endif /* _BESTATUS_ */ diff --git a/drivers/staging/benet/cev.h b/drivers/staging/benet/cev.h deleted file mode 100644 index 30996920a54..00000000000 --- a/drivers/staging/benet/cev.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __cev_amap_h__ -#define __cev_amap_h__ -#include "ep.h" - -/* - * Host Interrupt Status Register 0. The first of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ0 through EQ31. - */ -struct BE_CEV_ISR0_CSR_AMAP { - u8 interrupt0; /* DWORD 0 */ - u8 interrupt1; /* DWORD 0 */ - u8 interrupt2; /* DWORD 0 */ - u8 interrupt3; /* DWORD 0 */ - u8 interrupt4; /* DWORD 0 */ - u8 interrupt5; /* DWORD 0 */ - u8 interrupt6; /* DWORD 0 */ - u8 interrupt7; /* DWORD 0 */ - u8 interrupt8; /* DWORD 0 */ - u8 interrupt9; /* DWORD 0 */ - u8 interrupt10; /* DWORD 0 */ - u8 interrupt11; /* DWORD 0 */ - u8 interrupt12; /* DWORD 0 */ - u8 interrupt13; /* DWORD 0 */ - u8 interrupt14; /* DWORD 0 */ - u8 interrupt15; /* DWORD 0 */ - u8 interrupt16; /* DWORD 0 */ - u8 interrupt17; /* DWORD 0 */ - u8 interrupt18; /* DWORD 0 */ - u8 interrupt19; /* DWORD 0 */ - u8 interrupt20; /* DWORD 0 */ - u8 interrupt21; /* DWORD 0 */ - u8 interrupt22; /* DWORD 0 */ - u8 interrupt23; /* DWORD 0 */ - u8 interrupt24; /* DWORD 0 */ - u8 interrupt25; /* DWORD 0 */ - u8 interrupt26; /* DWORD 0 */ - u8 interrupt27; /* DWORD 0 */ - u8 interrupt28; /* DWORD 0 */ - u8 interrupt29; /* DWORD 0 */ - u8 interrupt30; /* DWORD 0 */ - u8 interrupt31; /* DWORD 0 */ -} __packed; -struct CEV_ISR0_CSR_AMAP { - u32 dw[1]; -}; - -/* - * Host Interrupt Status Register 1. The second of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ32 through EQ63. - */ -struct BE_CEV_ISR1_CSR_AMAP { - u8 interrupt32; /* DWORD 0 */ - u8 interrupt33; /* DWORD 0 */ - u8 interrupt34; /* DWORD 0 */ - u8 interrupt35; /* DWORD 0 */ - u8 interrupt36; /* DWORD 0 */ - u8 interrupt37; /* DWORD 0 */ - u8 interrupt38; /* DWORD 0 */ - u8 interrupt39; /* DWORD 0 */ - u8 interrupt40; /* DWORD 0 */ - u8 interrupt41; /* DWORD 0 */ - u8 interrupt42; /* DWORD 0 */ - u8 interrupt43; /* DWORD 0 */ - u8 interrupt44; /* DWORD 0 */ - u8 interrupt45; /* DWORD 0 */ - u8 interrupt46; /* DWORD 0 */ - u8 interrupt47; /* DWORD 0 */ - u8 interrupt48; /* DWORD 0 */ - u8 interrupt49; /* DWORD 0 */ - u8 interrupt50; /* DWORD 0 */ - u8 interrupt51; /* DWORD 0 */ - u8 interrupt52; /* DWORD 0 */ - u8 interrupt53; /* DWORD 0 */ - u8 interrupt54; /* DWORD 0 */ - u8 interrupt55; /* DWORD 0 */ - u8 interrupt56; /* DWORD 0 */ - u8 interrupt57; /* DWORD 0 */ - u8 interrupt58; /* DWORD 0 */ - u8 interrupt59; /* DWORD 0 */ - u8 interrupt60; /* DWORD 0 */ - u8 interrupt61; /* DWORD 0 */ - u8 interrupt62; /* DWORD 0 */ - u8 interrupt63; /* DWORD 0 */ -} __packed; -struct CEV_ISR1_CSR_AMAP { - u32 dw[1]; -}; -/* - * Host Interrupt Status Register 2. The third of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ64 through EQ95. - */ -struct BE_CEV_ISR2_CSR_AMAP { - u8 interrupt64; /* DWORD 0 */ - u8 interrupt65; /* DWORD 0 */ - u8 interrupt66; /* DWORD 0 */ - u8 interrupt67; /* DWORD 0 */ - u8 interrupt68; /* DWORD 0 */ - u8 interrupt69; /* DWORD 0 */ - u8 interrupt70; /* DWORD 0 */ - u8 interrupt71; /* DWORD 0 */ - u8 interrupt72; /* DWORD 0 */ - u8 interrupt73; /* DWORD 0 */ - u8 interrupt74; /* DWORD 0 */ - u8 interrupt75; /* DWORD 0 */ - u8 interrupt76; /* DWORD 0 */ - u8 interrupt77; /* DWORD 0 */ - u8 interrupt78; /* DWORD 0 */ - u8 interrupt79; /* DWORD 0 */ - u8 interrupt80; /* DWORD 0 */ - u8 interrupt81; /* DWORD 0 */ - u8 interrupt82; /* DWORD 0 */ - u8 interrupt83; /* DWORD 0 */ - u8 interrupt84; /* DWORD 0 */ - u8 interrupt85; /* DWORD 0 */ - u8 interrupt86; /* DWORD 0 */ - u8 interrupt87; /* DWORD 0 */ - u8 interrupt88; /* DWORD 0 */ - u8 interrupt89; /* DWORD 0 */ - u8 interrupt90; /* DWORD 0 */ - u8 interrupt91; /* DWORD 0 */ - u8 interrupt92; /* DWORD 0 */ - u8 interrupt93; /* DWORD 0 */ - u8 interrupt94; /* DWORD 0 */ - u8 interrupt95; /* DWORD 0 */ -} __packed; -struct CEV_ISR2_CSR_AMAP { - u32 dw[1]; -}; - -/* - * Host Interrupt Status Register 3. The fourth of four application - * interrupt status registers. This register contains the interrupts - * for Event Queues EQ96 through EQ127. - */ -struct BE_CEV_ISR3_CSR_AMAP { - u8 interrupt96; /* DWORD 0 */ - u8 interrupt97; /* DWORD 0 */ - u8 interrupt98; /* DWORD 0 */ - u8 interrupt99; /* DWORD 0 */ - u8 interrupt100; /* DWORD 0 */ - u8 interrupt101; /* DWORD 0 */ - u8 interrupt102; /* DWORD 0 */ - u8 interrupt103; /* DWORD 0 */ - u8 interrupt104; /* DWORD 0 */ - u8 interrupt105; /* DWORD 0 */ - u8 interrupt106; /* DWORD 0 */ - u8 interrupt107; /* DWORD 0 */ - u8 interrupt108; /* DWORD 0 */ - u8 interrupt109; /* DWORD 0 */ - u8 interrupt110; /* DWORD 0 */ - u8 interrupt111; /* DWORD 0 */ - u8 interrupt112; /* DWORD 0 */ - u8 interrupt113; /* DWORD 0 */ - u8 interrupt114; /* DWORD 0 */ - u8 interrupt115; /* DWORD 0 */ - u8 interrupt116; /* DWORD 0 */ - u8 interrupt117; /* DWORD 0 */ - u8 interrupt118; /* DWORD 0 */ - u8 interrupt119; /* DWORD 0 */ - u8 interrupt120; /* DWORD 0 */ - u8 interrupt121; /* DWORD 0 */ - u8 interrupt122; /* DWORD 0 */ - u8 interrupt123; /* DWORD 0 */ - u8 interrupt124; /* DWORD 0 */ - u8 interrupt125; /* DWORD 0 */ - u8 interrupt126; /* DWORD 0 */ - u8 interrupt127; /* DWORD 0 */ -} __packed; -struct CEV_ISR3_CSR_AMAP { - u32 dw[1]; -}; - -/* Completions and Events block Registers. */ -struct BE_CEV_CSRMAP_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[32]; /* DWORD 1 */ - u8 rsvd2[32]; /* DWORD 2 */ - u8 rsvd3[32]; /* DWORD 3 */ - struct BE_CEV_ISR0_CSR_AMAP isr0; - struct BE_CEV_ISR1_CSR_AMAP isr1; - struct BE_CEV_ISR2_CSR_AMAP isr2; - struct BE_CEV_ISR3_CSR_AMAP isr3; - u8 rsvd4[32]; /* DWORD 8 */ - u8 rsvd5[32]; /* DWORD 9 */ - u8 rsvd6[32]; /* DWORD 10 */ - u8 rsvd7[32]; /* DWORD 11 */ - u8 rsvd8[32]; /* DWORD 12 */ - u8 rsvd9[32]; /* DWORD 13 */ - u8 rsvd10[32]; /* DWORD 14 */ - u8 rsvd11[32]; /* DWORD 15 */ - u8 rsvd12[32]; /* DWORD 16 */ - u8 rsvd13[32]; /* DWORD 17 */ - u8 rsvd14[32]; /* DWORD 18 */ - u8 rsvd15[32]; /* DWORD 19 */ - u8 rsvd16[32]; /* DWORD 20 */ - u8 rsvd17[32]; /* DWORD 21 */ - u8 rsvd18[32]; /* DWORD 22 */ - u8 rsvd19[32]; /* DWORD 23 */ - u8 rsvd20[32]; /* DWORD 24 */ - u8 rsvd21[32]; /* DWORD 25 */ - u8 rsvd22[32]; /* DWORD 26 */ - u8 rsvd23[32]; /* DWORD 27 */ - u8 rsvd24[32]; /* DWORD 28 */ - u8 rsvd25[32]; /* DWORD 29 */ - u8 rsvd26[32]; /* DWORD 30 */ - u8 rsvd27[32]; /* DWORD 31 */ - u8 rsvd28[32]; /* DWORD 32 */ - u8 rsvd29[32]; /* DWORD 33 */ - u8 rsvd30[192]; /* DWORD 34 */ - u8 rsvd31[192]; /* DWORD 40 */ - u8 rsvd32[160]; /* DWORD 46 */ - u8 rsvd33[160]; /* DWORD 51 */ - u8 rsvd34[160]; /* DWORD 56 */ - u8 rsvd35[96]; /* DWORD 61 */ - u8 rsvd36[192][32]; /* DWORD 64 */ -} __packed; -struct CEV_CSRMAP_AMAP { - u32 dw[256]; -}; - -#endif /* __cev_amap_h__ */ diff --git a/drivers/staging/benet/cq.c b/drivers/staging/benet/cq.c deleted file mode 100644 index 65045864543..00000000000 --- a/drivers/staging/benet/cq.c +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" - -/* - * Completion Queue Objects - */ -/* - *============================================================================ - * P U B L I C R O U T I N E S - *============================================================================ - */ - -/* - This routine creates a completion queue based on the client completion - queue configuration information. - - - FunctionObject - Handle to a function object - CqBaseVa - Base VA for a the CQ ring - NumEntries - CEV_CQ_CNT_* values - solEventEnable - 0 = All CQEs can generate Events if CQ is eventable - 1 = only CQEs with solicited bit set are eventable - eventable - Eventable CQ, generates interrupts. - nodelay - 1 = Force interrupt, relevent if CQ eventable. - Interrupt is asserted immediately after EQE - write is confirmed, regardless of EQ Timer - or watermark settings. - wme - Enable watermark based coalescing - wmThresh - High watermark(CQ fullness at which event - or interrupt should be asserted). These are the - CEV_WATERMARK encoded values. - EqObject - EQ Handle to assign to this CQ - ppCqObject - Internal CQ Handle returned. - - Returns BE_SUCCESS if successfull, otherwise a useful error code is - returned. - - IRQL < DISPATCH_LEVEL - -*/ -int be_cq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, bool solicited_eventable, - bool no_delay, u32 wm_thresh, - struct be_eq_object *eq_object, struct be_cq_object *cq_object) -{ - int status = BE_SUCCESS; - u32 num_entries_encoding; - u32 num_entries = length / sizeof(struct MCC_CQ_ENTRY_AMAP); - struct FWCMD_COMMON_CQ_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(cq_object); - ASSERT(length % sizeof(struct MCC_CQ_ENTRY_AMAP) == 0); - - switch (num_entries) { - case 256: - num_entries_encoding = CEV_CQ_CNT_256; - break; - case 512: - num_entries_encoding = CEV_CQ_CNT_512; - break; - case 1024: - num_entries_encoding = CEV_CQ_CNT_1024; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - /* - * All cq entries all the same size. Use iSCSI version - * as a test for the proper rd length. - */ - memset(cq_object, 0, sizeof(*cq_object)); - - atomic_set(&cq_object->ref_count, 0); - cq_object->parent_function = pfob; - cq_object->eq_object = eq_object; - cq_object->num_entries = num_entries; - /* save for MCC cq processing */ - cq_object->va = rd->va; - - /* map into UT. */ - length = num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_CQ_CREATE); - - fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va), - length); - - AMAP_SET_BITS_PTR(CQ_CONTEXT, valid, &fwcmd->params.request.context, 1); - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(CQ_CONTEXT, Func, &fwcmd->params.request.context, n); - - n = (eq_object != NULL); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Eventable, - &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Armed, &fwcmd->params.request.context, 1); - - n = eq_object ? eq_object->eq_id : 0; - AMAP_SET_BITS_PTR(CQ_CONTEXT, EQID, &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Count, - &fwcmd->params.request.context, num_entries_encoding); - - n = 0; /* Protection Domain is always 0 in Linux driver */ - AMAP_SET_BITS_PTR(CQ_CONTEXT, PD, &fwcmd->params.request.context, n); - AMAP_SET_BITS_PTR(CQ_CONTEXT, NoDelay, - &fwcmd->params.request.context, no_delay); - AMAP_SET_BITS_PTR(CQ_CONTEXT, SolEvent, - &fwcmd->params.request.context, solicited_eventable); - - n = (wm_thresh != 0xFFFFFFFF); - AMAP_SET_BITS_PTR(CQ_CONTEXT, WME, &fwcmd->params.request.context, n); - - n = (n ? wm_thresh : 0); - AMAP_SET_BITS_PTR(CQ_CONTEXT, Watermark, - &fwcmd->params.request.context, n); - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create CQ failed."); - goto Error; - } - /* Remember the CQ id. */ - cq_object->cq_id = fwcmd->params.response.cq_id; - - /* insert this cq into eq_object reference */ - if (eq_object) { - atomic_inc(&eq_object->ref_count); - list_add_tail(&cq_object->cqlist_for_eq, - &eq_object->cq_list_head); - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - - Deferences the given object. Once the object's reference count drops to - zero, the object is destroyed and all resources that are held by this object - are released. The on-chip context is also destroyed along with the queue - ID, and any mappings made into the UT. - - cq_object - CQ handle returned from cq_object_create. - - returns the current reference count on the object - - IRQL: IRQL < DISPATCH_LEVEL -*/ -int be_cq_destroy(struct be_cq_object *cq_object) -{ - int status = 0; - - /* Nothing should reference this CQ at this point. */ - ASSERT(atomic_read(&cq_object->ref_count) == 0); - - /* Send fwcmd to destroy the CQ. */ - status = be_function_ring_destroy(cq_object->parent_function, - cq_object->cq_id, FWCMD_RING_TYPE_CQ, - NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Remove reference if this is an eventable CQ. */ - if (cq_object->eq_object) { - atomic_dec(&cq_object->eq_object->ref_count); - list_del(&cq_object->cqlist_for_eq); - } - return BE_SUCCESS; -} - diff --git a/drivers/staging/benet/descriptors.h b/drivers/staging/benet/descriptors.h deleted file mode 100644 index 8da438c407d..00000000000 --- a/drivers/staging/benet/descriptors.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __descriptors_amap_h__ -#define __descriptors_amap_h__ - -/* - * --- IPC_NODE_ID_ENUM --- - * IPC processor id values - */ -#define TPOST_NODE_ID (0) /* TPOST ID */ -#define TPRE_NODE_ID (1) /* TPRE ID */ -#define TXULP0_NODE_ID (2) /* TXULP0 ID */ -#define TXULP1_NODE_ID (3) /* TXULP1 ID */ -#define TXULP2_NODE_ID (4) /* TXULP2 ID */ -#define RXULP0_NODE_ID (5) /* RXULP0 ID */ -#define RXULP1_NODE_ID (6) /* RXULP1 ID */ -#define RXULP2_NODE_ID (7) /* RXULP2 ID */ -#define MPU_NODE_ID (15) /* MPU ID */ - -/* - * --- MAC_ID_ENUM --- - * Meaning of the mac_id field in rxpp_eth_d - */ -#define PORT0_HOST_MAC0 (0) /* PD 0, Port 0, host networking, MAC 0. */ -#define PORT0_HOST_MAC1 (1) /* PD 0, Port 0, host networking, MAC 1. */ -#define PORT0_STORAGE_MAC0 (2) /* PD 0, Port 0, host storage, MAC 0. */ -#define PORT0_STORAGE_MAC1 (3) /* PD 0, Port 0, host storage, MAC 1. */ -#define PORT1_HOST_MAC0 (4) /* PD 0, Port 1 host networking, MAC 0. */ -#define PORT1_HOST_MAC1 (5) /* PD 0, Port 1 host networking, MAC 1. */ -#define PORT1_STORAGE_MAC0 (6) /* PD 0, Port 1 host storage, MAC 0. */ -#define PORT1_STORAGE_MAC1 (7) /* PD 0, Port 1 host storage, MAC 1. */ -#define FIRST_VM_MAC (8) /* PD 1 MAC. Protection domains have IDs */ - /* from 0x8-0x26, one per PD. */ -#define LAST_VM_MAC (38) /* PD 31 MAC. */ -#define MGMT_MAC (39) /* Management port MAC. */ -#define MARBLE_MAC0 (59) /* Used for flushing function 0 receive */ - /* - * queues before re-using a torn-down - * receive ring. the DA = - * 00-00-00-00-00-00, and the MSB of the - * SA = 00 - */ -#define MARBLE_MAC1 (60) /* Used for flushing function 1 receive */ - /* - * queues before re-using a torn-down - * receive ring. the DA = - * 00-00-00-00-00-00, and the MSB of the - * SA != 00 - */ -#define NULL_MAC (61) /* Promiscuous mode, indicates no match */ -#define MCAST_MAC (62) /* Multicast match. */ -#define BCAST_MATCH (63) /* Broadcast match. */ - -#endif /* __descriptors_amap_h__ */ diff --git a/drivers/staging/benet/doorbells.h b/drivers/staging/benet/doorbells.h deleted file mode 100644 index 550cc4d5d6f..00000000000 --- a/drivers/staging/benet/doorbells.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __doorbells_amap_h__ -#define __doorbells_amap_h__ - -/* The TX/RDMA send queue doorbell. */ -struct BE_SQ_DB_AMAP { - u8 cid[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 numPosted[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct SQ_DB_AMAP { - u32 dw[1]; -}; - -/* The receive queue doorbell. */ -struct BE_RQ_DB_AMAP { - u8 rq[10]; /* DWORD 0 */ - u8 rsvd0[13]; /* DWORD 0 */ - u8 Invalidate; /* DWORD 0 */ - u8 numPosted[8]; /* DWORD 0 */ -} __packed; -struct RQ_DB_AMAP { - u32 dw[1]; -}; - -/* - * The CQ/EQ doorbell. Software MUST set reserved fields in this - * descriptor to zero, otherwise (CEV) hardware will not execute the - * doorbell (flagging a bad_db_qid error instead). - */ -struct BE_CQ_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[4]; /* DWORD 0 */ - u8 rearm; /* DWORD 0 */ - u8 event; /* DWORD 0 */ - u8 num_popped[13]; /* DWORD 0 */ - u8 rsvd1[3]; /* DWORD 0 */ -} __packed; -struct CQ_DB_AMAP { - u32 dw[1]; -}; - -struct BE_TPM_RQ_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 numPosted[11]; /* DWORD 0 */ - u8 mss_cnt[5]; /* DWORD 0 */ -} __packed; -struct TPM_RQ_DB_AMAP { - u32 dw[1]; -}; - -/* - * Post WRB Queue Doorbell Register used by the host Storage stack - * to notify the controller of a posted Work Request Block - */ -struct BE_WRB_POST_DB_AMAP { - u8 wrb_cid[10]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 wrb_index[8]; /* DWORD 0 */ - u8 numberPosted[8]; /* DWORD 0 */ -} __packed; -struct WRB_POST_DB_AMAP { - u32 dw[1]; -}; - -/* - * Update Default PDU Queue Doorbell Register used to communicate - * to the controller that the driver has stopped processing the queue - * and where in the queue it stopped, this is - * a CQ Entry Type. Used by storage driver. - */ -struct BE_DEFAULT_PDU_DB_AMAP { - u8 qid[10]; /* DWORD 0 */ - u8 rsvd0[4]; /* DWORD 0 */ - u8 rearm; /* DWORD 0 */ - u8 event; /* DWORD 0 */ - u8 cqproc[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct DEFAULT_PDU_DB_AMAP { - u32 dw[1]; -}; - -/* Management Command and Controller default fragment ring */ -struct BE_MCC_DB_AMAP { - u8 rid[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 numPosted[14]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct MCC_DB_AMAP { - u32 dw[1]; -}; - -/* - * Used for bootstrapping the Host interface. This register is - * used for driver communication with the MPU when no MCC Rings exist. - * The software must write this register twice to post any MCC - * command. First, it writes the register with hi=1 and the upper bits of - * the physical address for the MCC_MAILBOX structure. Software must poll - * the ready bit until this is acknowledged. Then, sotware writes the - * register with hi=0 with the lower bits in the address. It must - * poll the ready bit until the MCC command is complete. Upon completion, - * the MCC_MAILBOX will contain a valid completion queue entry. - */ -struct BE_MPU_MAILBOX_DB_AMAP { - u8 ready; /* DWORD 0 */ - u8 hi; /* DWORD 0 */ - u8 address[30]; /* DWORD 0 */ -} __packed; -struct MPU_MAILBOX_DB_AMAP { - u32 dw[1]; -}; - -/* - * This is the protection domain doorbell register map. Note that - * while this map shows doorbells for all Blade Engine supported - * protocols, not all of these may be valid in a given function or - * protection domain. It is the responsibility of the application - * accessing the doorbells to know which are valid. Each doorbell - * occupies 32 bytes of space, but unless otherwise specified, - * only the first 4 bytes should be written. There are 32 instances - * of these doorbells for the host and 31 virtual machines respectively. - * The host and VMs will only map the doorbell pages belonging to its - * protection domain. It will not be able to touch the doorbells for - * another VM. The doorbells are the only registers directly accessible - * by a virtual machine. Similarly, there are 511 additional - * doorbells for RDMA protection domains. PD 0 for RDMA shares - * the same physical protection domain doorbell page as ETH/iSCSI. - * - */ -struct BE_PROTECTION_DOMAIN_DBMAP_AMAP { - u8 rsvd0[512]; /* DWORD 0 */ - struct BE_SQ_DB_AMAP rdma_sq_db; - u8 rsvd1[7][32]; /* DWORD 17 */ - struct BE_WRB_POST_DB_AMAP iscsi_wrb_post_db; - u8 rsvd2[7][32]; /* DWORD 25 */ - struct BE_SQ_DB_AMAP etx_sq_db; - u8 rsvd3[7][32]; /* DWORD 33 */ - struct BE_RQ_DB_AMAP rdma_rq_db; - u8 rsvd4[7][32]; /* DWORD 41 */ - struct BE_DEFAULT_PDU_DB_AMAP iscsi_default_pdu_db; - u8 rsvd5[7][32]; /* DWORD 49 */ - struct BE_TPM_RQ_DB_AMAP tpm_rq_db; - u8 rsvd6[7][32]; /* DWORD 57 */ - struct BE_RQ_DB_AMAP erx_rq_db; - u8 rsvd7[7][32]; /* DWORD 65 */ - struct BE_CQ_DB_AMAP cq_db; - u8 rsvd8[7][32]; /* DWORD 73 */ - struct BE_MCC_DB_AMAP mpu_mcc_db; - u8 rsvd9[7][32]; /* DWORD 81 */ - struct BE_MPU_MAILBOX_DB_AMAP mcc_bootstrap_db; - u8 rsvd10[935][32]; /* DWORD 89 */ -} __packed; -struct PROTECTION_DOMAIN_DBMAP_AMAP { - u32 dw[1024]; -}; - -#endif /* __doorbells_amap_h__ */ diff --git a/drivers/staging/benet/ep.h b/drivers/staging/benet/ep.h deleted file mode 100644 index 72fcf64a9ff..00000000000 --- a/drivers/staging/benet/ep.h +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __ep_amap_h__ -#define __ep_amap_h__ - -/* General Control and Status Register. */ -struct BE_EP_CONTROL_CSR_AMAP { - u8 m0_RxPbuf; /* DWORD 0 */ - u8 m1_RxPbuf; /* DWORD 0 */ - u8 m2_RxPbuf; /* DWORD 0 */ - u8 ff_en; /* DWORD 0 */ - u8 rsvd0[27]; /* DWORD 0 */ - u8 CPU_reset; /* DWORD 0 */ -} __packed; -struct EP_CONTROL_CSR_AMAP { - u32 dw[1]; -}; - -/* Semaphore Register. */ -struct BE_EP_SEMAPHORE_CSR_AMAP { - u8 value[32]; /* DWORD 0 */ -} __packed; -struct EP_SEMAPHORE_CSR_AMAP { - u32 dw[1]; -}; - -/* Embedded Processor Specific Registers. */ -struct BE_EP_CSRMAP_AMAP { - struct BE_EP_CONTROL_CSR_AMAP ep_control; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - u8 rsvd3[32]; /* DWORD 4 */ - u8 rsvd4[32]; /* DWORD 5 */ - u8 rsvd5[8][128]; /* DWORD 6 */ - u8 rsvd6[32]; /* DWORD 38 */ - u8 rsvd7[32]; /* DWORD 39 */ - u8 rsvd8[32]; /* DWORD 40 */ - u8 rsvd9[32]; /* DWORD 41 */ - u8 rsvd10[32]; /* DWORD 42 */ - struct BE_EP_SEMAPHORE_CSR_AMAP ep_semaphore; - u8 rsvd11[32]; /* DWORD 44 */ - u8 rsvd12[19][32]; /* DWORD 45 */ -} __packed; -struct EP_CSRMAP_AMAP { - u32 dw[64]; -}; - -#endif /* __ep_amap_h__ */ diff --git a/drivers/staging/benet/eq.c b/drivers/staging/benet/eq.c deleted file mode 100644 index db92ccd8fed..00000000000 --- a/drivers/staging/benet/eq.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" -/* - This routine creates an event queue based on the client completion - queue configuration information. - - FunctionObject - Handle to a function object - EqBaseVa - Base VA for a the EQ ring - SizeEncoding - The encoded size for the EQ entries. This value is - either CEV_EQ_SIZE_4 or CEV_EQ_SIZE_16 - NumEntries - CEV_CQ_CNT_* values. - Watermark - Enables watermark based coalescing. This parameter - must be of the type CEV_WMARK_* if watermarks - are enabled. If watermarks to to be disabled - this value should be-1. - TimerDelay - If a timer delay is enabled this value should be the - time of the delay in 8 microsecond units. If - delays are not used this parameter should be - set to -1. - ppEqObject - Internal EQ Handle returned. - - Returns BE_SUCCESS if successfull,, otherwise a useful error code - is returned. - - IRQL < DISPATCH_LEVEL -*/ -int -be_eq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 eqe_size, u32 num_entries, - u32 watermark, /* CEV_WMARK_* or -1 */ - u32 timer_delay, /* in 8us units, or -1 */ - struct be_eq_object *eq_object) -{ - int status = BE_SUCCESS; - u32 num_entries_encoding, eqe_size_encoding, length; - struct FWCMD_COMMON_EQ_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(eq_object); - - switch (num_entries) { - case 256: - num_entries_encoding = CEV_EQ_CNT_256; - break; - case 512: - num_entries_encoding = CEV_EQ_CNT_512; - break; - case 1024: - num_entries_encoding = CEV_EQ_CNT_1024; - break; - case 2048: - num_entries_encoding = CEV_EQ_CNT_2048; - break; - case 4096: - num_entries_encoding = CEV_EQ_CNT_4096; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - switch (eqe_size) { - case 4: - eqe_size_encoding = CEV_EQ_SIZE_4; - break; - case 16: - eqe_size_encoding = CEV_EQ_SIZE_16; - break; - default: - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - if ((eqe_size == 4 && num_entries < 1024) || - (eqe_size == 16 && num_entries == 4096)) { - TRACE(DL_ERR, "Bad EQ size. eqe_size:%d num_entries:%d", - eqe_size, num_entries); - ASSERT(0); - return BE_STATUS_INVALID_PARAMETER; - } - - memset(eq_object, 0, sizeof(*eq_object)); - - atomic_set(&eq_object->ref_count, 0); - eq_object->parent_function = pfob; - eq_object->eq_id = 0xFFFFFFFF; - - INIT_LIST_HEAD(&eq_object->cq_list_head); - - length = num_entries * eqe_size; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_EQ_CREATE); - - fwcmd->params.request.num_pages = PAGES_SPANNED(OFFSET_IN_PAGE(rd->va), - length); - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(EQ_CONTEXT, Func, &fwcmd->params.request.context, n); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, valid, &fwcmd->params.request.context, 1); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Size, - &fwcmd->params.request.context, eqe_size_encoding); - - n = 0; /* Protection Domain is always 0 in Linux driver */ - AMAP_SET_BITS_PTR(EQ_CONTEXT, PD, &fwcmd->params.request.context, n); - - /* Let the caller ARM the EQ with the doorbell. */ - AMAP_SET_BITS_PTR(EQ_CONTEXT, Armed, &fwcmd->params.request.context, 0); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Count, &fwcmd->params.request.context, - num_entries_encoding); - - n = pfob->pci_function_number * 32; - AMAP_SET_BITS_PTR(EQ_CONTEXT, EventVect, - &fwcmd->params.request.context, n); - if (watermark != -1) { - AMAP_SET_BITS_PTR(EQ_CONTEXT, WME, - &fwcmd->params.request.context, 1); - AMAP_SET_BITS_PTR(EQ_CONTEXT, Watermark, - &fwcmd->params.request.context, watermark); - ASSERT(watermark <= CEV_WMARK_240); - } else - AMAP_SET_BITS_PTR(EQ_CONTEXT, WME, - &fwcmd->params.request.context, 0); - if (timer_delay != -1) { - AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR, - &fwcmd->params.request.context, 1); - - ASSERT(timer_delay <= 250); /* max value according to EAS */ - timer_delay = min(timer_delay, (u32)250); - - AMAP_SET_BITS_PTR(EQ_CONTEXT, Delay, - &fwcmd->params.request.context, timer_delay); - } else { - AMAP_SET_BITS_PTR(EQ_CONTEXT, TMR, - &fwcmd->params.request.context, 0); - } - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create EQ failed."); - goto Error; - } - /* Get the EQ id. The MPU allocates the IDs. */ - eq_object->eq_id = fwcmd->params.response.eq_id; - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - Deferences the given object. Once the object's reference count drops to - zero, the object is destroyed and all resources that are held by this - object are released. The on-chip context is also destroyed along with - the queue ID, and any mappings made into the UT. - - eq_object - EQ handle returned from eq_object_create. - - Returns BE_SUCCESS if successfull, otherwise a useful error code - is returned. - - IRQL: IRQL < DISPATCH_LEVEL -*/ -int be_eq_destroy(struct be_eq_object *eq_object) -{ - int status = 0; - - ASSERT(atomic_read(&eq_object->ref_count) == 0); - /* no CQs should reference this EQ now */ - ASSERT(list_empty(&eq_object->cq_list_head)); - - /* Send fwcmd to destroy the EQ. */ - status = be_function_ring_destroy(eq_object->parent_function, - eq_object->eq_id, FWCMD_RING_TYPE_EQ, - NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - return BE_SUCCESS; -} -/* - *--------------------------------------------------------------------------- - * Function: be_eq_modify_delay - * Changes the EQ delay for a group of EQs. - * num_eq - The number of EQs in the eq_array to adjust. - * This also is the number of delay values in - * the eq_delay_array. - * eq_array - Array of struct be_eq_object pointers to adjust. - * eq_delay_array - Array of "num_eq" timer delays in units - * of microseconds. The be_eq_query_delay_range - * fwcmd returns the resolution and range of - * legal EQ delays. - * cb - - * cb_context - - * q_ctxt - Optional. Pointer to a previously allocated - * struct. If the MCC WRB ring is full, this - * structure is used to queue the operation. It - * will be posted to the MCC ring when space - * becomes available. All queued commands will - * be posted to the ring in the order they are - * received. It is always valid to pass a pointer to - * a generic be_generic_q_cntxt. However, - * the specific context structs - * are generally smaller than the generic struct. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *------------------------------------------------------------------------- - */ -int -be_eq_modify_delay(struct be_function_object *pfob, - u32 num_eq, struct be_eq_object **eq_array, - u32 *eq_delay_array, mcc_wrb_cqe_callback cb, - void *cb_context, struct be_eq_modify_delay_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_MODIFY_EQ_DELAY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *gen_ctxt = NULL; - u32 i; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - gen_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - gen_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MODIFY_EQ_DELAY); - - ASSERT(num_eq > 0); - ASSERT(num_eq <= ARRAY_SIZE(fwcmd->params.request.delay)); - fwcmd->params.request.num_eq = num_eq; - for (i = 0; i < num_eq; i++) { - fwcmd->params.request.delay[i].eq_id = eq_array[i]->eq_id; - fwcmd->params.request.delay[i].delay_in_microseconds = - eq_delay_array[i]; - } - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, gen_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - diff --git a/drivers/staging/benet/eth.c b/drivers/staging/benet/eth.c deleted file mode 100644 index f641b6260d0..00000000000 --- a/drivers/staging/benet/eth.c +++ /dev/null @@ -1,1273 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include "hwlib.h" -#include "bestatus.h" - -/* - *--------------------------------------------------------- - * Function: be_eth_sq_create_ex - * Creates an ethernet send ring - extended version with - * additional parameters. - * pfob - - * rd - ring address - * length_in_bytes - - * type - The type of ring to create. - * ulp - The requested ULP number for the ring. - * This should be zero based, i.e. 0,1,2. This must - * be valid NIC ULP based on the firmware config. - * All doorbells for this ring must be sent to - * this ULP. The first network ring allocated for - * each ULP are higher performance than subsequent rings. - * cq_object - cq object for completions - * ex_parameters - Additional parameters (that may increase in - * future revisions). These parameters are only used - * for certain ring types -- see - * struct be_eth_sq_parameters for details. - * eth_sq - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_sq_create_ex(struct be_function_object *pfob, struct ring_desc *rd, - u32 length, u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_eth_sq_parameters *ex_parameters, - struct be_ethsq_object *eth_sq) -{ - struct FWCMD_COMMON_ETH_TX_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - u32 n; - unsigned long irql; - - ASSERT(rd); - ASSERT(eth_sq); - ASSERT(ex_parameters); - - spin_lock_irqsave(&pfob->post_lock, irql); - - memset(eth_sq, 0, sizeof(*eth_sq)); - - eth_sq->parent_function = pfob; - eth_sq->bid = 0xFFFFFFFF; - eth_sq->cq_object = cq_object; - - /* Translate hwlib interface to arm interface. */ - switch (type) { - case BE_ETH_TX_RING_TYPE_FORWARDING: - type = ETH_TX_RING_TYPE_FORWARDING; - break; - case BE_ETH_TX_RING_TYPE_STANDARD: - type = ETH_TX_RING_TYPE_STANDARD; - break; - case BE_ETH_TX_RING_TYPE_BOUND: - ASSERT(ex_parameters->port < 2); - type = ETH_TX_RING_TYPE_BOUND; - break; - default: - TRACE(DL_ERR, "Invalid eth tx ring type:%d", type); - return BE_NOT_OK; - break; - } - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* NIC must be supported by the current config. */ - ASSERT(pfob->fw_config.nic_ulp_mask); - - /* - * The ulp parameter must select a valid NIC ULP - * for the current config. - */ - ASSERT((1 << ulp) & pfob->fw_config.nic_ulp_mask); - - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_TX_CREATE); - fwcmd->header.request.port_number = ex_parameters->port; - - AMAP_SET_BITS_PTR(ETX_CONTEXT, pd_id, - &fwcmd->params.request.context, 0); - - n = be_ring_length_to_encoding(length, sizeof(struct ETH_WRB_AMAP)); - AMAP_SET_BITS_PTR(ETX_CONTEXT, tx_ring_size, - &fwcmd->params.request.context, n); - - AMAP_SET_BITS_PTR(ETX_CONTEXT, cq_id_send, - &fwcmd->params.request.context, cq_object->cq_id); - - n = pfob->pci_function_number; - AMAP_SET_BITS_PTR(ETX_CONTEXT, func, &fwcmd->params.request.context, n); - - fwcmd->params.request.type = type; - fwcmd->params.request.ulp_num = (1 << ulp); - fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE); - ASSERT(PAGES_SPANNED(rd->va, rd->length) >= - fwcmd->params.request.num_pages); - - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create etx queue failed."); - goto Error; - } - /* save the butler ID */ - eth_sq->bid = fwcmd->params.response.cid; - - /* add a reference to the corresponding CQ */ - atomic_inc(&cq_object->ref_count); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine destroys an ethernet send queue - - EthSq - EthSq Handle returned from EthSqCreate - - This function always return BE_SUCCESS. - - This function frees memory allocated by EthSqCreate for the EthSq Object. - -*/ -int be_eth_sq_destroy(struct be_ethsq_object *eth_sq) -{ - int status = 0; - - /* Send fwcmd to destroy the queue. */ - status = be_function_ring_destroy(eth_sq->parent_function, eth_sq->bid, - FWCMD_RING_TYPE_ETH_TX, NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Derefence any associated CQs. */ - atomic_dec(ð_sq->cq_object->ref_count); - return status; -} -/* - This routine attempts to set the transmit flow control parameters. - - FunctionObject - Handle to a function object - - txfc_enable - transmit flow control enable - true for - enable, false for disable - - rxfc_enable - receive flow control enable - true for - enable, false for disable - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_set_flow_control(struct be_function_object *pfob, - bool txfc_enable, bool rxfc_enable) -{ - struct FWCMD_COMMON_SET_FLOW_CONTROL *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FLOW_CONTROL); - - fwcmd->params.request.rx_flow_control = rxfc_enable; - fwcmd->params.request.tx_flow_control = txfc_enable; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "set flow control fwcmd failed."); - goto error; - } - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine attempts to get the transmit flow control parameters. - - pfob - Handle to a function object - - txfc_enable - transmit flow control enable - true for - enable, false for disable - - rxfc_enable - receive flow control enable - true for enable, - false for disable - - Returns BE_SUCCESS if successfull, otherwise a useful int error code - is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_get_flow_control(struct be_function_object *pfob, - bool *txfc_enable, bool *rxfc_enable) -{ - struct FWCMD_COMMON_GET_FLOW_CONTROL *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FLOW_CONTROL); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "get flow control fwcmd failed."); - goto error; - } - - *txfc_enable = fwcmd->params.response.tx_flow_control; - *rxfc_enable = fwcmd->params.response.rx_flow_control; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_set_qos - * This function sets the ethernet transmit Quality of Service (QoS) - * characteristics of BladeEngine for the domain. All ethernet - * transmit rings of the domain will evenly share the bandwidth. - * The exeception to sharing is the host primary (super) ethernet - * transmit ring as well as the host ethernet forwarding ring - * for missed offload data. - * pfob - - * max_bps - the maximum bits per second in units of - * 10 Mbps (valid 0-100) - * max_pps - the maximum packets per second in units - * of 1 Kpps (0 indicates no limit) - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps) -{ - struct FWCMD_COMMON_SET_QOS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_QOS); - - /* Set fields in fwcmd */ - fwcmd->params.request.max_bits_per_second_NIC = max_bps; - fwcmd->params.request.max_packets_per_second_NIC = max_pps; - fwcmd->params.request.valid_flags = QOS_BITS_NIC | QOS_PKTS_NIC; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) - TRACE(DL_ERR, "network set qos fwcmd failed."); - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_get_qos - * This function retrieves the ethernet transmit Quality of Service (QoS) - * characteristics for the domain. - * max_bps - the maximum bits per second in units of - * 10 Mbps (valid 0-100) - * max_pps - the maximum packets per second in units of - * 1 Kpps (0 indicates no limit) - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps) -{ - struct FWCMD_COMMON_GET_QOS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_QOS); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "network get qos fwcmd failed."); - goto error; - } - - *max_bps = fwcmd->params.response.max_bits_per_second_NIC; - *max_pps = fwcmd->params.response.max_packets_per_second_NIC; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - *--------------------------------------------------------- - * Function: be_eth_set_frame_size - * This function sets the ethernet maximum frame size. The previous - * values are returned. - * pfob - - * tx_frame_size - maximum transmit frame size in bytes - * rx_frame_size - maximum receive frame size in bytes - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *--------------------------------------------------------- - */ -int -be_eth_set_frame_size(struct be_function_object *pfob, - u32 *tx_frame_size, u32 *rx_frame_size) -{ - struct FWCMD_COMMON_SET_FRAME_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_SET_FRAME_SIZE); - fwcmd->params.request.max_tx_frame_size = *tx_frame_size; - fwcmd->params.request.max_rx_frame_size = *rx_frame_size; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "network set frame size fwcmd failed."); - goto error; - } - - *tx_frame_size = fwcmd->params.response.chip_max_tx_frame_size; - *rx_frame_size = fwcmd->params.response.chip_max_rx_frame_size; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine creates a Ethernet receive ring. - - pfob - handle to a function object - rq_base_va - base VA for the default receive ring. this must be - exactly 8K in length and continguous physical memory. - cq_object - handle to a previously created CQ to be associated - with the RQ. - pp_eth_rq - pointer to an opqaue handle where an eth - receive object is returned. - Returns BE_SUCCESS if successfull, , otherwise a useful - int error code is returned. - - IRQL: < DISPATCH_LEVEL - this function allocates a struct be_ethrq_object *object. - there must be no more than 1 of these per function object, unless the - function object supports RSS (is networking and on the host). - the rq_base_va must point to a buffer of exactly 8K. - the erx::host_cqid (or host_stor_cqid) register and erx::ring_page registers - will be updated as appropriate on return -*/ -int -be_eth_rq_create(struct be_function_object *pfob, - struct ring_desc *rd, struct be_cq_object *cq_object, - struct be_cq_object *bcmc_cq_object, - struct be_ethrq_object *eth_rq) -{ - int status = 0; - struct MCC_WRB_AMAP *wrb = NULL; - struct FWCMD_COMMON_ETH_RX_CREATE *fwcmd = NULL; - unsigned long irql; - - /* MPU will set the */ - ASSERT(rd); - ASSERT(eth_rq); - - spin_lock_irqsave(&pfob->post_lock, irql); - - eth_rq->parent_function = pfob; - eth_rq->cq_object = cq_object; - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_ETH_RX_CREATE); - - fwcmd->params.request.num_pages = 2; /* required length */ - fwcmd->params.request.cq_id = cq_object->cq_id; - - if (bcmc_cq_object) - fwcmd->params.request.bcmc_cq_id = bcmc_cq_object->cq_id; - else - fwcmd->params.request.bcmc_cq_id = 0xFFFF; - - /* Create a page list for the FWCMD. */ - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "fwcmd to map eth rxq frags failed."); - goto Error; - } - /* Save the ring ID for cleanup. */ - eth_rq->rid = fwcmd->params.response.id; - - atomic_inc(&cq_object->ref_count); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine destroys an Ethernet receive queue - - eth_rq - ethernet receive queue handle returned from eth_rq_create - - Returns BE_SUCCESS on success and an appropriate int on failure. - - This function frees resourcs allocated by EthRqCreate. - The erx::host_cqid (or host_stor_cqid) register and erx::ring_page - registers will be updated as appropriate on return - IRQL: < DISPATCH_LEVEL -*/ - -static void be_eth_rq_destroy_internal_cb(void *context, int status, - struct MCC_WRB_AMAP *wrb) -{ - struct be_ethrq_object *eth_rq = (struct be_ethrq_object *) context; - - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Destroy eth rq failed in internal callback.\n"); - } else { - /* Dereference any CQs associated with this queue. */ - atomic_dec(ð_rq->cq_object->ref_count); - } - - return; -} - -int be_eth_rq_destroy(struct be_ethrq_object *eth_rq) -{ - int status = BE_SUCCESS; - - /* Send fwcmd to destroy the RQ. */ - status = be_function_ring_destroy(eth_rq->parent_function, - eth_rq->rid, FWCMD_RING_TYPE_ETH_RX, NULL, NULL, - be_eth_rq_destroy_internal_cb, eth_rq); - - return status; -} - -/* - *--------------------------------------------------------------------------- - * Function: be_eth_rq_destroy_options - * Destroys an ethernet receive ring with finer granularity options - * than the standard be_eth_rq_destroy() API function. - * eth_rq - - * flush - Set to 1 to flush the ring, set to 0 to bypass the flush - * cb - Callback function on completion - * cb_context - Callback context - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *---------------------------------------------------------------------------- - */ -int -be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush, - mcc_wrb_cqe_callback cb, void *cb_context) -{ - struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = BE_SUCCESS; - struct be_function_object *pfob = NULL; - unsigned long irql; - - pfob = eth_rq->parent_function; - - spin_lock_irqsave(&pfob->post_lock, irql); - - TRACE(DL_INFO, "Destroy eth_rq ring id:%d, flush:%d", eth_rq->rid, - flush); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in destroy eth_rq ring."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY); - - fwcmd->params.request.id = eth_rq->rid; - fwcmd->params.request.ring_type = FWCMD_RING_TYPE_ETH_RX; - fwcmd->params.request.bypass_flush = ((0 == flush) ? 1 : 0); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context, - be_eth_rq_destroy_internal_cb, eth_rq, fwcmd, NULL); - - if (status != BE_SUCCESS && status != BE_PENDING) { - TRACE(DL_ERR, "eth_rq ring destroy failed. id:%d, flush:%d", - eth_rq->rid, flush); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine queries the frag size for erx. - - pfob - handle to a function object - - frag_size_bytes - erx frag size in bytes that is/was set. - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - -*/ -int -be_eth_rq_get_frag_size(struct be_function_object *pfob, u32 *frag_size_bytes) -{ - struct FWCMD_ETH_GET_RX_FRAG_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - ASSERT(frag_size_bytes); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - return BE_STATUS_NO_MCC_WRB; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_GET_RX_FRAG_SIZE); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "get frag size fwcmd failed."); - goto error; - } - - *frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2; - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine attempts to set the frag size for erx. If the frag size is - already set, the attempt fails and the current frag size is returned. - - pfob - Handle to a function object - - frag_size - Erx frag size in bytes that is/was set. - - current_frag_size_bytes - Pointer to location where currrent frag - is to be rturned - - Returns BE_SUCCESS if successfull, otherwise a useful int error - code is returned. - - IRQL: < DISPATCH_LEVEL - - This function always fails in non-privileged machine context. -*/ -int -be_eth_rq_set_frag_size(struct be_function_object *pfob, - u32 frag_size, u32 *frag_size_bytes) -{ - struct FWCMD_ETH_SET_RX_FRAG_SIZE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - ASSERT(frag_size_bytes); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_SET_RX_FRAG_SIZE); - - ASSERT(frag_size >= 128 && frag_size <= 16 * 1024); - - /* This is the log2 of the fragsize. This is not the exact - * ERX encoding. */ - fwcmd->params.request.new_fragsize_log2 = __ilog2_u32(frag_size); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - - if (status != 0) { - TRACE(DL_ERR, "set frag size fwcmd failed."); - goto error; - } - - *frag_size_bytes = 1 << fwcmd->params.response.actual_fragsize_log2; -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - This routine gets or sets a mac address for a domain - given the port and mac. - - FunctionObject - Function object handle. - port1 - Set to TRUE if this function will set/get the Port 1 - address. Only the host may set this to TRUE. - mac1 - Set to TRUE if this function will set/get the - MAC 1 address. Only the host may set this to TRUE. - write - Set to TRUE if this function should write the mac address. - mac_address - Buffer of the mac address to read or write. - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ -int be_rxf_mac_address_read_write(struct be_function_object *pfob, - bool port1, /* VM must always set to false */ - bool mac1, /* VM must always set to false */ - bool mgmt, bool write, - bool permanent, u8 *mac_address, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context) /* optional */ -{ - int status = BE_SUCCESS; - union { - struct FWCMD_COMMON_NTWK_MAC_QUERY *query; - struct FWCMD_COMMON_NTWK_MAC_SET *set; - } fwcmd = {NULL}; - struct MCC_WRB_AMAP *wrb = NULL; - u32 type = 0; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - ASSERT(mac_address); - - ASSERT(port1 == false); - ASSERT(mac1 == false); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - - if (mgmt) { - type = MAC_ADDRESS_TYPE_MANAGEMENT; - } else { - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) - type = MAC_ADDRESS_TYPE_NETWORK; - else - type = MAC_ADDRESS_TYPE_STORAGE; - } - - if (write) { - /* Prepares an embedded fwcmd, including - * request/response sizes. - */ - fwcmd.set = BE_PREPARE_EMBEDDED_FWCMD(pfob, - wrb, COMMON_NTWK_MAC_SET); - - fwcmd.set->params.request.invalidate = 0; - fwcmd.set->params.request.mac1 = (mac1 ? 1 : 0); - fwcmd.set->params.request.port = (port1 ? 1 : 0); - fwcmd.set->params.request.type = type; - - /* Copy the mac address to set. */ - fwcmd.set->params.request.mac.SizeOfStructure = - sizeof(fwcmd.set->params.request.mac); - memcpy(fwcmd.set->params.request.mac.MACAddress, - mac_address, ETH_ALEN); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, - cb, cb_context, NULL, NULL, fwcmd.set, NULL); - - } else { - - /* - * Prepares an embedded fwcmd, including - * request/response sizes. - */ - fwcmd.query = BE_PREPARE_EMBEDDED_FWCMD(pfob, - wrb, COMMON_NTWK_MAC_QUERY); - - fwcmd.query->params.request.mac1 = (mac1 ? 1 : 0); - fwcmd.query->params.request.port = (port1 ? 1 : 0); - fwcmd.query->params.request.type = type; - fwcmd.query->params.request.permanent = permanent; - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_MAC_QUERY, - params.response.mac.MACAddress); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_MAC_QUERY, - params.response.mac.MACAddress); - rc.va = mac_address; - /* Post the f/w command (with a copy for the response) */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, - cb_context, NULL, NULL, fwcmd.query, &rc); - } - - if (status < 0) { - TRACE(DL_ERR, "mac set/query failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine writes data to context memory. - - pfob - Function object handle. - mac_table - Set to the 128-bit multicast address hash table. - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ - -int be_rxf_multicast_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u8 *mac_table, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context, - struct be_multicast_q_ctxt *q_ctxt) -{ - int status = BE_SUCCESS; - struct FWCMD_COMMON_NTWK_MULTICAST_SET *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - ASSERT(num <= ARRAY_SIZE(fwcmd->params.request.mac)); - - if (num > ARRAY_SIZE(fwcmd->params.request.mac)) { - TRACE(DL_ERR, "Too many multicast addresses. BE supports %d.", - (int) ARRAY_SIZE(fwcmd->params.request.mac)); - return BE_NOT_OK; - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_MULTICAST_SET); - - fwcmd->params.request.promiscuous = promiscuous; - if (!promiscuous) { - fwcmd->params.request.num_mac = num; - if (num > 0) { - ASSERT(mac_table); - memcpy(fwcmd->params.request.mac, - mac_table, ETH_ALEN * num); - } - } - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "multicast fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine adds or removes a vlan tag from the rxf table. - - FunctionObject - Function object handle. - VLanTag - VLan tag to add or remove. - Add - Set to TRUE if this will add a vlan tag - - Returns BE_SUCCESS if successfull, otherwise a useful int is returned. - - IRQL: < DISPATCH_LEVEL -*/ -int be_rxf_vlan_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u16 *vlan_tag_array, - mcc_wrb_cqe_callback cb, /* optional */ - void *cb_context, - struct be_vlan_q_ctxt *q_ctxt) /* optional */ -{ - int status = BE_SUCCESS; - struct FWCMD_COMMON_NTWK_VLAN_CONFIG *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - if (num > ARRAY_SIZE(fwcmd->params.request.vlan_tag)) { - TRACE(DL_ERR, "Too many VLAN tags."); - return BE_NOT_OK; - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_VLAN_CONFIG); - - fwcmd->params.request.promiscuous = promiscuous; - if (!promiscuous) { - fwcmd->params.request.num_vlan = num; - - if (num > 0) { - ASSERT(vlan_tag_array); - memcpy(fwcmd->params.request.vlan_tag, vlan_tag_array, - num * sizeof(vlan_tag_array[0])); - } - } - - /* Post the commadn */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "vlan fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -int be_rxf_link_status(struct be_function_object *pfob, - struct BE_LINK_STATUS *link_status, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_link_status_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - ASSERT(link_status); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, - COMMON_NTWK_LINK_STATUS_QUERY); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY, - params.response); - rc.va = link_status; - /* Post or queue the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, &rc); - - if (status < 0) { - TRACE(DL_ERR, "link status fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_rxf_query_eth_statistics(struct be_function_object *pfob, - struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd, - u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_nonembedded_q_ctxt *q_ctxt) -{ - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - ASSERT(va_for_fwcmd); - ASSERT(pa_for_fwcmd); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - - TRACE(DL_INFO, "Query eth stats. fwcmd va:%p pa:0x%08x_%08x", - va_for_fwcmd, upper_32_bits(pa_for_fwcmd), (u32)pa_for_fwcmd); - - /* Prepares an embedded fwcmd, including request/response sizes. */ - va_for_fwcmd = BE_PREPARE_NONEMBEDDED_FWCMD(pfob, wrb, - va_for_fwcmd, pa_for_fwcmd, ETH_GET_STATISTICS); - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, va_for_fwcmd, NULL); - if (status < 0) { - TRACE(DL_ERR, "eth stats fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_rxf_promiscuous(struct be_function_object *pfob, - bool enable_port0, bool enable_port1, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_promiscuous_q_ctxt *q_ctxt) -{ - struct FWCMD_ETH_PROMISCUOUS *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, ETH_PROMISCUOUS); - - fwcmd->params.request.port0_promiscuous = enable_port0; - fwcmd->params.request.port1_promiscuous = enable_port1; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, NULL); - - if (status < 0) { - TRACE(DL_ERR, "promiscuous fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - - -/* - *------------------------------------------------------------------------- - * Function: be_rxf_filter_config - * Configures BladeEngine ethernet receive filter settings. - * pfob - - * settings - Pointer to the requested filter settings. - * The response from BladeEngine will be placed back - * in this structure. - * cb - optional - * cb_context - optional - * q_ctxt - Optional. Pointer to a previously allocated struct. - * If the MCC WRB ring is full, this structure is - * used to queue the operation. It will be posted - * to the MCC ring when space becomes available. All - * queued commands will be posted to the ring in - * the order they are received. It is always valid - * to pass a pointer to a generic - * be_generic_q_ctxt. However, the specific - * context structs are generally smaller than - * the generic struct. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *--------------------------------------------------------------------------- - */ -int -be_rxf_filter_config(struct be_function_object *pfob, - struct NTWK_RX_FILTER_SETTINGS *settings, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_rxf_filter_q_ctxt *q_ctxt) -{ - struct FWCMD_COMMON_NTWK_RX_FILTER *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - struct be_generic_q_ctxt *generic_ctxt = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - ASSERT(settings); - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - - if (!wrb) { - if (q_ctxt && cb) { - wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - generic_ctxt = (struct be_generic_q_ctxt *) q_ctxt; - generic_ctxt->context.bytes = sizeof(*q_ctxt); - } else { - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_NTWK_RX_FILTER); - memcpy(&fwcmd->params.request, settings, sizeof(*settings)); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_NTWK_RX_FILTER, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_NTWK_RX_FILTER, - params.response); - rc.va = settings; - /* Post or queue the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, generic_ctxt, - cb, cb_context, NULL, NULL, fwcmd, &rc); - - if (status < 0) { - TRACE(DL_ERR, "RXF/ERX filter config fwcmd failed."); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} diff --git a/drivers/staging/benet/etx_context.h b/drivers/staging/benet/etx_context.h deleted file mode 100644 index 554fbe5d127..00000000000 --- a/drivers/staging/benet/etx_context.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __etx_context_amap_h__ -#define __etx_context_amap_h__ - -/* ETX ring context structure. */ -struct BE_ETX_CONTEXT_AMAP { - u8 tx_cidx[11]; /* DWORD 0 */ - u8 rsvd0[5]; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 tx_pidx[11]; /* DWORD 1 */ - u8 rsvd2; /* DWORD 1 */ - u8 tx_ring_size[4]; /* DWORD 1 */ - u8 pd_id[5]; /* DWORD 1 */ - u8 pd_id_not_valid; /* DWORD 1 */ - u8 cq_id_send[10]; /* DWORD 1 */ - u8 rsvd3[32]; /* DWORD 2 */ - u8 rsvd4[32]; /* DWORD 3 */ - u8 cur_bytes[32]; /* DWORD 4 */ - u8 max_bytes[32]; /* DWORD 5 */ - u8 time_stamp[32]; /* DWORD 6 */ - u8 rsvd5[11]; /* DWORD 7 */ - u8 func; /* DWORD 7 */ - u8 rsvd6[20]; /* DWORD 7 */ - u8 cur_txd_count[32]; /* DWORD 8 */ - u8 max_txd_count[32]; /* DWORD 9 */ - u8 rsvd7[32]; /* DWORD 10 */ - u8 rsvd8[32]; /* DWORD 11 */ - u8 rsvd9[32]; /* DWORD 12 */ - u8 rsvd10[32]; /* DWORD 13 */ - u8 rsvd11[32]; /* DWORD 14 */ - u8 rsvd12[32]; /* DWORD 15 */ -} __packed; -struct ETX_CONTEXT_AMAP { - u32 dw[16]; -}; - -#endif /* __etx_context_amap_h__ */ diff --git a/drivers/staging/benet/funcobj.c b/drivers/staging/benet/funcobj.c deleted file mode 100644 index 0f57eb58dae..00000000000 --- a/drivers/staging/benet/funcobj.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include "hwlib.h" -#include "bestatus.h" - - -int -be_function_internal_query_firmware_config(struct be_function_object *pfob, - struct BE_FIRMWARE_CONFIG *config) -{ - struct FWCMD_COMMON_FIRMWARE_CONFIG *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_FIRMWARE_CONFIG); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_FIRMWARE_CONFIG, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_FIRMWARE_CONFIG, - params.response); - rc.va = config; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, - NULL, NULL, NULL, fwcmd, &rc); -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This allocates and initializes a function object based on the information - provided by upper layer drivers. - - Returns BE_SUCCESS on success and an appropriate int on failure. - - A function object represents a single BladeEngine (logical) PCI function. - That is a function object either represents - the networking side of BladeEngine or the iSCSI side of BladeEngine. - - This routine will also detect and create an appropriate PD object for the - PCI function as needed. -*/ -int -be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va, - u8 __iomem *pci_va, u32 function_type, - struct ring_desc *mailbox, struct be_function_object *pfob) -{ - int status; - - ASSERT(pfob); /* not a magic assert */ - ASSERT(function_type <= 2); - - TRACE(DL_INFO, "Create function object. type:%s object:0x%p", - (function_type == BE_FUNCTION_TYPE_ISCSI ? "iSCSI" : - (function_type == BE_FUNCTION_TYPE_NETWORK ? "Network" : - "Arm")), pfob); - - memset(pfob, 0, sizeof(*pfob)); - - pfob->type = function_type; - pfob->csr_va = csr_va; - pfob->db_va = db_va; - pfob->pci_va = pci_va; - - spin_lock_init(&pfob->cq_lock); - spin_lock_init(&pfob->post_lock); - spin_lock_init(&pfob->mcc_context_lock); - - - pfob->pci_function_number = 1; - - - pfob->emulate = false; - TRACE(DL_NOTE, "Non-emulation mode"); - status = be_drive_POST(pfob); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "BladeEngine POST failed."); - goto error; - } - - /* Initialize the mailbox */ - status = be_mpu_init_mailbox(pfob, mailbox); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Failed to initialize mailbox."); - goto error; - } - /* - * Cache the firmware config for ASSERTs in hwclib and later - * driver queries. - */ - status = be_function_internal_query_firmware_config(pfob, - &pfob->fw_config); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "Failed to query firmware config."); - goto error; - } - -error: - if (status != BE_SUCCESS) { - /* No cleanup necessary */ - TRACE(DL_ERR, "Failed to create function."); - memset(pfob, 0, sizeof(*pfob)); - } - return status; -} - -/* - This routine drops the reference count on a given function object. Once - the reference count falls to zero, the function object is destroyed and all - resources held are freed. - - FunctionObject - The function object to drop the reference to. -*/ -int be_function_object_destroy(struct be_function_object *pfob) -{ - TRACE(DL_INFO, "Destroy pfob. Object:0x%p", - pfob); - - - ASSERT(pfob->mcc == NULL); - - return BE_SUCCESS; -} - -int be_function_cleanup(struct be_function_object *pfob) -{ - int status = 0; - u32 isr; - u32 host_intr; - struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP ctrl; - - - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) { - status = be_rxf_multicast_config(pfob, false, 0, - NULL, NULL, NULL, NULL); - ASSERT(status == BE_SUCCESS); - } - /* VLAN */ - status = be_rxf_vlan_config(pfob, false, 0, NULL, NULL, NULL, NULL); - ASSERT(status == BE_SUCCESS); - /* - * MCC Queue -- Switches to mailbox mode. May want to destroy - * all but the MCC CQ before this call if polling CQ is much better - * performance than polling mailbox register. - */ - if (pfob->mcc) - status = be_mcc_ring_destroy(pfob->mcc); - /* - * If interrupts are disabled, clear any CEV interrupt assertions that - * fired after we stopped processing EQs. - */ - ctrl.dw[0] = PCICFG1_READ(pfob, host_timer_int_ctrl); - host_intr = AMAP_GET_BITS_PTR(PCICFG_HOST_TIMER_INT_CTRL_CSR, - hostintr, ctrl.dw); - if (!host_intr) - if (pfob->type == BE_FUNCTION_TYPE_NETWORK) - isr = CSR_READ(pfob, cev.isr1); - else - isr = CSR_READ(pfob, cev.isr0); - else - /* This should never happen... */ - TRACE(DL_ERR, "function_cleanup called with interrupt enabled"); - /* Function object destroy */ - status = be_function_object_destroy(pfob); - ASSERT(status == BE_SUCCESS); - - return status; -} - - -void * -be_function_prepare_embedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, u32 payld_len, u32 request_length, - u32 response_length, u32 opcode, u32 subsystem) -{ - struct FWCMD_REQUEST_HEADER *header = NULL; - u32 n; - - ASSERT(wrb); - - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 1); - AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, min(payld_len, n)); - header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n); - - header->timeout = 0; - header->domain = 0; - header->request_length = max(request_length, response_length); - header->opcode = opcode; - header->subsystem = subsystem; - - return header; -} - -void * -be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - void *fwcmd_va, u64 fwcmd_pa, - u32 payld_len, - u32 request_length, - u32 response_length, - u32 opcode, u32 subsystem) -{ - struct FWCMD_REQUEST_HEADER *header = NULL; - u32 n; - struct MCC_WRB_PAYLOAD_AMAP *plp; - - ASSERT(wrb); - ASSERT(fwcmd_va); - - header = (struct FWCMD_REQUEST_HEADER *) fwcmd_va; - - AMAP_SET_BITS_PTR(MCC_WRB, embedded, wrb, 0); - AMAP_SET_BITS_PTR(MCC_WRB, payload_length, wrb, payld_len); - - /* - * Assume one fragment. The caller may override the SGL by - * rewriting the 0th length and adding more entries. They - * will also need to update the sge_count. - */ - AMAP_SET_BITS_PTR(MCC_WRB, sge_count, wrb, 1); - - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - plp = (struct MCC_WRB_PAYLOAD_AMAP *)((u8 *)wrb + n); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].length, plp, payld_len); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_lo, plp, (u32)fwcmd_pa); - AMAP_SET_BITS_PTR(MCC_WRB_PAYLOAD, sgl[0].pa_hi, plp, - upper_32_bits(fwcmd_pa)); - - header->timeout = 0; - header->domain = 0; - header->request_length = max(request_length, response_length); - header->opcode = opcode; - header->subsystem = subsystem; - - return header; -} - -struct MCC_WRB_AMAP * -be_function_peek_mcc_wrb(struct be_function_object *pfob) -{ - struct MCC_WRB_AMAP *wrb = NULL; - u32 offset; - - if (pfob->mcc) - wrb = _be_mpu_peek_ring_wrb(pfob->mcc, false); - else { - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8; - wrb = (struct MCC_WRB_AMAP *) ((u8 *) pfob->mailbox.va + - offset); - } - - if (wrb) - memset(wrb, 0, sizeof(struct MCC_WRB_AMAP)); - - return wrb; -} - -#if defined(BE_DEBUG) -void be_function_debug_print_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, void *optional_fwcmd_va, - struct be_mcc_wrb_context *wrb_context) -{ - - struct FWCMD_REQUEST_HEADER *header = NULL; - u8 embedded; - u32 n; - - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, wrb); - - if (embedded) { - n = offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - header = (struct FWCMD_REQUEST_HEADER *)((u8 *)wrb + n); - } else { - header = (struct FWCMD_REQUEST_HEADER *) optional_fwcmd_va; - } - - /* Save the completed count before posting for a debug assert. */ - - if (header) { - wrb_context->opcode = header->opcode; - wrb_context->subsystem = header->subsystem; - - } else { - wrb_context->opcode = 0; - wrb_context->subsystem = 0; - } -} -#else -#define be_function_debug_print_wrb(a_, b_, c_, d_) -#endif - -int -be_function_post_mcc_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - struct be_generic_q_ctxt *q_ctxt, - mcc_wrb_cqe_callback cb, void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context, void *optional_fwcmd_va, - struct be_mcc_wrb_response_copy *rc) -{ - int status; - struct be_mcc_wrb_context *wrb_context = NULL; - u64 *p; - - if (q_ctxt) { - /* Initialize context. */ - q_ctxt->context.internal_cb = internal_cb; - q_ctxt->context.internal_cb_context = internal_cb_context; - q_ctxt->context.cb = cb; - q_ctxt->context.cb_context = cb_context; - if (rc) { - q_ctxt->context.copy.length = rc->length; - q_ctxt->context.copy.fwcmd_offset = rc->fwcmd_offset; - q_ctxt->context.copy.va = rc->va; - } else - q_ctxt->context.copy.length = 0; - - q_ctxt->context.optional_fwcmd_va = optional_fwcmd_va; - - /* Queue this request */ - status = be_function_queue_mcc_wrb(pfob, q_ctxt); - - goto Error; - } - /* - * Allocate a WRB context struct to hold the callback pointers, - * status, etc. This is required if commands complete out of order. - */ - wrb_context = _be_mcc_allocate_wrb_context(pfob); - if (!wrb_context) { - TRACE(DL_WARN, "Failed to allocate MCC WRB context."); - status = BE_STATUS_SYSTEM_RESOURCES; - goto Error; - } - /* Initialize context. */ - memset(wrb_context, 0, sizeof(*wrb_context)); - wrb_context->internal_cb = internal_cb; - wrb_context->internal_cb_context = internal_cb_context; - wrb_context->cb = cb; - wrb_context->cb_context = cb_context; - if (rc) { - wrb_context->copy.length = rc->length; - wrb_context->copy.fwcmd_offset = rc->fwcmd_offset; - wrb_context->copy.va = rc->va; - } else - wrb_context->copy.length = 0; - wrb_context->wrb = wrb; - - /* - * Copy the context pointer into the WRB opaque tag field. - * Verify assumption of 64-bit tag with a compile time assert. - */ - p = (u64 *) ((u8 *)wrb + offsetof(struct BE_MCC_WRB_AMAP, tag)/8); - *p = (u64)(size_t)wrb_context; - - /* Print info about this FWCMD for debug builds. */ - be_function_debug_print_wrb(pfob, wrb, optional_fwcmd_va, wrb_context); - - /* - * issue the WRB to the MPU as appropriate - */ - if (pfob->mcc) { - /* - * we're in WRB mode, pass to the mcc layer - */ - status = _be_mpu_post_wrb_ring(pfob->mcc, wrb, wrb_context); - } else { - /* - * we're in mailbox mode - */ - status = _be_mpu_post_wrb_mailbox(pfob, wrb, wrb_context); - - /* mailbox mode always completes synchronously */ - ASSERT(status != BE_STATUS_PENDING); - } - -Error: - - return status; -} - -int -be_function_ring_destroy(struct be_function_object *pfob, - u32 id, u32 ring_type, mcc_wrb_cqe_callback cb, - void *cb_context, mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context) -{ - - struct FWCMD_COMMON_RING_DESTROY *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - int status = 0; - unsigned long irql; - - spin_lock_irqsave(&pfob->post_lock, irql); - - TRACE(DL_INFO, "Destroy ring id:%d type:%d", id, ring_type); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in destroy ring."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_RING_DESTROY); - - fwcmd->params.request.id = id; - fwcmd->params.request.ring_type = ring_type; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, cb_context, - internal_cb, internal_cb_context, fwcmd, NULL); - if (status != BE_SUCCESS && status != BE_PENDING) { - TRACE(DL_ERR, "Ring destroy fwcmd failed. id:%d ring_type:%d", - id, ring_type); - goto Error; - } - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -void -be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list, u32 max_num) -{ - u32 num_pages = PAGES_SPANNED(rd->va, rd->length); - u32 i = 0; - u64 pa = rd->pa; - __le64 lepa; - - ASSERT(pa_list); - ASSERT(pa); - - for (i = 0; i < min(num_pages, max_num); i++) { - lepa = cpu_to_le64(pa); - pa_list[i].lo = (u32)lepa; - pa_list[i].hi = upper_32_bits(lepa); - pa += PAGE_SIZE; - } -} - - - -/*----------------------------------------------------------------------------- - * Function: be_function_get_fw_version - * Retrieves the firmware version on the adpater. If the callback is - * NULL this call executes synchronously. If the callback is not NULL, - * the returned status will be BE_PENDING if the command was issued - * successfully. - * pfob - - * fwv - Pointer to response buffer if callback is NULL. - * cb - Callback function invoked when the FWCMD completes. - * cb_context - Passed to the callback function. - * return pend_status - BE_SUCCESS (0) on success. - * BE_PENDING (postive value) if the FWCMD - * completion is pending. Negative error code on failure. - *--------------------------------------------------------------------------- - */ -int -be_function_get_fw_version(struct be_function_object *pfob, - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fwv, - mcc_wrb_cqe_callback cb, void *cb_context) -{ - int status = BE_SUCCESS; - struct MCC_WRB_AMAP *wrb = NULL; - struct FWCMD_COMMON_GET_FW_VERSION *fwcmd = NULL; - unsigned long irql; - struct be_mcc_wrb_response_copy rc; - - spin_lock_irqsave(&pfob->post_lock, irql); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - TRACE(DL_ERR, "MCC wrb peek failed."); - status = BE_STATUS_NO_MCC_WRB; - goto Error; - } - - if (!cb && !fwv) { - TRACE(DL_ERR, "callback and response buffer NULL!"); - status = BE_NOT_OK; - goto Error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_GET_FW_VERSION); - - rc.length = FIELD_SIZEOF(struct FWCMD_COMMON_GET_FW_VERSION, - params.response); - rc.fwcmd_offset = offsetof(struct FWCMD_COMMON_GET_FW_VERSION, - params.response); - rc.va = fwv; - - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, cb, - cb_context, NULL, NULL, fwcmd, &rc); - -Error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -int -be_function_queue_mcc_wrb(struct be_function_object *pfob, - struct be_generic_q_ctxt *q_ctxt) -{ - int status; - - ASSERT(q_ctxt); - - /* - * issue the WRB to the MPU as appropriate - */ - if (pfob->mcc) { - - /* We're in ring mode. Queue this item. */ - pfob->mcc->backlog_length++; - list_add_tail(&q_ctxt->context.list, &pfob->mcc->backlog); - status = BE_PENDING; - } else { - status = BE_NOT_OK; - } - return status; -} - diff --git a/drivers/staging/benet/fwcmd_common.h b/drivers/staging/benet/fwcmd_common.h deleted file mode 100644 index 406e0d6fa98..00000000000 --- a/drivers/staging/benet/fwcmd_common.h +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_common_amap_h__ -#define __fwcmd_common_amap_h__ -#include "host_struct.h" - -/* --- PHY_LINK_DUPLEX_ENUM --- */ -#define PHY_LINK_DUPLEX_NONE (0) -#define PHY_LINK_DUPLEX_HALF (1) -#define PHY_LINK_DUPLEX_FULL (2) - -/* --- PHY_LINK_SPEED_ENUM --- */ -#define PHY_LINK_SPEED_ZERO (0) /* No link. */ -#define PHY_LINK_SPEED_10MBPS (1) /* 10 Mbps */ -#define PHY_LINK_SPEED_100MBPS (2) /* 100 Mbps */ -#define PHY_LINK_SPEED_1GBPS (3) /* 1 Gbps */ -#define PHY_LINK_SPEED_10GBPS (4) /* 10 Gbps */ - -/* --- PHY_LINK_FAULT_ENUM --- */ -#define PHY_LINK_FAULT_NONE (0) /* No fault status - available or detected */ -#define PHY_LINK_FAULT_LOCAL (1) /* Local fault detected */ -#define PHY_LINK_FAULT_REMOTE (2) /* Remote fault detected */ - -/* --- BE_ULP_MASK --- */ -#define BE_ULP0_MASK (1) -#define BE_ULP1_MASK (2) -#define BE_ULP2_MASK (4) - -/* --- NTWK_ACTIVE_PORT --- */ -#define NTWK_PORT_A (0) /* Port A is currently active */ -#define NTWK_PORT_B (1) /* Port B is currently active */ -#define NTWK_NO_ACTIVE_PORT (15) /* Both ports have lost link */ - -/* --- NTWK_LINK_TYPE --- */ -#define NTWK_LINK_TYPE_PHYSICAL (0) /* link up/down event - applies to BladeEngine's - Physical Ports - */ -#define NTWK_LINK_TYPE_VIRTUAL (1) /* Virtual link up/down event - reported by BladeExchange. - This applies only when the - VLD feature is enabled - */ - -/* - * --- FWCMD_MAC_TYPE_ENUM --- - * This enum defines the types of MAC addresses in the RXF MAC Address Table. - */ -#define MAC_ADDRESS_TYPE_STORAGE (0) /* Storage MAC Address */ -#define MAC_ADDRESS_TYPE_NETWORK (1) /* Network MAC Address */ -#define MAC_ADDRESS_TYPE_PD (2) /* Protection Domain MAC Addr */ -#define MAC_ADDRESS_TYPE_MANAGEMENT (3) /* Managment MAC Address */ - - -/* --- FWCMD_RING_TYPE_ENUM --- */ -#define FWCMD_RING_TYPE_ETH_RX (1) /* Ring created with */ - /* FWCMD_COMMON_ETH_RX_CREATE. */ -#define FWCMD_RING_TYPE_ETH_TX (2) /* Ring created with */ - /* FWCMD_COMMON_ETH_TX_CREATE. */ -#define FWCMD_RING_TYPE_ISCSI_WRBQ (3) /* Ring created with */ - /* FWCMD_COMMON_ISCSI_WRBQ_CREATE. */ -#define FWCMD_RING_TYPE_ISCSI_DEFQ (4) /* Ring created with */ - /* FWCMD_COMMON_ISCSI_DEFQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_WRBQ (5) /* Ring created with */ - /* FWCMD_COMMON_TPM_WRBQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_DEFQ (6) /* Ring created with */ - /* FWCMD_COMMONTPM_TDEFQ_CREATE. */ -#define FWCMD_RING_TYPE_TPM_RQ (7) /* Ring created with */ - /* FWCMD_COMMON_TPM_RQ_CREATE. */ -#define FWCMD_RING_TYPE_MCC (8) /* Ring created with */ - /* FWCMD_COMMON_MCC_CREATE. */ -#define FWCMD_RING_TYPE_CQ (9) /* Ring created with */ - /* FWCMD_COMMON_CQ_CREATE. */ -#define FWCMD_RING_TYPE_EQ (10) /* Ring created with */ - /* FWCMD_COMMON_EQ_CREATE. */ -#define FWCMD_RING_TYPE_QP (11) /* Ring created with */ - /* FWCMD_RDMA_QP_CREATE. */ - - -/* --- ETH_TX_RING_TYPE_ENUM --- */ -#define ETH_TX_RING_TYPE_FORWARDING (1) /* Ethernet ring for - forwarding packets */ -#define ETH_TX_RING_TYPE_STANDARD (2) /* Ethernet ring for sending - network packets. */ -#define ETH_TX_RING_TYPE_BOUND (3) /* Ethernet ring bound to the - port specified in the command - header.port_number field. - Rings of this type are - NOT subject to the - failover logic implemented - in the BladeEngine. - */ - -/* --- FWCMD_COMMON_QOS_TYPE_ENUM --- */ -#define QOS_BITS_NIC (1) /* max_bits_per_second_NIC */ - /* field is valid. */ -#define QOS_PKTS_NIC (2) /* max_packets_per_second_NIC */ - /* field is valid. */ -#define QOS_IOPS_ISCSI (4) /* max_ios_per_second_iSCSI */ - /*field is valid. */ -#define QOS_VLAN_TAG (8) /* domain_VLAN_tag field - is valid. */ -#define QOS_FABRIC_ID (16) /* fabric_domain_ID field - is valid. */ -#define QOS_OEM_PARAMS (32) /* qos_params_oem field - is valid. */ -#define QOS_TPUT_ISCSI (64) /* max_bytes_per_second_iSCSI - field is valid. */ - - -/* - * --- FAILOVER_CONFIG_ENUM --- - * Failover configuration setting used in FWCMD_COMMON_FORCE_FAILOVER - */ -#define FAILOVER_CONFIG_NO_CHANGE (0) /* No change to automatic */ - /* port failover setting. */ -#define FAILOVER_CONFIG_ON (1) /* Automatic port failover - on link down is enabled. */ -#define FAILOVER_CONFIG_OFF (2) /* Automatic port failover - on link down is disabled. */ - -/* - * --- FAILOVER_PORT_ENUM --- - * Failover port setting used in FWCMD_COMMON_FORCE_FAILOVER - */ -#define FAILOVER_PORT_A (0) /* Selects port A. */ -#define FAILOVER_PORT_B (1) /* Selects port B. */ -#define FAILOVER_PORT_NONE (15) /* No port change requested. */ - - -/* - * --- MGMT_FLASHROM_OPCODE --- - * Flash ROM operation code - */ -#define MGMT_FLASHROM_OPCODE_FLASH (1) /* Commit downloaded data - to Flash ROM */ -#define MGMT_FLASHROM_OPCODE_SAVE (2) /* Save downloaded data to - ARM's DDR - do not flash */ -#define MGMT_FLASHROM_OPCODE_CLEAR (3) /* Erase specified component - from FlashROM */ -#define MGMT_FLASHROM_OPCODE_REPORT (4) /* Read specified component - from Flash ROM */ -#define MGMT_FLASHROM_OPCODE_IMAGE_INFO (5) /* Returns size of a - component */ - -/* - * --- MGMT_FLASHROM_OPTYPE --- - * Flash ROM operation type - */ -#define MGMT_FLASHROM_OPTYPE_CODE_FIRMWARE (0) /* Includes ARM firmware, - IPSec (optional) and EP - firmware */ -#define MGMT_FLASHROM_OPTYPE_CODE_REDBOOT (1) -#define MGMT_FLASHROM_OPTYPE_CODE_BIOS (2) -#define MGMT_FLASHROM_OPTYPE_CODE_PXE_BIOS (3) -#define MGMT_FLASHROM_OPTYPE_CODE_CTRLS (4) -#define MGMT_FLASHROM_OPTYPE_CFG_IPSEC (5) -#define MGMT_FLASHROM_OPTYPE_CFG_INI (6) -#define MGMT_FLASHROM_OPTYPE_ROM_OFFSET_SPECIFIED (7) - -/* - * --- FLASHROM_TYPE --- - * Flash ROM manufacturers supported in the f/w - */ -#define INTEL (0) -#define SPANSION (1) -#define MICRON (2) - -/* --- DDR_CAS_TYPE --- */ -#define CAS_3 (0) -#define CAS_4 (1) -#define CAS_5 (2) - -/* --- DDR_SIZE_TYPE --- */ -#define SIZE_256MB (0) -#define SIZE_512MB (1) - -/* --- DDR_MODE_TYPE --- */ -#define DDR_NO_ECC (0) -#define DDR_ECC (1) - -/* --- INTERFACE_10GB_TYPE --- */ -#define CX4_TYPE (0) -#define XFP_TYPE (1) - -/* --- BE_CHIP_MAX_MTU --- */ -#define CHIP_MAX_MTU (9000) - -/* --- XAUI_STATE_ENUM --- */ -#define XAUI_STATE_ENABLE (0) /* This MUST be the default - value for all requests - which set/change - equalization parameter. */ -#define XAUI_STATE_DISABLE (255) /* The XAUI for both ports - may be disabled for EMI - tests. There is no - provision for turning off - individual ports. - */ -/* --- BE_ASIC_REVISION --- */ -#define BE_ASIC_REV_A0 (1) -#define BE_ASIC_REV_A1 (2) - -#endif /* __fwcmd_common_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_common_bmap.h b/drivers/staging/benet/fwcmd_common_bmap.h deleted file mode 100644 index a007cf27650..00000000000 --- a/drivers/staging/benet/fwcmd_common_bmap.h +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_common_bmap_h__ -#define __fwcmd_common_bmap_h__ -#include "fwcmd_types_bmap.h" -#include "fwcmd_hdr_bmap.h" - -#if defined(__BIG_ENDIAN) - /* Physical Address. */ -struct PHYS_ADDR { - union { - struct { - u32 lo; /* DWORD 0 */ - u32 hi; /* DWORD 1 */ - } __packed; /* unnamed struct */ - u32 dw[2]; /* dword union */ - }; /* unnamed union */ -} __packed ; - - -#else - /* Physical Address. */ -struct PHYS_ADDR { - union { - struct { - u32 lo; /* DWORD 0 */ - u32 hi; /* DWORD 1 */ - } __packed; /* unnamed struct */ - u32 dw[2]; /* dword union */ - }; /* unnamed union */ -} __packed ; - -struct BE_LINK_STATUS { - u8 mac0_duplex; - u8 mac0_speed; - u8 mac1_duplex; - u8 mac1_speed; - u8 mgmt_mac_duplex; - u8 mgmt_mac_speed; - u8 active_port; - u8 rsvd0; - u8 mac0_fault; - u8 mac1_fault; - u16 rsvd1; -} __packed; -#endif - -struct FWCMD_COMMON_ANON_170_REQUEST { - u32 rsvd0; -} __packed; - -union LINK_STATUS_QUERY_PARAMS { - struct BE_LINK_STATUS response; - struct FWCMD_COMMON_ANON_170_REQUEST request; -} __packed; - -/* - * Queries the the link status for all ports. The valid values below - * DO NOT indicate that a particular duplex or speed is supported by - * BladeEngine. These enumerations simply list all possible duplexes - * and speeds for any port. Consult BladeEngine product documentation - * for the supported parameters. - */ -struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY { - union FWCMD_HEADER header; - union LINK_STATUS_QUERY_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_171_REQUEST { - u8 type; - u8 port; - u8 mac1; - u8 permanent; -} __packed; - -struct FWCMD_COMMON_ANON_172_RESPONSE { - struct MAC_ADDRESS_FORMAT mac; -} __packed; - -union NTWK_MAC_QUERY_PARAMS { - struct FWCMD_COMMON_ANON_171_REQUEST request; - struct FWCMD_COMMON_ANON_172_RESPONSE response; -} __packed; - -/* Queries one MAC address. */ -struct FWCMD_COMMON_NTWK_MAC_QUERY { - union FWCMD_HEADER header; - union NTWK_MAC_QUERY_PARAMS params; -} __packed; - -struct MAC_SET_PARAMS_IN { - u8 type; - u8 port; - u8 mac1; - u8 invalidate; - struct MAC_ADDRESS_FORMAT mac; -} __packed; - -struct MAC_SET_PARAMS_OUT { - u32 rsvd0; -} __packed; - -union MAC_SET_PARAMS { - struct MAC_SET_PARAMS_IN request; - struct MAC_SET_PARAMS_OUT response; -} __packed; - -/* Sets a MAC address. */ -struct FWCMD_COMMON_NTWK_MAC_SET { - union FWCMD_HEADER header; - union MAC_SET_PARAMS params; -} __packed; - -/* MAC address list. */ -struct NTWK_MULTICAST_MAC_LIST { - u8 byte[6]; -} __packed; - -struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD { - u16 num_mac; - u8 promiscuous; - u8 rsvd0; - struct NTWK_MULTICAST_MAC_LIST mac[32]; -} __packed; - -struct FWCMD_COMMON_ANON_174_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_173_PARAMS { - struct FWCMD_COMMON_NTWK_MULTICAST_SET_REQUEST_PAYLOAD request; - struct FWCMD_COMMON_ANON_174_RESPONSE response; -} __packed; - -/* - * Sets multicast address hash. The MPU will merge the MAC address lists - * from all clients, including the networking and storage functions. - * This command may fail if the final merged list of MAC addresses exceeds - * 32 entries. - */ -struct FWCMD_COMMON_NTWK_MULTICAST_SET { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_173_PARAMS params; -} __packed; - -struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD { - u16 num_vlan; - u8 promiscuous; - u8 rsvd0; - u16 vlan_tag[32]; -} __packed; - -struct FWCMD_COMMON_ANON_176_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_175_PARAMS { - struct FWCMD_COMMON_NTWK_VLAN_CONFIG_REQUEST_PAYLOAD request; - struct FWCMD_COMMON_ANON_176_RESPONSE response; -} __packed; - -/* - * Sets VLAN tag filter. The MPU will merge the VLAN tag list from all - * clients, including the networking and storage functions. This command - * may fail if the final vlan_tag array (from all functions) is longer - * than 32 entries. - */ -struct FWCMD_COMMON_NTWK_VLAN_CONFIG { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_175_PARAMS params; -} __packed; - -struct RING_DESTROY_REQUEST { - u16 ring_type; - u16 id; - u8 bypass_flush; - u8 rsvd0; - u16 rsvd1; -} __packed; - -struct FWCMD_COMMON_ANON_190_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_189_PARAMS { - struct RING_DESTROY_REQUEST request; - struct FWCMD_COMMON_ANON_190_RESPONSE response; -} __packed; -/* - * Command for destroying any ring. The connection(s) using the ring should - * be quiesced before destroying the ring. - */ -struct FWCMD_COMMON_RING_DESTROY { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_189_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_192_REQUEST { - u16 num_pages; - u16 rsvd0; - struct CQ_CONTEXT_AMAP context; - struct PHYS_ADDR pages[4]; -} __packed ; - -struct FWCMD_COMMON_ANON_193_RESPONSE { - u16 cq_id; -} __packed ; - -union FWCMD_COMMON_ANON_191_PARAMS { - struct FWCMD_COMMON_ANON_192_REQUEST request; - struct FWCMD_COMMON_ANON_193_RESPONSE response; -} __packed ; - -/* - * Command for creating a completion queue. A Completion Queue must span - * at least 1 page and at most 4 pages. Each completion queue entry - * is 16 bytes regardless of CQ entry format. Thus the ring must be - * at least 256 entries deep (corresponding to 1 page) and can be at - * most 1024 entries deep (corresponding to 4 pages). The number of - * pages posted must contain the CQ ring size as encoded in the context. - * - */ -struct FWCMD_COMMON_CQ_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_191_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_198_REQUEST { - u16 num_pages; - u16 rsvd0; - struct EQ_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_199_RESPONSE { - u16 eq_id; -} __packed ; - -union FWCMD_COMMON_ANON_197_PARAMS { - struct FWCMD_COMMON_ANON_198_REQUEST request; - struct FWCMD_COMMON_ANON_199_RESPONSE response; -} __packed ; - -/* - * Command for creating a event queue. An Event Queue must span at least - * 1 page and at most 8 pages. The number of pages posted must contain - * the EQ ring. The ring is defined by the size of the EQ entries (encoded - * in the context) and the number of EQ entries (also encoded in the - * context). - */ -struct FWCMD_COMMON_EQ_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_197_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_201_REQUEST { - u16 cq_id; - u16 bcmc_cq_id; - u16 num_pages; - u16 rsvd0; - struct PHYS_ADDR pages[2]; -} __packed; - -struct FWCMD_COMMON_ANON_202_RESPONSE { - u16 id; -} __packed; - -union FWCMD_COMMON_ANON_200_PARAMS { - struct FWCMD_COMMON_ANON_201_REQUEST request; - struct FWCMD_COMMON_ANON_202_RESPONSE response; -} __packed; - -/* - * Command for creating Ethernet receive ring. An ERX ring contains ETH_RX_D - * entries (8 bytes each). An ERX ring must be 1024 entries deep - * (corresponding to 2 pages). - */ -struct FWCMD_COMMON_ETH_RX_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_200_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_204_REQUEST { - u16 num_pages; - u8 ulp_num; - u8 type; - struct ETX_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_205_RESPONSE { - u16 cid; - u8 ulp_num; - u8 rsvd0; -} __packed ; - -union FWCMD_COMMON_ANON_203_PARAMS { - struct FWCMD_COMMON_ANON_204_REQUEST request; - struct FWCMD_COMMON_ANON_205_RESPONSE response; -} __packed ; - -/* - * Command for creating an Ethernet transmit ring. An ETX ring contains - * ETH_WRB entries (16 bytes each). An ETX ring must be at least 256 - * entries deep (corresponding to 1 page) and at most 2k entries deep - * (corresponding to 8 pages). - */ -struct FWCMD_COMMON_ETH_TX_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_203_PARAMS params; -} __packed ; - -struct FWCMD_COMMON_ANON_222_REQUEST { - u16 num_pages; - u16 rsvd0; - struct MCC_RING_CONTEXT_AMAP context; - struct PHYS_ADDR pages[8]; -} __packed ; - -struct FWCMD_COMMON_ANON_223_RESPONSE { - u16 id; -} __packed ; - -union FWCMD_COMMON_ANON_221_PARAMS { - struct FWCMD_COMMON_ANON_222_REQUEST request; - struct FWCMD_COMMON_ANON_223_RESPONSE response; -} __packed ; - -/* - * Command for creating the MCC ring. An MCC ring must be at least 16 - * entries deep (corresponding to 1 page) and at most 128 entries deep - * (corresponding to 8 pages). - */ -struct FWCMD_COMMON_MCC_CREATE { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_221_PARAMS params; -} __packed ; - -struct GET_QOS_IN { - u32 qos_params_rsvd; -} __packed; - -struct GET_QOS_OUT { - u32 max_bits_per_second_NIC; - u32 max_packets_per_second_NIC; - u32 max_ios_per_second_iSCSI; - u32 max_bytes_per_second_iSCSI; - u16 domain_VLAN_tag; - u16 fabric_domain_ID; - u32 qos_params_oem[4]; -} __packed; - -union GET_QOS_PARAMS { - struct GET_QOS_IN request; - struct GET_QOS_OUT response; -} __packed; - -/* QOS/Bandwidth settings per domain. Applicable only in VMs. */ -struct FWCMD_COMMON_GET_QOS { - union FWCMD_HEADER header; - union GET_QOS_PARAMS params; -} __packed; - -struct SET_QOS_IN { - u32 valid_flags; - u32 max_bits_per_second_NIC; - u32 max_packets_per_second_NIC; - u32 max_ios_per_second_iSCSI; - u32 max_bytes_per_second_iSCSI; - u16 domain_VLAN_tag; - u16 fabric_domain_ID; - u32 qos_params_oem[4]; -} __packed; - -struct SET_QOS_OUT { - u32 qos_params_rsvd; -} __packed; - -union SET_QOS_PARAMS { - struct SET_QOS_IN request; - struct SET_QOS_OUT response; -} __packed; - -/* QOS/Bandwidth settings per domain. Applicable only in VMs. */ -struct FWCMD_COMMON_SET_QOS { - union FWCMD_HEADER header; - union SET_QOS_PARAMS params; -} __packed; - -struct SET_FRAME_SIZE_IN { - u32 max_tx_frame_size; - u32 max_rx_frame_size; -} __packed; - -struct SET_FRAME_SIZE_OUT { - u32 chip_max_tx_frame_size; - u32 chip_max_rx_frame_size; -} __packed; - -union SET_FRAME_SIZE_PARAMS { - struct SET_FRAME_SIZE_IN request; - struct SET_FRAME_SIZE_OUT response; -} __packed; - -/* Set frame size command. Only host domain may issue this command. */ -struct FWCMD_COMMON_SET_FRAME_SIZE { - union FWCMD_HEADER header; - union SET_FRAME_SIZE_PARAMS params; -} __packed; - -struct FORCE_FAILOVER_IN { - u32 move_to_port; - u32 failover_config; -} __packed; - -struct FWCMD_COMMON_ANON_231_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_230_PARAMS { - struct FORCE_FAILOVER_IN request; - struct FWCMD_COMMON_ANON_231_RESPONSE response; -} __packed; - -/* - * Use this command to control failover in BladeEngine. It may be used - * to failback to a restored port or to forcibly move traffic from - * one port to another. It may also be used to enable or disable the - * automatic failover feature. This command can only be issued by domain - * 0. - */ -struct FWCMD_COMMON_FORCE_FAILOVER { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_230_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_240_REQUEST { - u64 context; -} __packed; - -struct FWCMD_COMMON_ANON_241_RESPONSE { - u64 context; -} __packed; - -union FWCMD_COMMON_ANON_239_PARAMS { - struct FWCMD_COMMON_ANON_240_REQUEST request; - struct FWCMD_COMMON_ANON_241_RESPONSE response; -} __packed; - -/* - * This command can be used by clients as a no-operation request. Typical - * uses for drivers are as a heartbeat mechanism, or deferred processing - * catalyst. The ARM will always complete this command with a good completion. - * The 64-bit parameter is not touched by the ARM processor. - */ -struct FWCMD_COMMON_NOP { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_239_PARAMS params; -} __packed; - -struct NTWK_RX_FILTER_SETTINGS { - u8 promiscuous; - u8 ip_cksum; - u8 tcp_cksum; - u8 udp_cksum; - u8 pass_err; - u8 pass_ckerr; - u8 strip_crc; - u8 mcast_en; - u8 bcast_en; - u8 mcast_promiscuous_en; - u8 unicast_en; - u8 vlan_promiscuous; -} __packed; - -union FWCMD_COMMON_ANON_242_PARAMS { - struct NTWK_RX_FILTER_SETTINGS request; - struct NTWK_RX_FILTER_SETTINGS response; -} __packed; - -/* - * This command is used to modify the ethernet receive filter configuration. - * Only domain 0 network function drivers may issue this command. The - * applied configuration is returned in the response payload. Note: - * Some receive packet filter settings are global on BladeEngine and - * can affect both the storage and network function clients that the - * BladeEngine hardware and firmware serve. Additionaly, depending - * on the revision of BladeEngine, some ethernet receive filter settings - * are dependent on others. If a dependency exists between settings - * for the BladeEngine revision, and the command request settings do - * not meet the dependency requirement, the invalid settings will not - * be applied despite the comand succeeding. For example: a driver may - * request to enable broadcast packets, but not enable multicast packets. - * On early revisions of BladeEngine, there may be no distinction between - * broadcast and multicast filters, so broadcast could not be enabled - * without enabling multicast. In this scenario, the comand would still - * succeed, but the response payload would indicate the previously - * configured broadcast and multicast setting. - */ -struct FWCMD_COMMON_NTWK_RX_FILTER { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_242_PARAMS params; -} __packed; - - -struct FWCMD_COMMON_ANON_244_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD { - u8 firmware_version_string[32]; - u8 fw_on_flash_version_string[32]; -} __packed; - -union FWCMD_COMMON_ANON_243_PARAMS { - struct FWCMD_COMMON_ANON_244_REQUEST request; - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD response; -} __packed; - -/* This comand retrieves the firmware version. */ -struct FWCMD_COMMON_GET_FW_VERSION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_243_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_246_REQUEST { - u16 tx_flow_control; - u16 rx_flow_control; -} __packed; - -struct FWCMD_COMMON_ANON_247_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_245_PARAMS { - struct FWCMD_COMMON_ANON_246_REQUEST request; - struct FWCMD_COMMON_ANON_247_RESPONSE response; -} __packed; - -/* - * This comand is used to program BladeEngine flow control behavior. - * Only the host networking driver is allowed to use this comand. - */ -struct FWCMD_COMMON_SET_FLOW_CONTROL { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_245_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_249_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_COMMON_ANON_250_RESPONSE { - u16 tx_flow_control; - u16 rx_flow_control; -} __packed; - -union FWCMD_COMMON_ANON_248_PARAMS { - struct FWCMD_COMMON_ANON_249_REQUEST request; - struct FWCMD_COMMON_ANON_250_RESPONSE response; -} __packed; - -/* This comand is used to read BladeEngine flow control settings. */ -struct FWCMD_COMMON_GET_FLOW_CONTROL { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_248_PARAMS params; -} __packed; - -struct EQ_DELAY_PARAMS { - u32 eq_id; - u32 delay_in_microseconds; -} __packed; - -struct FWCMD_COMMON_ANON_257_REQUEST { - u32 num_eq; - u32 rsvd0; - struct EQ_DELAY_PARAMS delay[16]; -} __packed; - -struct FWCMD_COMMON_ANON_258_RESPONSE { - u32 delay_resolution_in_microseconds; - u32 delay_max_in_microseconds; -} __packed; - -union MODIFY_EQ_DELAY_PARAMS { - struct FWCMD_COMMON_ANON_257_REQUEST request; - struct FWCMD_COMMON_ANON_258_RESPONSE response; -} __packed; - -/* This comand changes the EQ delay for a given set of EQs. */ -struct FWCMD_COMMON_MODIFY_EQ_DELAY { - union FWCMD_HEADER header; - union MODIFY_EQ_DELAY_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_260_REQUEST { - u32 rsvd0; -} __packed; - -struct BE_FIRMWARE_CONFIG { - u16 be_config_number; - u16 asic_revision; - u32 nic_ulp_mask; - u32 tulp_mask; - u32 iscsi_ulp_mask; - u32 rdma_ulp_mask; - u32 rsvd0[4]; - u32 eth_tx_id_start; - u32 eth_tx_id_count; - u32 eth_rx_id_start; - u32 eth_rx_id_count; - u32 tpm_wrbq_id_start; - u32 tpm_wrbq_id_count; - u32 tpm_defq_id_start; - u32 tpm_defq_id_count; - u32 iscsi_wrbq_id_start; - u32 iscsi_wrbq_id_count; - u32 iscsi_defq_id_start; - u32 iscsi_defq_id_count; - u32 rdma_qp_id_start; - u32 rdma_qp_id_count; - u32 rsvd1[8]; -} __packed; - -union FWCMD_COMMON_ANON_259_PARAMS { - struct FWCMD_COMMON_ANON_260_REQUEST request; - struct BE_FIRMWARE_CONFIG response; -} __packed; - -/* - * This comand queries the current firmware configuration parameters. - * The static configuration type is defined by be_config_number. This - * differentiates different BladeEngine builds, such as iSCSI Initiator - * versus iSCSI Target. For a given static configuration, the Upper - * Layer Protocol (ULP) processors may be reconfigured to support different - * protocols. Each ULP processor supports one or more protocols. The - * masks indicate which processors are configured for each protocol. - * For a given static configuration, the number of TCP connections - * supported for each protocol may vary. The *_id_start and *_id_count - * variables define a linear range of IDs that are available for each - * supported protocol. The *_id_count may be used by the driver to allocate - * the appropriate number of connection resources. The *_id_start may - * be used to map the arbitrary range of IDs to a zero-based range - * of indices. - */ -struct FWCMD_COMMON_FIRMWARE_CONFIG { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_259_PARAMS params; -} __packed; - -struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS { - u32 emph_lev_sel_port0; - u32 emph_lev_sel_port1; - u8 xaui_vo_sel; - u8 xaui_state; - u16 rsvd0; - u32 xaui_eq_vector; -} __packed; - -struct FWCMD_COMMON_ANON_262_REQUEST { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_261_PARAMS { - struct FWCMD_COMMON_ANON_262_REQUEST request; - struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS response; -} __packed; - -/* - * This comand can be used to read XAUI equalization parameters. The - * ARM firmware applies default equalization parameters during initialization. - * These parameters may be customer-specific when derived from the - * SEEPROM. See SEEPROM_DATA for equalization specific fields. - */ -struct FWCMD_COMMON_GET_PORT_EQUALIZATION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_261_PARAMS params; -} __packed; - -struct FWCMD_COMMON_ANON_264_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_COMMON_ANON_263_PARAMS { - struct FWCMD_COMMON_PORT_EQUALIZATION_PARAMS request; - struct FWCMD_COMMON_ANON_264_RESPONSE response; -} __packed; - -/* - * This comand can be used to set XAUI equalization parameters. The ARM - * firmware applies default equalization parameters during initialization. - * These parameters may be customer-specific when derived from the - * SEEPROM. See SEEPROM_DATA for equalization specific fields. - */ -struct FWCMD_COMMON_SET_PORT_EQUALIZATION { - union FWCMD_HEADER header; - union FWCMD_COMMON_ANON_263_PARAMS params; -} __packed; - -#endif /* __fwcmd_common_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_eth_bmap.h b/drivers/staging/benet/fwcmd_eth_bmap.h deleted file mode 100644 index 234b179eace..00000000000 --- a/drivers/staging/benet/fwcmd_eth_bmap.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_eth_bmap_h__ -#define __fwcmd_eth_bmap_h__ -#include "fwcmd_hdr_bmap.h" -#include "fwcmd_types_bmap.h" - -struct MIB_ETH_STATISTICS_PARAMS_IN { - u32 rsvd0; -} __packed; - -struct BE_RXF_STATS { - u32 p0recvdtotalbytesLSD; /* DWORD 0 */ - u32 p0recvdtotalbytesMSD; /* DWORD 1 */ - u32 p0recvdtotalframes; /* DWORD 2 */ - u32 p0recvdunicastframes; /* DWORD 3 */ - u32 p0recvdmulticastframes; /* DWORD 4 */ - u32 p0recvdbroadcastframes; /* DWORD 5 */ - u32 p0crcerrors; /* DWORD 6 */ - u32 p0alignmentsymerrs; /* DWORD 7 */ - u32 p0pauseframesrecvd; /* DWORD 8 */ - u32 p0controlframesrecvd; /* DWORD 9 */ - u32 p0inrangelenerrors; /* DWORD 10 */ - u32 p0outrangeerrors; /* DWORD 11 */ - u32 p0frametoolongerrors; /* DWORD 12 */ - u32 p0droppedaddressmatch; /* DWORD 13 */ - u32 p0droppedvlanmismatch; /* DWORD 14 */ - u32 p0ipdroppedtoosmall; /* DWORD 15 */ - u32 p0ipdroppedtooshort; /* DWORD 16 */ - u32 p0ipdroppedhdrtoosmall; /* DWORD 17 */ - u32 p0tcpdroppedlen; /* DWORD 18 */ - u32 p0droppedrunt; /* DWORD 19 */ - u32 p0recvd64; /* DWORD 20 */ - u32 p0recvd65_127; /* DWORD 21 */ - u32 p0recvd128_256; /* DWORD 22 */ - u32 p0recvd256_511; /* DWORD 23 */ - u32 p0recvd512_1023; /* DWORD 24 */ - u32 p0recvd1518_1522; /* DWORD 25 */ - u32 p0recvd1522_2047; /* DWORD 26 */ - u32 p0recvd2048_4095; /* DWORD 27 */ - u32 p0recvd4096_8191; /* DWORD 28 */ - u32 p0recvd8192_9216; /* DWORD 29 */ - u32 p0rcvdipcksmerrs; /* DWORD 30 */ - u32 p0recvdtcpcksmerrs; /* DWORD 31 */ - u32 p0recvdudpcksmerrs; /* DWORD 32 */ - u32 p0recvdnonrsspackets; /* DWORD 33 */ - u32 p0recvdippackets; /* DWORD 34 */ - u32 p0recvdchute1packets; /* DWORD 35 */ - u32 p0recvdchute2packets; /* DWORD 36 */ - u32 p0recvdchute3packets; /* DWORD 37 */ - u32 p0recvdipsecpackets; /* DWORD 38 */ - u32 p0recvdmanagementpackets; /* DWORD 39 */ - u32 p0xmitbyteslsd; /* DWORD 40 */ - u32 p0xmitbytesmsd; /* DWORD 41 */ - u32 p0xmitunicastframes; /* DWORD 42 */ - u32 p0xmitmulticastframes; /* DWORD 43 */ - u32 p0xmitbroadcastframes; /* DWORD 44 */ - u32 p0xmitpauseframes; /* DWORD 45 */ - u32 p0xmitcontrolframes; /* DWORD 46 */ - u32 p0xmit64; /* DWORD 47 */ - u32 p0xmit65_127; /* DWORD 48 */ - u32 p0xmit128_256; /* DWORD 49 */ - u32 p0xmit256_511; /* DWORD 50 */ - u32 p0xmit512_1023; /* DWORD 51 */ - u32 p0xmit1518_1522; /* DWORD 52 */ - u32 p0xmit1522_2047; /* DWORD 53 */ - u32 p0xmit2048_4095; /* DWORD 54 */ - u32 p0xmit4096_8191; /* DWORD 55 */ - u32 p0xmit8192_9216; /* DWORD 56 */ - u32 p0rxfifooverflowdropped; /* DWORD 57 */ - u32 p0ipseclookupfaileddropped; /* DWORD 58 */ - u32 p1recvdtotalbytesLSD; /* DWORD 59 */ - u32 p1recvdtotalbytesMSD; /* DWORD 60 */ - u32 p1recvdtotalframes; /* DWORD 61 */ - u32 p1recvdunicastframes; /* DWORD 62 */ - u32 p1recvdmulticastframes; /* DWORD 63 */ - u32 p1recvdbroadcastframes; /* DWORD 64 */ - u32 p1crcerrors; /* DWORD 65 */ - u32 p1alignmentsymerrs; /* DWORD 66 */ - u32 p1pauseframesrecvd; /* DWORD 67 */ - u32 p1controlframesrecvd; /* DWORD 68 */ - u32 p1inrangelenerrors; /* DWORD 69 */ - u32 p1outrangeerrors; /* DWORD 70 */ - u32 p1frametoolongerrors; /* DWORD 71 */ - u32 p1droppedaddressmatch; /* DWORD 72 */ - u32 p1droppedvlanmismatch; /* DWORD 73 */ - u32 p1ipdroppedtoosmall; /* DWORD 74 */ - u32 p1ipdroppedtooshort; /* DWORD 75 */ - u32 p1ipdroppedhdrtoosmall; /* DWORD 76 */ - u32 p1tcpdroppedlen; /* DWORD 77 */ - u32 p1droppedrunt; /* DWORD 78 */ - u32 p1recvd64; /* DWORD 79 */ - u32 p1recvd65_127; /* DWORD 80 */ - u32 p1recvd128_256; /* DWORD 81 */ - u32 p1recvd256_511; /* DWORD 82 */ - u32 p1recvd512_1023; /* DWORD 83 */ - u32 p1recvd1518_1522; /* DWORD 84 */ - u32 p1recvd1522_2047; /* DWORD 85 */ - u32 p1recvd2048_4095; /* DWORD 86 */ - u32 p1recvd4096_8191; /* DWORD 87 */ - u32 p1recvd8192_9216; /* DWORD 88 */ - u32 p1rcvdipcksmerrs; /* DWORD 89 */ - u32 p1recvdtcpcksmerrs; /* DWORD 90 */ - u32 p1recvdudpcksmerrs; /* DWORD 91 */ - u32 p1recvdnonrsspackets; /* DWORD 92 */ - u32 p1recvdippackets; /* DWORD 93 */ - u32 p1recvdchute1packets; /* DWORD 94 */ - u32 p1recvdchute2packets; /* DWORD 95 */ - u32 p1recvdchute3packets; /* DWORD 96 */ - u32 p1recvdipsecpackets; /* DWORD 97 */ - u32 p1recvdmanagementpackets; /* DWORD 98 */ - u32 p1xmitbyteslsd; /* DWORD 99 */ - u32 p1xmitbytesmsd; /* DWORD 100 */ - u32 p1xmitunicastframes; /* DWORD 101 */ - u32 p1xmitmulticastframes; /* DWORD 102 */ - u32 p1xmitbroadcastframes; /* DWORD 103 */ - u32 p1xmitpauseframes; /* DWORD 104 */ - u32 p1xmitcontrolframes; /* DWORD 105 */ - u32 p1xmit64; /* DWORD 106 */ - u32 p1xmit65_127; /* DWORD 107 */ - u32 p1xmit128_256; /* DWORD 108 */ - u32 p1xmit256_511; /* DWORD 109 */ - u32 p1xmit512_1023; /* DWORD 110 */ - u32 p1xmit1518_1522; /* DWORD 111 */ - u32 p1xmit1522_2047; /* DWORD 112 */ - u32 p1xmit2048_4095; /* DWORD 113 */ - u32 p1xmit4096_8191; /* DWORD 114 */ - u32 p1xmit8192_9216; /* DWORD 115 */ - u32 p1rxfifooverflowdropped; /* DWORD 116 */ - u32 p1ipseclookupfaileddropped; /* DWORD 117 */ - u32 pxdroppednopbuf; /* DWORD 118 */ - u32 pxdroppednotxpb; /* DWORD 119 */ - u32 pxdroppednoipsecbuf; /* DWORD 120 */ - u32 pxdroppednoerxdescr; /* DWORD 121 */ - u32 pxdroppednotpredescr; /* DWORD 122 */ - u32 pxrecvdmanagementportpackets; /* DWORD 123 */ - u32 pxrecvdmanagementportbytes; /* DWORD 124 */ - u32 pxrecvdmanagementportpauseframes; /* DWORD 125 */ - u32 pxrecvdmanagementporterrors; /* DWORD 126 */ - u32 pxxmitmanagementportpackets; /* DWORD 127 */ - u32 pxxmitmanagementportbytes; /* DWORD 128 */ - u32 pxxmitmanagementportpause; /* DWORD 129 */ - u32 pxxmitmanagementportrxfifooverflow; /* DWORD 130 */ - u32 pxrecvdipsecipcksmerrs; /* DWORD 131 */ - u32 pxrecvdtcpsecipcksmerrs; /* DWORD 132 */ - u32 pxrecvdudpsecipcksmerrs; /* DWORD 133 */ - u32 pxipsecrunt; /* DWORD 134 */ - u32 pxipsecaddressmismatchdropped; /* DWORD 135 */ - u32 pxipsecrxfifooverflowdropped; /* DWORD 136 */ - u32 pxipsecframestoolong; /* DWORD 137 */ - u32 pxipsectotalipframes; /* DWORD 138 */ - u32 pxipseciptoosmall; /* DWORD 139 */ - u32 pxipseciptooshort; /* DWORD 140 */ - u32 pxipseciphdrtoosmall; /* DWORD 141 */ - u32 pxipsectcphdrbad; /* DWORD 142 */ - u32 pxrecvdipsecchute1; /* DWORD 143 */ - u32 pxrecvdipsecchute2; /* DWORD 144 */ - u32 pxrecvdipsecchute3; /* DWORD 145 */ - u32 pxdropped7frags; /* DWORD 146 */ - u32 pxdroppedfrags; /* DWORD 147 */ - u32 pxdroppedinvalidfragring; /* DWORD 148 */ - u32 pxnumforwardedpackets; /* DWORD 149 */ -} __packed; - -union MIB_ETH_STATISTICS_PARAMS { - struct MIB_ETH_STATISTICS_PARAMS_IN request; - struct BE_RXF_STATS response; -} __packed; - -/* - * Query ethernet statistics. All domains may issue this command. The - * host domain drivers may optionally reset internal statistic counters - * with a query. - */ -struct FWCMD_ETH_GET_STATISTICS { - union FWCMD_HEADER header; - union MIB_ETH_STATISTICS_PARAMS params; -} __packed; - - -struct FWCMD_ETH_ANON_175_REQUEST { - u8 port0_promiscuous; - u8 port1_promiscuous; - u16 rsvd0; -} __packed; - -struct FWCMD_ETH_ANON_176_RESPONSE { - u32 rsvd0; -} __packed; - -union FWCMD_ETH_ANON_174_PARAMS { - struct FWCMD_ETH_ANON_175_REQUEST request; - struct FWCMD_ETH_ANON_176_RESPONSE response; -} __packed; - -/* Enables/Disables promiscuous ethernet receive mode. */ -struct FWCMD_ETH_PROMISCUOUS { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_174_PARAMS params; -} __packed; - -struct FWCMD_ETH_ANON_178_REQUEST { - u32 new_fragsize_log2; -} __packed; - -struct FWCMD_ETH_ANON_179_RESPONSE { - u32 actual_fragsize_log2; -} __packed; - -union FWCMD_ETH_ANON_177_PARAMS { - struct FWCMD_ETH_ANON_178_REQUEST request; - struct FWCMD_ETH_ANON_179_RESPONSE response; -} __packed; - -/* - * Sets the Ethernet RX fragment size. Only host (domain 0) networking - * drivers may issue this command. This call will fail for non-host - * protection domains. In this situation the MCC CQ status will indicate - * a failure due to insufficient priviledges. The response should be - * ignored, and the driver should use the FWCMD_ETH_GET_FRAG_SIZE to - * query the existing ethernet receive fragment size. It must use this - * fragment size for all fragments in the ethernet receive ring. If - * the command succeeds, the driver must use the frag size indicated - * in the command response since the requested frag size may not be applied - * until the next reboot. When the requested fragsize matches the response - * fragsize, this indicates the request was applied immediately. - */ -struct FWCMD_ETH_SET_RX_FRAG_SIZE { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_177_PARAMS params; -} __packed; - -struct FWCMD_ETH_ANON_181_REQUEST { - u32 rsvd0; -} __packed; - -struct FWCMD_ETH_ANON_182_RESPONSE { - u32 actual_fragsize_log2; -} __packed; - -union FWCMD_ETH_ANON_180_PARAMS { - struct FWCMD_ETH_ANON_181_REQUEST request; - struct FWCMD_ETH_ANON_182_RESPONSE response; -} __packed; - -/* - * Queries the Ethernet RX fragment size. All domains may issue this - * command. The driver should call this command to determine the minimum - * required fragment size for the ethernet RX ring buffers. Drivers - * may choose to use a larger size for each fragment buffer, but BladeEngine - * will use up to the configured minimum required fragsize in each ethernet - * receive fragment buffer. For example, if the ethernet receive fragment - * size is configured to 4kB, and a driver uses 8kB fragments, a 6kB - * ethernet packet received by BladeEngine will be split accross two - * of the driver's receive framgents (4kB in one fragment buffer, and - * 2kB in the subsequent fragment buffer). - */ -struct FWCMD_ETH_GET_RX_FRAG_SIZE { - union FWCMD_HEADER header; - union FWCMD_ETH_ANON_180_PARAMS params; -} __packed; - -#endif /* __fwcmd_eth_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_hdr_bmap.h b/drivers/staging/benet/fwcmd_hdr_bmap.h deleted file mode 100644 index 28b45328fe7..00000000000 --- a/drivers/staging/benet/fwcmd_hdr_bmap.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_hdr_bmap_h__ -#define __fwcmd_hdr_bmap_h__ - -struct FWCMD_REQUEST_HEADER { - u8 opcode; - u8 subsystem; - u8 port_number; - u8 domain; - u32 timeout; - u32 request_length; - u32 rsvd0; -} __packed; - -struct FWCMD_RESPONSE_HEADER { - u8 opcode; - u8 subsystem; - u8 rsvd0; - u8 domain; - u8 status; - u8 additional_status; - u16 rsvd1; - u32 response_length; - u32 actual_response_length; -} __packed; - -/* - * The firmware/driver overwrites the input FWCMD_REQUEST_HEADER with - * the output FWCMD_RESPONSE_HEADER. - */ -union FWCMD_HEADER { - struct FWCMD_REQUEST_HEADER request; - struct FWCMD_RESPONSE_HEADER response; -} __packed; - -#endif /* __fwcmd_hdr_bmap_h__ */ diff --git a/drivers/staging/benet/fwcmd_mcc.h b/drivers/staging/benet/fwcmd_mcc.h deleted file mode 100644 index 9eeca878c1f..00000000000 --- a/drivers/staging/benet/fwcmd_mcc.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_mcc_amap_h__ -#define __fwcmd_mcc_amap_h__ -#include "fwcmd_opcodes.h" -/* - * Where applicable, a WRB, may contain a list of Scatter-gather elements. - * Each element supports a 64 bit address and a 32bit length field. - */ -struct BE_MCC_SGE_AMAP { - u8 pa_lo[32]; /* DWORD 0 */ - u8 pa_hi[32]; /* DWORD 1 */ - u8 length[32]; /* DWORD 2 */ -} __packed; -struct MCC_SGE_AMAP { - u32 dw[3]; -}; -/* - * The design of an MCC_SGE allows up to 19 elements to be embedded - * in a WRB, supporting 64KB data transfers (assuming a 4KB page size). - */ -struct BE_MCC_WRB_PAYLOAD_AMAP { - union { - struct BE_MCC_SGE_AMAP sgl[19]; - u8 embedded[59][32]; /* DWORD 0 */ - }; -} __packed; -struct MCC_WRB_PAYLOAD_AMAP { - u32 dw[59]; -}; - -/* - * This is the structure of the MCC Command WRB for commands - * sent to the Management Processing Unit (MPU). See section - * for usage in embedded and non-embedded modes. - */ -struct BE_MCC_WRB_AMAP { - u8 embedded; /* DWORD 0 */ - u8 rsvd0[2]; /* DWORD 0 */ - u8 sge_count[5]; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 special[8]; /* DWORD 0 */ - u8 payload_length[32]; /* DWORD 1 */ - u8 tag[2][32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 4 */ - struct BE_MCC_WRB_PAYLOAD_AMAP payload; -} __packed; -struct MCC_WRB_AMAP { - u32 dw[64]; -}; - -/* This is the structure of the MCC Completion queue entry */ -struct BE_MCC_CQ_ENTRY_AMAP { - u8 completion_status[16]; /* DWORD 0 */ - u8 extended_status[16]; /* DWORD 0 */ - u8 mcc_tag[2][32]; /* DWORD 1 */ - u8 rsvd0[27]; /* DWORD 3 */ - u8 consumed; /* DWORD 3 */ - u8 completed; /* DWORD 3 */ - u8 hpi_buffer_completion; /* DWORD 3 */ - u8 async_event; /* DWORD 3 */ - u8 valid; /* DWORD 3 */ -} __packed; -struct MCC_CQ_ENTRY_AMAP { - u32 dw[4]; -}; - -/* Mailbox structures used by the MPU during bootstrap */ -struct BE_MCC_MAILBOX_AMAP { - struct BE_MCC_WRB_AMAP wrb; - struct BE_MCC_CQ_ENTRY_AMAP cq; -} __packed; -struct MCC_MAILBOX_AMAP { - u32 dw[68]; -}; - -#endif /* __fwcmd_mcc_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_opcodes.h b/drivers/staging/benet/fwcmd_opcodes.h deleted file mode 100644 index 23d569386b4..00000000000 --- a/drivers/staging/benet/fwcmd_opcodes.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_opcodes_amap_h__ -#define __fwcmd_opcodes_amap_h__ - -/* - * --- FWCMD_SUBSYSTEMS --- - * The commands are grouped into the following subsystems. The subsystem - * code along with the opcode uniquely identify a particular fwcmd. - */ -#define FWCMD_SUBSYSTEM_RSVD (0) /* This subsystem is reserved. It is */ - /* never used. */ -#define FWCMD_SUBSYSTEM_COMMON (1) /* CMDs in this group are common to - * all subsystems. See - * COMMON_SUBSYSTEM_OPCODES for opcodes - * and Common Host Configuration CMDs - * for the FWCMD descriptions. - */ -#define FWCMD_SUBSYSTEM_COMMON_ISCSI (2) /* CMDs in this group are */ - /* - * common to Initiator and Target. See - * COMMON_ISCSI_SUBSYSTEM_OPCODES and - * Common iSCSI Initiator and Target - * CMDs for the command descriptions. - */ -#define FWCMD_SUBSYSTEM_ETH (3) /* This subsystem is used to - execute Ethernet commands. */ - -#define FWCMD_SUBSYSTEM_TPM (4) /* This subsystem is used - to execute TPM commands. */ -#define FWCMD_SUBSYSTEM_PXE_UNDI (5) /* This subsystem is used - * to execute PXE - * and UNDI specific commands. - */ - -#define FWCMD_SUBSYSTEM_ISCSI_INI (6) /* This subsystem is used to - execute ISCSI Initiator - specific commands. - */ -#define FWCMD_SUBSYSTEM_ISCSI_TGT (7) /* This subsystem is used - to execute iSCSI Target - specific commands.between - PTL and ARM firmware. - */ -#define FWCMD_SUBSYSTEM_MILI_PTL (8) /* This subsystem is used to - execute iSCSI Target specific - commands.between MILI - and PTL. */ -#define FWCMD_SUBSYSTEM_MILI_TMD (9) /* This subsystem is used to - execute iSCSI Target specific - commands between MILI - and TMD. */ -#define FWCMD_SUBSYSTEM_PROXY (11) /* This subsystem is used - to execute proxied commands - within the host at the - explicit request of a - non priviledged domain. - This 'subsystem' is entirely - virtual from the controller - and firmware perspective as - it is implemented in host - drivers. - */ - -/* - * --- COMMON_SUBSYSTEM_OPCODES --- - * These opcodes are common to both networking and storage PCI - * functions. They are used to reserve resources and configure - * BladeEngine. These opcodes all use the FWCMD_SUBSYSTEM_COMMON - * subsystem code. - */ -#define OPCODE_COMMON_NTWK_MAC_QUERY (1) -#define SUBSYSTEM_COMMON_NTWK_MAC_QUERY (1) -#define SUBSYSTEM_COMMON_NTWK_MAC_SET (1) -#define SUBSYSTEM_COMMON_NTWK_MULTICAST_SET (1) -#define SUBSYSTEM_COMMON_NTWK_VLAN_CONFIG (1) -#define SUBSYSTEM_COMMON_NTWK_LINK_STATUS_QUERY (1) -#define SUBSYSTEM_COMMON_READ_FLASHROM (1) -#define SUBSYSTEM_COMMON_WRITE_FLASHROM (1) -#define SUBSYSTEM_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (1) -#define SUBSYSTEM_COMMON_ADD_PAGE_TABLES (1) -#define SUBSYSTEM_COMMON_REMOVE_PAGE_TABLES (1) -#define SUBSYSTEM_COMMON_RING_DESTROY (1) -#define SUBSYSTEM_COMMON_CQ_CREATE (1) -#define SUBSYSTEM_COMMON_EQ_CREATE (1) -#define SUBSYSTEM_COMMON_ETH_RX_CREATE (1) -#define SUBSYSTEM_COMMON_ETH_TX_CREATE (1) -#define SUBSYSTEM_COMMON_ISCSI_DEFQ_CREATE (1) -#define SUBSYSTEM_COMMON_ISCSI_WRBQ_CREATE (1) -#define SUBSYSTEM_COMMON_MCC_CREATE (1) -#define SUBSYSTEM_COMMON_JELL_CONFIG (1) -#define SUBSYSTEM_COMMON_FORCE_FAILOVER (1) -#define SUBSYSTEM_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (1) -#define SUBSYSTEM_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (1) -#define SUBSYSTEM_COMMON_POST_ZERO_BUFFER (1) -#define SUBSYSTEM_COMMON_GET_QOS (1) -#define SUBSYSTEM_COMMON_SET_QOS (1) -#define SUBSYSTEM_COMMON_TCP_GET_STATISTICS (1) -#define SUBSYSTEM_COMMON_SEEPROM_READ (1) -#define SUBSYSTEM_COMMON_TCP_STATE_QUERY (1) -#define SUBSYSTEM_COMMON_GET_CNTL_ATTRIBUTES (1) -#define SUBSYSTEM_COMMON_NOP (1) -#define SUBSYSTEM_COMMON_NTWK_RX_FILTER (1) -#define SUBSYSTEM_COMMON_GET_FW_VERSION (1) -#define SUBSYSTEM_COMMON_SET_FLOW_CONTROL (1) -#define SUBSYSTEM_COMMON_GET_FLOW_CONTROL (1) -#define SUBSYSTEM_COMMON_SET_TCP_PARAMETERS (1) -#define SUBSYSTEM_COMMON_SET_FRAME_SIZE (1) -#define SUBSYSTEM_COMMON_GET_FAT (1) -#define SUBSYSTEM_COMMON_MODIFY_EQ_DELAY (1) -#define SUBSYSTEM_COMMON_FIRMWARE_CONFIG (1) -#define SUBSYSTEM_COMMON_ENABLE_DISABLE_DOMAINS (1) -#define SUBSYSTEM_COMMON_GET_DOMAIN_CONFIG (1) -#define SUBSYSTEM_COMMON_SET_VLD_CONFIG (1) -#define SUBSYSTEM_COMMON_GET_VLD_CONFIG (1) -#define SUBSYSTEM_COMMON_GET_PORT_EQUALIZATION (1) -#define SUBSYSTEM_COMMON_SET_PORT_EQUALIZATION (1) -#define SUBSYSTEM_COMMON_RED_CONFIG (1) -#define OPCODE_COMMON_NTWK_MAC_SET (2) -#define OPCODE_COMMON_NTWK_MULTICAST_SET (3) -#define OPCODE_COMMON_NTWK_VLAN_CONFIG (4) -#define OPCODE_COMMON_NTWK_LINK_STATUS_QUERY (5) -#define OPCODE_COMMON_READ_FLASHROM (6) -#define OPCODE_COMMON_WRITE_FLASHROM (7) -#define OPCODE_COMMON_QUERY_MAX_FWCMD_BUFFER_SIZE (8) -#define OPCODE_COMMON_ADD_PAGE_TABLES (9) -#define OPCODE_COMMON_REMOVE_PAGE_TABLES (10) -#define OPCODE_COMMON_RING_DESTROY (11) -#define OPCODE_COMMON_CQ_CREATE (12) -#define OPCODE_COMMON_EQ_CREATE (13) -#define OPCODE_COMMON_ETH_RX_CREATE (14) -#define OPCODE_COMMON_ETH_TX_CREATE (15) -#define OPCODE_COMMON_NET_RESERVED0 (16) /* Reserved */ -#define OPCODE_COMMON_NET_RESERVED1 (17) /* Reserved */ -#define OPCODE_COMMON_NET_RESERVED2 (18) /* Reserved */ -#define OPCODE_COMMON_ISCSI_DEFQ_CREATE (19) -#define OPCODE_COMMON_ISCSI_WRBQ_CREATE (20) -#define OPCODE_COMMON_MCC_CREATE (21) -#define OPCODE_COMMON_JELL_CONFIG (22) -#define OPCODE_COMMON_FORCE_FAILOVER (23) -#define OPCODE_COMMON_ADD_TEMPLATE_HEADER_BUFFERS (24) -#define OPCODE_COMMON_REMOVE_TEMPLATE_HEADER_BUFFERS (25) -#define OPCODE_COMMON_POST_ZERO_BUFFER (26) -#define OPCODE_COMMON_GET_QOS (27) -#define OPCODE_COMMON_SET_QOS (28) -#define OPCODE_COMMON_TCP_GET_STATISTICS (29) -#define OPCODE_COMMON_SEEPROM_READ (30) -#define OPCODE_COMMON_TCP_STATE_QUERY (31) -#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES (32) -#define OPCODE_COMMON_NOP (33) -#define OPCODE_COMMON_NTWK_RX_FILTER (34) -#define OPCODE_COMMON_GET_FW_VERSION (35) -#define OPCODE_COMMON_SET_FLOW_CONTROL (36) -#define OPCODE_COMMON_GET_FLOW_CONTROL (37) -#define OPCODE_COMMON_SET_TCP_PARAMETERS (38) -#define OPCODE_COMMON_SET_FRAME_SIZE (39) -#define OPCODE_COMMON_GET_FAT (40) -#define OPCODE_COMMON_MODIFY_EQ_DELAY (41) -#define OPCODE_COMMON_FIRMWARE_CONFIG (42) -#define OPCODE_COMMON_ENABLE_DISABLE_DOMAINS (43) -#define OPCODE_COMMON_GET_DOMAIN_CONFIG (44) -#define OPCODE_COMMON_SET_VLD_CONFIG (45) -#define OPCODE_COMMON_GET_VLD_CONFIG (46) -#define OPCODE_COMMON_GET_PORT_EQUALIZATION (47) -#define OPCODE_COMMON_SET_PORT_EQUALIZATION (48) -#define OPCODE_COMMON_RED_CONFIG (49) - - - -/* - * --- ETH_SUBSYSTEM_OPCODES --- - * These opcodes are used for configuring the Ethernet interfaces. These - * opcodes all use the FWCMD_SUBSYSTEM_ETH subsystem code. - */ -#define OPCODE_ETH_RSS_CONFIG (1) -#define OPCODE_ETH_ACPI_CONFIG (2) -#define SUBSYSTEM_ETH_RSS_CONFIG (3) -#define SUBSYSTEM_ETH_ACPI_CONFIG (3) -#define OPCODE_ETH_PROMISCUOUS (3) -#define SUBSYSTEM_ETH_PROMISCUOUS (3) -#define SUBSYSTEM_ETH_GET_STATISTICS (3) -#define SUBSYSTEM_ETH_GET_RX_FRAG_SIZE (3) -#define SUBSYSTEM_ETH_SET_RX_FRAG_SIZE (3) -#define OPCODE_ETH_GET_STATISTICS (4) -#define OPCODE_ETH_GET_RX_FRAG_SIZE (5) -#define OPCODE_ETH_SET_RX_FRAG_SIZE (6) - - - - - -/* - * --- MCC_STATUS_CODE --- - * These are the global status codes used by all subsystems - */ -#define MCC_STATUS_SUCCESS (0) /* Indicates a successful - completion of the command */ -#define MCC_STATUS_INSUFFICIENT_PRIVILEGES (1) /* The client does not have - sufficient privileges to - execute the command */ -#define MCC_STATUS_INVALID_PARAMETER (2) /* A parameter in the command - was invalid. The extended - status contains the index - of the parameter */ -#define MCC_STATUS_INSUFFICIENT_RESOURCES (3) /* There are insufficient - chip resources to execute - the command */ -#define MCC_STATUS_QUEUE_FLUSHING (4) /* The command is completing - because the queue was - getting flushed */ -#define MCC_STATUS_DMA_FAILED (5) /* The command is completing - with a DMA error */ - -/* - * --- MGMT_ERROR_CODES --- - * Error Codes returned in the status field of the FWCMD response header - */ -#define MGMT_STATUS_SUCCESS (0) /* The FWCMD completed - without errors */ -#define MGMT_STATUS_FAILED (1) /* Error status in the Status - field of the - struct FWCMD_RESPONSE_HEADER */ -#define MGMT_STATUS_ILLEGAL_REQUEST (2) /* Invalid FWCMD opcode */ -#define MGMT_STATUS_ILLEGAL_FIELD (3) /* Invalid parameter in - the FWCMD payload */ - -#endif /* __fwcmd_opcodes_amap_h__ */ diff --git a/drivers/staging/benet/fwcmd_types_bmap.h b/drivers/staging/benet/fwcmd_types_bmap.h deleted file mode 100644 index 92217aff3a1..00000000000 --- a/drivers/staging/benet/fwcmd_types_bmap.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __fwcmd_types_bmap_h__ -#define __fwcmd_types_bmap_h__ - -/* MAC address format */ -struct MAC_ADDRESS_FORMAT { - u16 SizeOfStructure; - u8 MACAddress[6]; -} __packed; - -#endif /* __fwcmd_types_bmap_h__ */ diff --git a/drivers/staging/benet/host_struct.h b/drivers/staging/benet/host_struct.h deleted file mode 100644 index 3de6722b980..00000000000 --- a/drivers/staging/benet/host_struct.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __host_struct_amap_h__ -#define __host_struct_amap_h__ -#include "be_cm.h" -#include "be_common.h" -#include "descriptors.h" - -/* --- EQ_COMPLETION_MAJOR_CODE_ENUM --- */ -#define EQ_MAJOR_CODE_COMPLETION (0) /* Completion event on a */ - /* qcompletion ueue. */ -#define EQ_MAJOR_CODE_ETH (1) /* Affiliated Ethernet Event. */ -#define EQ_MAJOR_CODE_RESERVED (2) /* Reserved */ -#define EQ_MAJOR_CODE_RDMA (3) /* Affiliated RDMA Event. */ -#define EQ_MAJOR_CODE_ISCSI (4) /* Affiliated ISCSI Event */ -#define EQ_MAJOR_CODE_UNAFFILIATED (5) /* Unaffiliated Event */ - -/* --- EQ_COMPLETION_MINOR_CODE_ENUM --- */ -#define EQ_MINOR_CODE_COMPLETION (0) /* Completion event on a */ - /* completion queue. */ -#define EQ_MINOR_CODE_OTHER (1) /* Other Event (TBD). */ - -/* Queue Entry Definition for all 4 byte event queue types. */ -struct BE_EQ_ENTRY_AMAP { - u8 Valid; /* DWORD 0 */ - u8 MajorCode[3]; /* DWORD 0 */ - u8 MinorCode[12]; /* DWORD 0 */ - u8 ResourceID[16]; /* DWORD 0 */ -} __packed; -struct EQ_ENTRY_AMAP { - u32 dw[1]; -}; - -/* - * --- ETH_EVENT_CODE --- - * These codes are returned by the MPU when one of these events has occurred, - * and the event is configured to report to an Event Queue when an event - * is detected. - */ -#define ETH_EQ_LINK_STATUS (0) /* Link status change event */ - /* detected. */ -#define ETH_EQ_WATERMARK (1) /* watermark event detected. */ -#define ETH_EQ_MAGIC_PKT (2) /* magic pkt event detected. */ -#define ETH_EQ_ACPI_PKT0 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT1 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT2 (3) /* ACPI interesting packet */ - /* detected. */ -#define ETH_EQ_ACPI_PKT3 (3) /* ACPI interesting packet */ - /* detected. */ - -/* - * --- ETH_TX_COMPL_STATUS_ENUM --- - * Status codes contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_VALID (0) -#define ETH_COMP_ERROR (1) -#define ETH_COMP_INVALID (15) - -/* - * --- ETH_TX_COMPL_PORT_ENUM --- - * Port indicator contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_PORT0 (0) -#define ETH_COMP_PORT1 (1) -#define ETH_COMP_MGMT (2) - -/* - * --- ETH_TX_COMPL_CT_ENUM --- - * Completion type indicator contained in Ethernet TX completion descriptors. - */ -#define ETH_COMP_ETH (0) - -/* - * Work request block that the driver issues to the chip for - * Ethernet transmissions. All control fields must be valid in each WRB for - * a message. The controller, as specified by the flags, optionally writes - * an entry to the Completion Ring and generate an event. - */ -struct BE_ETH_WRB_AMAP { - u8 frag_pa_hi[32]; /* DWORD 0 */ - u8 frag_pa_lo[32]; /* DWORD 1 */ - u8 complete; /* DWORD 2 */ - u8 event; /* DWORD 2 */ - u8 crc; /* DWORD 2 */ - u8 forward; /* DWORD 2 */ - u8 ipsec; /* DWORD 2 */ - u8 mgmt; /* DWORD 2 */ - u8 ipcs; /* DWORD 2 */ - u8 udpcs; /* DWORD 2 */ - u8 tcpcs; /* DWORD 2 */ - u8 lso; /* DWORD 2 */ - u8 last; /* DWORD 2 */ - u8 vlan; /* DWORD 2 */ - u8 dbg[3]; /* DWORD 2 */ - u8 hash_val[3]; /* DWORD 2 */ - u8 lso_mss[14]; /* DWORD 2 */ - u8 frag_len[16]; /* DWORD 3 */ - u8 vlan_tag[16]; /* DWORD 3 */ -} __packed; -struct ETH_WRB_AMAP { - u32 dw[4]; -}; - -/* This is an Ethernet transmit completion descriptor */ -struct BE_ETH_TX_COMPL_AMAP { - u8 user_bytes[16]; /* DWORD 0 */ - u8 nwh_bytes[8]; /* DWORD 0 */ - u8 lso; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ - u8 wrb_index[16]; /* DWORD 1 */ - u8 ct[2]; /* DWORD 1 */ - u8 port[2]; /* DWORD 1 */ - u8 rsvd1[8]; /* DWORD 1 */ - u8 status[4]; /* DWORD 1 */ - u8 rsvd2[16]; /* DWORD 2 */ - u8 ringid[11]; /* DWORD 2 */ - u8 hash_val[4]; /* DWORD 2 */ - u8 valid; /* DWORD 2 */ - u8 rsvd3[32]; /* DWORD 3 */ -} __packed; -struct ETH_TX_COMPL_AMAP { - u32 dw[4]; -}; - -/* Ethernet Receive Buffer descriptor */ -struct BE_ETH_RX_D_AMAP { - u8 fragpa_hi[32]; /* DWORD 0 */ - u8 fragpa_lo[32]; /* DWORD 1 */ -} __packed; -struct ETH_RX_D_AMAP { - u32 dw[2]; -}; - -/* This is an Ethernet Receive Completion Descriptor */ -struct BE_ETH_RX_COMPL_AMAP { - u8 vlan_tag[16]; /* DWORD 0 */ - u8 pktsize[14]; /* DWORD 0 */ - u8 port; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 err; /* DWORD 1 */ - u8 rsshp; /* DWORD 1 */ - u8 ipf; /* DWORD 1 */ - u8 tcpf; /* DWORD 1 */ - u8 udpf; /* DWORD 1 */ - u8 ipcksm; /* DWORD 1 */ - u8 tcpcksm; /* DWORD 1 */ - u8 udpcksm; /* DWORD 1 */ - u8 macdst[6]; /* DWORD 1 */ - u8 vtp; /* DWORD 1 */ - u8 vtm; /* DWORD 1 */ - u8 fragndx[10]; /* DWORD 1 */ - u8 ct[2]; /* DWORD 1 */ - u8 ipsec; /* DWORD 1 */ - u8 numfrags[3]; /* DWORD 1 */ - u8 rsvd1[31]; /* DWORD 2 */ - u8 valid; /* DWORD 2 */ - u8 rsshash[32]; /* DWORD 3 */ -} __packed; -struct ETH_RX_COMPL_AMAP { - u32 dw[4]; -}; - -#endif /* __host_struct_amap_h__ */ diff --git a/drivers/staging/benet/hwlib.h b/drivers/staging/benet/hwlib.h deleted file mode 100644 index afedf4dc590..00000000000 --- a/drivers/staging/benet/hwlib.h +++ /dev/null @@ -1,830 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#ifndef __hwlib_h__ -#define __hwlib_h__ - -#include -#include -#include -#include - -#include "regmap.h" /* srcgen array map output */ - -#include "asyncmesg.h" -#include "fwcmd_opcodes.h" -#include "post_codes.h" -#include "fwcmd_mcc.h" - -#include "fwcmd_types_bmap.h" -#include "fwcmd_common_bmap.h" -#include "fwcmd_eth_bmap.h" -#include "bestatus.h" -/* - * - * Macros for reading/writing a protection domain or CSR registers - * in BladeEngine. - */ -#define PD_READ(fo, field) ioread32((fo)->db_va + \ - offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8) - -#define PD_WRITE(fo, field, val) iowrite32(val, (fo)->db_va + \ - offsetof(struct BE_PROTECTION_DOMAIN_DBMAP_AMAP, field)/8) - -#define CSR_READ(fo, field) ioread32((fo)->csr_va + \ - offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8) - -#define CSR_WRITE(fo, field, val) iowrite32(val, (fo)->csr_va + \ - offsetof(struct BE_BLADE_ENGINE_CSRMAP_AMAP, field)/8) - -#define PCICFG0_READ(fo, field) ioread32((fo)->pci_va + \ - offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8) - -#define PCICFG0_WRITE(fo, field, val) iowrite32(val, (fo)->pci_va + \ - offsetof(struct BE_PCICFG0_CSRMAP_AMAP, field)/8) - -#define PCICFG1_READ(fo, field) ioread32((fo)->pci_va + \ - offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8) - -#define PCICFG1_WRITE(fo, field, val) iowrite32(val, (fo)->pci_va + \ - offsetof(struct BE_PCICFG1_CSRMAP_AMAP, field)/8) - -#ifdef BE_DEBUG -#define ASSERT(c) BUG_ON(!(c)); -#else -#define ASSERT(c) -#endif - -/* debug levels */ -enum BE_DEBUG_LEVELS { - DL_ALWAYS = 0, /* cannot be masked */ - DL_ERR = 0x1, /* errors that should never happen */ - DL_WARN = 0x2, /* something questionable. - recoverable errors */ - DL_NOTE = 0x4, /* infrequent, important debug info */ - DL_INFO = 0x8, /* debug information */ - DL_VERBOSE = 0x10, /* detailed info, such as buffer traces */ - BE_DL_MIN_VALUE = 0x1, /* this is the min value used */ - BE_DL_MAX_VALUE = 0x80 /* this is the higheset value used */ -} ; - -extern unsigned int trace_level; - -#define TRACE(lm, fmt, args...) { \ - if (trace_level & lm) { \ - printk(KERN_NOTICE "BE: %s:%d \n" fmt, \ - __FILE__ , __LINE__ , ## args); \ - } \ - } - -static inline unsigned int be_trace_set_level(unsigned int level) -{ - unsigned int old_level = trace_level; - trace_level = level; - return old_level; -} - -#define be_trace_get_level() trace_level -/* - * Returns number of pages spanned by the size of data - * starting at the given address. - */ -#define PAGES_SPANNED(_address, _size) \ - ((u32)((((size_t)(_address) & (PAGE_SIZE - 1)) + \ - (_size) + (PAGE_SIZE - 1)) >> PAGE_SHIFT)) -/* Byte offset into the page corresponding to given address */ -#define OFFSET_IN_PAGE(_addr_) ((size_t)(_addr_) & (PAGE_SIZE-1)) - -/* - * circular subtract. - * Returns a - b assuming a circular number system, where a and b are - * in range (0, maxValue-1). If a==b, zero is returned so the - * highest value possible with this subtraction is maxValue-1. - */ -static inline u32 be_subc(u32 a, u32 b, u32 max) -{ - ASSERT(a <= max && b <= max); - ASSERT(max > 0); - return a >= b ? (a - b) : (max - b + a); -} - -static inline u32 be_addc(u32 a, u32 b, u32 max) -{ - ASSERT(a < max); - ASSERT(max > 0); - return (max - a > b) ? (a + b) : (b + a - max); -} - -/* descriptor for a physically contiguous memory used for ring */ -struct ring_desc { - u32 length; /* length in bytes */ - void *va; /* virtual address */ - u64 pa; /* bus address */ -} ; - -/* - * This structure stores information about a ring shared between hardware - * and software. Each ring is allocated by the driver in the uncached - * extension and mapped into BladeEngine's unified table. - */ -struct mp_ring { - u32 pages; /* queue size in pages */ - u32 id; /* queue id assigned by beklib */ - u32 num; /* number of elements in queue */ - u32 cidx; /* consumer index */ - u32 pidx; /* producer index -- not used by most rings */ - u32 itemSize; /* size in bytes of one object */ - - void *va; /* The virtual address of the ring. - This should be last to allow 32 & 64 - bit debugger extensions to work. */ -} ; - -/*----------- amap bit filed get / set macros and functions -----*/ -/* - * Structures defined in the map header files (under fw/amap/) with names - * in the format BE__AMAP are pseudo structures with members - * of type u8. These structures are templates that are used in - * conjuntion with the structures with names in the format - * _AMAP to calculate the bit masks and bit offsets to get or set - * bit fields in structures. The structures _AMAP are arrays - * of 32 bits words and have the correct size. The following macros - * provide convenient ways to get and set the various members - * in the structures without using strucctures with bit fields. - * Always use the macros AMAP_GET_BITS_PTR and AMAP_SET_BITS_PTR - * macros to extract and set various members. - */ - -/* - * Returns the a bit mask for the register that is NOT shifted into location. - * That means return values always look like: 0x1, 0xFF, 0x7FF, etc... - */ -static inline u32 amap_mask(u32 bit_size) -{ - return bit_size == 32 ? 0xFFFFFFFF : (1 << bit_size) - 1; -} - -#define AMAP_BIT_MASK(_struct_, field) \ - amap_mask(AMAP_BIT_SIZE(_struct_, field)) - -/* - * non-optimized set bits function. First clears the bits and then assigns them. - * This does not require knowledge of the particular DWORD you are setting. - * e.g. AMAP_SET_BITS_PTR (struct, field1, &contextMemory, 123); - */ -static inline void -amap_set(void *ptr, u32 dw_offset, u32 mask, u32 offset, u32 value) -{ - u32 *dw = (u32 *)ptr; - *(dw + dw_offset) &= ~(mask << offset); - *(dw + dw_offset) |= (mask & value) << offset; -} - -#define AMAP_SET_BITS_PTR(_struct_, field, _structPtr_, val) \ - amap_set(_structPtr_, AMAP_WORD_OFFSET(_struct_, field),\ - AMAP_BIT_MASK(_struct_, field), \ - AMAP_BIT_OFFSET(_struct_, field), val) -/* - * Non-optimized routine that gets the bits without knowing the correct DWORD. - * e.g. fieldValue = AMAP_GET_BITS_PTR (struct, field1, &contextMemory); - */ -static inline u32 -amap_get(void *ptr, u32 dw_offset, u32 mask, u32 offset) -{ - u32 *dw = (u32 *)ptr; - return mask & (*(dw + dw_offset) >> offset); -} -#define AMAP_GET_BITS_PTR(_struct_, field, _structPtr_) \ - amap_get(_structPtr_, AMAP_WORD_OFFSET(_struct_, field), \ - AMAP_BIT_MASK(_struct_, field), \ - AMAP_BIT_OFFSET(_struct_, field)) - -/* Returns 0-31 representing bit offset within a DWORD of a bitfield. */ -#define AMAP_BIT_OFFSET(_struct_, field) \ - (offsetof(struct BE_ ## _struct_ ## _AMAP, field) % 32) - -/* Returns 0-n representing DWORD offset of bitfield within the structure. */ -#define AMAP_WORD_OFFSET(_struct_, field) \ - (offsetof(struct BE_ ## _struct_ ## _AMAP, field)/32) - -/* Returns size of bitfield in bits. */ -#define AMAP_BIT_SIZE(_struct_, field) \ - sizeof(((struct BE_ ## _struct_ ## _AMAP*)0)->field) - -struct be_mcc_wrb_response_copy { - u16 length; /* bytes in response */ - u16 fwcmd_offset; /* offset within the wrb of the response */ - void *va; /* user's va to copy response into */ - -} ; -typedef void (*mcc_wrb_cqe_callback) (void *context, int status, - struct MCC_WRB_AMAP *optional_wrb); -struct be_mcc_wrb_context { - - mcc_wrb_cqe_callback internal_cb; /* Function to call on - completion */ - void *internal_cb_context; /* Parameter to pass - to completion function */ - - mcc_wrb_cqe_callback cb; /* Function to call on completion */ - void *cb_context; /* Parameter to pass to completion function */ - - int *users_final_status; /* pointer to a local - variable for synchronous - commands */ - struct MCC_WRB_AMAP *wrb; /* pointer to original wrb for embedded - commands only */ - struct list_head next; /* links context structs together in - free list */ - - struct be_mcc_wrb_response_copy copy; /* Optional parameters to copy - embedded response to user's va */ - -#if defined(BE_DEBUG) - u16 subsystem, opcode; /* Track this FWCMD for debug builds. */ - struct MCC_WRB_AMAP *ring_wrb; - u32 consumed_count; -#endif -} ; - -/* - Represents a function object for network or storage. This - is used to manage per-function resources like MCC CQs, etc. -*/ -struct be_function_object { - - u32 magic; /*!< magic for detecting memory corruption. */ - - /* PCI BAR mapped addresses */ - u8 __iomem *csr_va; /* CSR */ - u8 __iomem *db_va; /* Door Bell */ - u8 __iomem *pci_va; /* PCI config space */ - u32 emulate; /* if set, MPU is not available. - Emulate everything. */ - u32 pend_queue_driving; /* if set, drive the queued WRBs - after releasing the WRB lock */ - - spinlock_t post_lock; /* lock for verifying one thread posting wrbs */ - spinlock_t cq_lock; /* lock for verifying one thread - processing cq */ - spinlock_t mcc_context_lock; /* lock for protecting mcc - context free list */ - unsigned long post_irq; - unsigned long cq_irq; - - u32 type; - u32 pci_function_number; - - struct be_mcc_object *mcc; /* mcc rings. */ - - struct { - struct MCC_MAILBOX_AMAP *va; /* VA to the mailbox */ - u64 pa; /* PA to the mailbox */ - u32 length; /* byte length of mailbox */ - - /* One default context struct used for posting at - * least one MCC_WRB - */ - struct be_mcc_wrb_context default_context; - bool default_context_allocated; - } mailbox; - - struct { - - /* Wake on lans configured. */ - u32 wol_bitmask; /* bits 0,1,2,3 are set if - corresponding index is enabled */ - } config; - - - struct BE_FIRMWARE_CONFIG fw_config; -} ; - -/* - Represents an Event Queue -*/ -struct be_eq_object { - u32 magic; - atomic_t ref_count; - - struct be_function_object *parent_function; - - struct list_head eq_list; - struct list_head cq_list_head; - - u32 eq_id; - void *cb_context; - -} ; - -/* - Manages a completion queue -*/ -struct be_cq_object { - u32 magic; - atomic_t ref_count; - - struct be_function_object *parent_function; - struct be_eq_object *eq_object; - - struct list_head cq_list; - struct list_head cqlist_for_eq; - - void *va; - u32 num_entries; - - void *cb_context; - - u32 cq_id; - -} ; - -/* - Manages an ethernet send queue -*/ -struct be_ethsq_object { - u32 magic; - - struct list_head list; - - struct be_function_object *parent_function; - struct be_cq_object *cq_object; - u32 bid; - -} ; - -/* -@brief - Manages an ethernet receive queue -*/ -struct be_ethrq_object { - u32 magic; - struct list_head list; - struct be_function_object *parent_function; - u32 rid; - struct be_cq_object *cq_object; - struct be_cq_object *rss_cq_object[4]; - -} ; - -/* - Manages an MCC -*/ -typedef void (*mcc_async_event_callback) (void *context, u32 event_code, - void *event); -struct be_mcc_object { - u32 magic; - - struct be_function_object *parent_function; - struct list_head mcc_list; - - struct be_cq_object *cq_object; - - /* Async event callback for MCC CQ. */ - mcc_async_event_callback async_cb; - void *async_context; - - struct { - struct be_mcc_wrb_context *base; - u32 num; - struct list_head list_head; - } wrb_context; - - struct { - struct ring_desc *rd; - struct mp_ring ring; - } sq; - - struct { - struct mp_ring ring; - } cq; - - u32 processing; /* flag indicating that one thread - is processing CQ */ - u32 rearm; /* doorbell rearm setting to make - sure the active processing thread */ - /* rearms the CQ if any of the threads requested it. */ - - struct list_head backlog; - u32 backlog_length; - u32 driving_backlog; - u32 consumed_index; - -} ; - - -/* Queue context header -- the required software information for - * queueing a WRB. - */ -struct be_queue_driver_context { - mcc_wrb_cqe_callback internal_cb; /* Function to call on - completion */ - void *internal_cb_context; /* Parameter to pass - to completion function */ - - mcc_wrb_cqe_callback cb; /* Function to call on completion */ - void *cb_context; /* Parameter to pass to completion function */ - - struct be_mcc_wrb_response_copy copy; /* Optional parameters to copy - embedded response to user's va */ - void *optional_fwcmd_va; - struct list_head list; - u32 bytes; -} ; - -/* - * Common MCC WRB header that all commands require. - */ -struct be_mcc_wrb_header { - u8 rsvd[offsetof(struct BE_MCC_WRB_AMAP, payload)/8]; -} ; - -/* - * All non embedded commands supported by hwlib functions only allow - * 1 SGE. This queue context handles them all. - */ -struct be_nonembedded_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct MCC_SGE_AMAP sge[1]; -} ; - -/* - * ------------------------------------------------------------------------ - * This section contains the specific queue struct for each command. - * The user could always provide a be_generic_q_ctxt but this is a - * rather large struct. By using the specific struct, memory consumption - * can be reduced. - * ------------------------------------------------------------------------ - */ - -struct be_link_status_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_LINK_STATUS_QUERY fwcmd; -} ; - -struct be_multicast_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_MULTICAST_SET fwcmd; -} ; - - -struct be_vlan_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_VLAN_CONFIG fwcmd; -} ; - -struct be_promiscuous_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_ETH_PROMISCUOUS fwcmd; -} ; - -struct be_force_failover_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_FORCE_FAILOVER fwcmd; -} ; - - -struct be_rxf_filter_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_NTWK_RX_FILTER fwcmd; -} ; - -struct be_eq_modify_delay_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct FWCMD_COMMON_MODIFY_EQ_DELAY fwcmd; -} ; - -/* - * The generic context is the largest size that would be required. - * It is the software context plus an entire WRB. - */ -struct be_generic_q_ctxt { - struct be_queue_driver_context context; - struct be_mcc_wrb_header wrb_header; - struct MCC_WRB_PAYLOAD_AMAP payload; -} ; - -/* - * Types for the BE_QUEUE_CONTEXT object. - */ -#define BE_QUEUE_INVALID (0) -#define BE_QUEUE_LINK_STATUS (0xA006) -#define BE_QUEUE_ETH_STATS (0xA007) -#define BE_QUEUE_TPM_STATS (0xA008) -#define BE_QUEUE_TCP_STATS (0xA009) -#define BE_QUEUE_MULTICAST (0xA00A) -#define BE_QUEUE_VLAN (0xA00B) -#define BE_QUEUE_RSS (0xA00C) -#define BE_QUEUE_FORCE_FAILOVER (0xA00D) -#define BE_QUEUE_PROMISCUOUS (0xA00E) -#define BE_QUEUE_WAKE_ON_LAN (0xA00F) -#define BE_QUEUE_NOP (0xA010) - -/* --- BE_FUNCTION_ENUM --- */ -#define BE_FUNCTION_TYPE_ISCSI (0) -#define BE_FUNCTION_TYPE_NETWORK (1) -#define BE_FUNCTION_TYPE_ARM (2) - -/* --- BE_ETH_TX_RING_TYPE_ENUM --- */ -#define BE_ETH_TX_RING_TYPE_FORWARDING (1) /* Ether ring for forwarding */ -#define BE_ETH_TX_RING_TYPE_STANDARD (2) /* Ether ring for sending */ - /* network packets. */ -#define BE_ETH_TX_RING_TYPE_BOUND (3) /* Ethernet ring for sending */ - /* network packets, bound */ - /* to a physical port. */ -/* - * ---------------------------------------------------------------------- - * API MACROS - * ---------------------------------------------------------------------- - */ -#define BE_FWCMD_NAME(_short_name_) struct FWCMD_##_short_name_ -#define BE_OPCODE_NAME(_short_name_) OPCODE_##_short_name_ -#define BE_SUBSYSTEM_NAME(_short_name_) SUBSYSTEM_##_short_name_ - - -#define BE_PREPARE_EMBEDDED_FWCMD(_pfob_, _wrb_, _short_name_) \ - ((BE_FWCMD_NAME(_short_name_) *) \ - be_function_prepare_embedded_fwcmd(_pfob_, _wrb_, \ - sizeof(BE_FWCMD_NAME(_short_name_)), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \ - BE_OPCODE_NAME(_short_name_), \ - BE_SUBSYSTEM_NAME(_short_name_))); - -#define BE_PREPARE_NONEMBEDDED_FWCMD(_pfob_, _wrb_, _iva_, _ipa_, _short_name_)\ - ((BE_FWCMD_NAME(_short_name_) *) \ - be_function_prepare_nonembedded_fwcmd(_pfob_, _wrb_, (_iva_), (_ipa_), \ - sizeof(BE_FWCMD_NAME(_short_name_)), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.request), \ - FIELD_SIZEOF(BE_FWCMD_NAME(_short_name_), params.response), \ - BE_OPCODE_NAME(_short_name_), \ - BE_SUBSYSTEM_NAME(_short_name_))); - -int be_function_object_create(u8 __iomem *csr_va, u8 __iomem *db_va, - u8 __iomem *pci_va, u32 function_type, struct ring_desc *mailbox_rd, - struct be_function_object *pfob); - -int be_function_object_destroy(struct be_function_object *pfob); -int be_function_cleanup(struct be_function_object *pfob); - - -int be_function_get_fw_version(struct be_function_object *pfob, - struct FWCMD_COMMON_GET_FW_VERSION_RESPONSE_PAYLOAD *fw_version, - mcc_wrb_cqe_callback cb, void *cb_context); - - -int be_eq_modify_delay(struct be_function_object *pfob, - u32 num_eq, struct be_eq_object **eq_array, - u32 *eq_delay_array, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_eq_modify_delay_q_ctxt *q_ctxt); - - - -int be_eq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 eqe_size, u32 num_entries, - u32 watermark, u32 timer_delay, struct be_eq_object *eq_object); - -int be_eq_destroy(struct be_eq_object *eq); - -int be_cq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - bool solicited_eventable, bool no_delay, - u32 wm_thresh, struct be_eq_object *eq_object, - struct be_cq_object *cq_object); - -int be_cq_destroy(struct be_cq_object *cq); - -int be_mcc_ring_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - struct be_mcc_wrb_context *context_array, - u32 num_context_entries, - struct be_cq_object *cq, struct be_mcc_object *mcc); -int be_mcc_ring_destroy(struct be_mcc_object *mcc_object); - -int be_mcc_process_cq(struct be_mcc_object *mcc_object, bool rearm); - -int be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object, - mcc_async_event_callback cb, void *cb_context); - -int be_pci_soft_reset(struct be_function_object *pfob); - - -int be_drive_POST(struct be_function_object *pfob); - - -int be_eth_sq_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length_in_bytes, - u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_ethsq_object *eth_sq); - -struct be_eth_sq_parameters { - u32 port; - u32 rsvd0[2]; -} ; - -int be_eth_sq_create_ex(struct be_function_object *pfob, - struct ring_desc *rd, u32 length_in_bytes, - u32 type, u32 ulp, struct be_cq_object *cq_object, - struct be_eth_sq_parameters *ex_parameters, - struct be_ethsq_object *eth_sq); -int be_eth_sq_destroy(struct be_ethsq_object *eth_sq); - -int be_eth_set_flow_control(struct be_function_object *pfob, - bool txfc_enable, bool rxfc_enable); - -int be_eth_get_flow_control(struct be_function_object *pfob, - bool *txfc_enable, bool *rxfc_enable); -int be_eth_set_qos(struct be_function_object *pfob, u32 max_bps, u32 max_pps); - -int be_eth_get_qos(struct be_function_object *pfob, u32 *max_bps, u32 *max_pps); - -int be_eth_set_frame_size(struct be_function_object *pfob, - u32 *tx_frame_size, u32 *rx_frame_size); - -int be_eth_rq_create(struct be_function_object *pfob, - struct ring_desc *rd, struct be_cq_object *cq_object, - struct be_cq_object *bcmc_cq_object, - struct be_ethrq_object *eth_rq); - -int be_eth_rq_destroy(struct be_ethrq_object *eth_rq); - -int be_eth_rq_destroy_options(struct be_ethrq_object *eth_rq, bool flush, - mcc_wrb_cqe_callback cb, void *cb_context); -int be_eth_rq_set_frag_size(struct be_function_object *pfob, - u32 new_frag_size_bytes, u32 *actual_frag_size_bytes); -int be_eth_rq_get_frag_size(struct be_function_object *pfob, - u32 *frag_size_bytes); - -void *be_function_prepare_embedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - u32 payload_length, u32 request_length, - u32 response_length, u32 opcode, u32 subsystem); -void *be_function_prepare_nonembedded_fwcmd(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, void *fwcmd_header_va, u64 fwcmd_header_pa, - u32 payload_length, u32 request_length, u32 response_length, - u32 opcode, u32 subsystem); - - -struct MCC_WRB_AMAP * -be_function_peek_mcc_wrb(struct be_function_object *pfob); - -int be_rxf_mac_address_read_write(struct be_function_object *pfob, - bool port1, bool mac1, bool mgmt, - bool write, bool permanent, u8 *mac_address, - mcc_wrb_cqe_callback cb, - void *cb_context); - -int be_rxf_multicast_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u8 *mac_table, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_multicast_q_ctxt *q_ctxt); - -int be_rxf_vlan_config(struct be_function_object *pfob, - bool promiscuous, u32 num, u16 *vlan_tag_array, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_vlan_q_ctxt *q_ctxt); - - -int be_rxf_link_status(struct be_function_object *pfob, - struct BE_LINK_STATUS *link_status, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_link_status_q_ctxt *q_ctxt); - - -int be_rxf_query_eth_statistics(struct be_function_object *pfob, - struct FWCMD_ETH_GET_STATISTICS *va_for_fwcmd, - u64 pa_for_fwcmd, mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_nonembedded_q_ctxt *q_ctxt); - -int be_rxf_promiscuous(struct be_function_object *pfob, - bool enable_port0, bool enable_port1, - mcc_wrb_cqe_callback cb, void *cb_context, - struct be_promiscuous_q_ctxt *q_ctxt); - - -int be_rxf_filter_config(struct be_function_object *pfob, - struct NTWK_RX_FILTER_SETTINGS *settings, - mcc_wrb_cqe_callback cb, - void *cb_context, - struct be_rxf_filter_q_ctxt *q_ctxt); - -/* - * ------------------------------------------------------ - * internal functions used by hwlib - * ------------------------------------------------------ - */ - - -int be_function_ring_destroy(struct be_function_object *pfob, - u32 id, u32 ring_type, mcc_wrb_cqe_callback cb, - void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_callback_context); - -int be_function_post_mcc_wrb(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, - struct be_generic_q_ctxt *q_ctxt, - mcc_wrb_cqe_callback cb, void *cb_context, - mcc_wrb_cqe_callback internal_cb, - void *internal_cb_context, void *optional_fwcmd_va, - struct be_mcc_wrb_response_copy *response_copy); - -int be_function_queue_mcc_wrb(struct be_function_object *pfob, - struct be_generic_q_ctxt *q_ctxt); - -/* - * ------------------------------------------------------ - * MCC QUEUE - * ------------------------------------------------------ - */ - -int be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *rd); - - -struct MCC_WRB_AMAP * -_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue); - -struct be_mcc_wrb_context * -_be_mcc_allocate_wrb_context(struct be_function_object *pfob); - -void _be_mcc_free_wrb_context(struct be_function_object *pfob, - struct be_mcc_wrb_context *context); - -int _be_mpu_post_wrb_mailbox(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context); - -int _be_mpu_post_wrb_ring(struct be_mcc_object *mcc, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context); - -void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc); - - -/* - * ------------------------------------------------------ - * Ring Sizes - * ------------------------------------------------------ - */ -static inline u32 be_ring_encoding_to_length(u32 encoding, u32 object_size) -{ - - ASSERT(encoding != 1); /* 1 is rsvd */ - ASSERT(encoding < 16); - ASSERT(object_size > 0); - - if (encoding == 0) /* 32k deep */ - encoding = 16; - - return (1 << (encoding - 1)) * object_size; -} - -static inline -u32 be_ring_length_to_encoding(u32 length_in_bytes, u32 object_size) -{ - - u32 count, encoding; - - ASSERT(object_size > 0); - ASSERT(length_in_bytes % object_size == 0); - - count = length_in_bytes / object_size; - - ASSERT(count > 1); - ASSERT(count <= 32 * 1024); - ASSERT(length_in_bytes <= 8 * PAGE_SIZE); /* max ring size in UT */ - - encoding = __ilog2_u32(count) + 1; - - if (encoding == 16) - encoding = 0; /* 32k deep */ - - return encoding; -} - -void be_rd_to_pa_list(struct ring_desc *rd, struct PHYS_ADDR *pa_list, - u32 max_num); -#endif /* __hwlib_h__ */ diff --git a/drivers/staging/benet/mpu.c b/drivers/staging/benet/mpu.c deleted file mode 100644 index 269cc11d305..00000000000 --- a/drivers/staging/benet/mpu.c +++ /dev/null @@ -1,1364 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -#include -#include "hwlib.h" -#include "bestatus.h" - -static -inline void mp_ring_create(struct mp_ring *ring, u32 num, u32 size, void *va) -{ - ASSERT(ring); - memset(ring, 0, sizeof(struct mp_ring)); - ring->num = num; - ring->pages = DIV_ROUND_UP(num * size, PAGE_SIZE); - ring->itemSize = size; - ring->va = va; -} - -/* - * ----------------------------------------------------------------------- - * Interface for 2 index rings. i.e. consumer/producer rings - * -------------------------------------------------------------------------- - */ - -/* Returns number items pending on ring. */ -static inline u32 mp_ring_num_pending(struct mp_ring *ring) -{ - ASSERT(ring); - if (ring->num == 0) - return 0; - return be_subc(ring->pidx, ring->cidx, ring->num); -} - -/* Returns number items free on ring. */ -static inline u32 mp_ring_num_empty(struct mp_ring *ring) -{ - ASSERT(ring); - return ring->num - 1 - mp_ring_num_pending(ring); -} - -/* Consume 1 item */ -static inline void mp_ring_consume(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->pidx != ring->cidx); - - ring->cidx = be_addc(ring->cidx, 1, ring->num); -} - -/* Produce 1 item */ -static inline void mp_ring_produce(struct mp_ring *ring) -{ - ASSERT(ring); - ring->pidx = be_addc(ring->pidx, 1, ring->num); -} - -/* Consume count items */ -static inline void mp_ring_consume_multiple(struct mp_ring *ring, u32 count) -{ - ASSERT(ring); - ASSERT(mp_ring_num_pending(ring) >= count); - ring->cidx = be_addc(ring->cidx, count, ring->num); -} - -static inline void *mp_ring_item(struct mp_ring *ring, u32 index) -{ - ASSERT(ring); - ASSERT(index < ring->num); - ASSERT(ring->itemSize > 0); - return (u8 *) ring->va + index * ring->itemSize; -} - -/* Ptr to produce item */ -static inline void *mp_ring_producer_ptr(struct mp_ring *ring) -{ - ASSERT(ring); - return mp_ring_item(ring, ring->pidx); -} - -/* - * Returns a pointer to the current location in the ring. - * This is used for rings with 1 index. - */ -static inline void *mp_ring_current(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->pidx == 0); /* not used */ - - return mp_ring_item(ring, ring->cidx); -} - -/* - * Increment index for rings with only 1 index. - * This is used for rings with 1 index. - */ -static inline void *mp_ring_next(struct mp_ring *ring) -{ - ASSERT(ring); - ASSERT(ring->num > 0); - ASSERT(ring->pidx == 0); /* not used */ - - ring->cidx = be_addc(ring->cidx, 1, ring->num); - return mp_ring_current(ring); -} - -/* - This routine waits for a previously posted mailbox WRB to be completed. - Specifically it waits for the mailbox to say that it's ready to accept - more data by setting the LSB of the mailbox pd register to 1. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL -*/ -static void be_mcc_mailbox_wait(struct be_function_object *pfob) -{ - struct MPU_MAILBOX_DB_AMAP mailbox_db; - u32 i = 0; - u32 ready; - - if (pfob->emulate) { - /* No waiting for mailbox in emulated mode. */ - return; - } - - mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db); - ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db); - - while (ready == false) { - if ((++i & 0x3FFFF) == 0) { - TRACE(DL_WARN, "Waiting for mailbox ready - %dk polls", - i / 1000); - } - udelay(1); - mailbox_db.dw[0] = PD_READ(pfob, mcc_bootstrap_db); - ready = AMAP_GET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db); - } -} - -/* - This routine tells the MCC mailbox that there is data to processed - in the mailbox. It does this by setting the physical address for the - mailbox location and clearing the LSB. This routine returns immediately - and does not wait for the WRB to be processed. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL - -*/ -static void be_mcc_mailbox_notify(struct be_function_object *pfob) -{ - struct MPU_MAILBOX_DB_AMAP mailbox_db; - u32 pa; - - ASSERT(pfob->mailbox.pa); - ASSERT(pfob->mailbox.va); - - /* If emulated, do not ring the mailbox */ - if (pfob->emulate) { - TRACE(DL_WARN, "MPU disabled. Skipping mailbox notify."); - return; - } - - /* form the higher bits in the address */ - mailbox_db.dw[0] = 0; /* init */ - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 1); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0); - - /* bits 34 to 63 */ - pa = (u32) (pfob->mailbox.pa >> 34); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa); - - /* Wait for the MPU to be ready */ - be_mcc_mailbox_wait(pfob); - - /* Ring doorbell 1st time */ - PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]); - - /* Wait for 1st write to be acknowledged. */ - be_mcc_mailbox_wait(pfob); - - /* lower bits 30 bits from 4th bit (bits 4 to 33)*/ - pa = (u32) (pfob->mailbox.pa >> 4) & 0x3FFFFFFF; - - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, hi, &mailbox_db, 0); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, ready, &mailbox_db, 0); - AMAP_SET_BITS_PTR(MPU_MAILBOX_DB, address, &mailbox_db, pa); - - /* Ring doorbell 2nd time */ - PD_WRITE(pfob, mcc_bootstrap_db, mailbox_db.dw[0]); -} - -/* - This routine tells the MCC mailbox that there is data to processed - in the mailbox. It does this by setting the physical address for the - mailbox location and clearing the LSB. This routine spins until the - MPU writes a 1 into the LSB indicating that the data has been received - and is ready to be processed. - - pcontroller - The function object to post this data to - - IRQL < DISPATCH_LEVEL -*/ -static void -be_mcc_mailbox_notify_and_wait(struct be_function_object *pfob) -{ - /* - * Notify it - */ - be_mcc_mailbox_notify(pfob); - /* - * Now wait for completion of WRB - */ - be_mcc_mailbox_wait(pfob); -} - -void -be_mcc_process_cqe(struct be_function_object *pfob, - struct MCC_CQ_ENTRY_AMAP *cqe) -{ - struct be_mcc_wrb_context *wrb_context = NULL; - u32 offset, status; - u8 *p; - - ASSERT(cqe); - /* - * A command completed. Commands complete out-of-order. - * Determine which command completed from the TAG. - */ - offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8; - p = (u8 *) cqe + offset; - wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p); - ASSERT(wrb_context); - - /* - * Perform a response copy if requested. - * Only copy data if the FWCMD is successful. - */ - status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, cqe); - if (status == MGMT_STATUS_SUCCESS && wrb_context->copy.length > 0) { - ASSERT(wrb_context->wrb); - ASSERT(wrb_context->copy.va); - p = (u8 *)wrb_context->wrb + - offsetof(struct BE_MCC_WRB_AMAP, payload)/8; - memcpy(wrb_context->copy.va, - (u8 *)p + wrb_context->copy.fwcmd_offset, - wrb_context->copy.length); - } - - if (status) - status = BE_NOT_OK; - /* internal callback */ - if (wrb_context->internal_cb) { - wrb_context->internal_cb(wrb_context->internal_cb_context, - status, wrb_context->wrb); - } - - /* callback */ - if (wrb_context->cb) { - wrb_context->cb(wrb_context->cb_context, - status, wrb_context->wrb); - } - /* Free the context structure */ - _be_mcc_free_wrb_context(pfob, wrb_context); -} - -void be_drive_mcc_wrb_queue(struct be_mcc_object *mcc) -{ - struct be_function_object *pfob = NULL; - int status = BE_PENDING; - struct be_generic_q_ctxt *q_ctxt; - struct MCC_WRB_AMAP *wrb; - struct MCC_WRB_AMAP *queue_wrb; - u32 length, payload_length, sge_count, embedded; - unsigned long irql; - - BUILD_BUG_ON((sizeof(struct be_generic_q_ctxt) < - sizeof(struct be_queue_driver_context) + - sizeof(struct MCC_WRB_AMAP))); - pfob = mcc->parent_function; - - spin_lock_irqsave(&pfob->post_lock, irql); - - if (mcc->driving_backlog) { - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return; - } - /* Acquire the flag to limit 1 thread to redrive posts. */ - mcc->driving_backlog = 1; - - while (!list_empty(&mcc->backlog)) { - wrb = _be_mpu_peek_ring_wrb(mcc, true); /* Driving the queue */ - if (!wrb) - break; /* No space in the ring yet. */ - /* Get the next queued entry to process. */ - q_ctxt = list_first_entry(&mcc->backlog, - struct be_generic_q_ctxt, context.list); - list_del(&q_ctxt->context.list); - pfob->mcc->backlog_length--; - /* - * Compute the required length of the WRB. - * Since the queue element may be smaller than - * the complete WRB, copy only the required number of bytes. - */ - queue_wrb = (struct MCC_WRB_AMAP *) &q_ctxt->wrb_header; - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, queue_wrb); - if (embedded) { - payload_length = AMAP_GET_BITS_PTR(MCC_WRB, - payload_length, queue_wrb); - length = sizeof(struct be_mcc_wrb_header) + - payload_length; - } else { - sge_count = AMAP_GET_BITS_PTR(MCC_WRB, sge_count, - queue_wrb); - ASSERT(sge_count == 1); /* only 1 frag. */ - length = sizeof(struct be_mcc_wrb_header) + - sge_count * sizeof(struct MCC_SGE_AMAP); - } - - /* - * Truncate the length based on the size of the - * queue element. Some elements that have output parameters - * can be smaller than the payload_length field would - * indicate. We really only need to copy the request - * parameters, not the response. - */ - length = min(length, (u32) (q_ctxt->context.bytes - - offsetof(struct be_generic_q_ctxt, wrb_header))); - - /* Copy the queue element WRB into the ring. */ - memcpy(wrb, &q_ctxt->wrb_header, length); - - /* Post the wrb. This should not fail assuming we have - * enough context structs. */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, - q_ctxt->context.cb, q_ctxt->context.cb_context, - q_ctxt->context.internal_cb, - q_ctxt->context.internal_cb_context, - q_ctxt->context.optional_fwcmd_va, - &q_ctxt->context.copy); - - if (status == BE_SUCCESS) { - /* - * Synchronous completion. Since it was queued, - * we will invoke the callback. - * To the user, this is an asynchronous request. - */ - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - - ASSERT(q_ctxt->context.cb); - - q_ctxt->context.cb( - q_ctxt->context.cb_context, - BE_SUCCESS, NULL); - - spin_lock_irqsave(&pfob->post_lock, irql); - - } else if (status != BE_PENDING) { - /* - * Another resource failed. Should never happen - * if we have sufficient MCC_WRB_CONTEXT structs. - * Return to head of the queue. - */ - TRACE(DL_WARN, "Failed to post a queued WRB. 0x%x", - status); - list_add(&q_ctxt->context.list, &mcc->backlog); - pfob->mcc->backlog_length++; - break; - } - } - - /* Free the flag to limit 1 thread to redrive posts. */ - mcc->driving_backlog = 0; - spin_unlock_irqrestore(&pfob->post_lock, irql); -} - -/* This function asserts that the WRB was consumed in order. */ -#ifdef BE_DEBUG -u32 be_mcc_wrb_consumed_in_order(struct be_mcc_object *mcc, - struct MCC_CQ_ENTRY_AMAP *cqe) -{ - struct be_mcc_wrb_context *wrb_context = NULL; - u32 wrb_index; - u32 wrb_consumed_in_order; - u32 offset; - u8 *p; - - ASSERT(cqe); - /* - * A command completed. Commands complete out-of-order. - * Determine which command completed from the TAG. - */ - offset = offsetof(struct BE_MCC_CQ_ENTRY_AMAP, mcc_tag)/8; - p = (u8 *) cqe + offset; - wrb_context = (struct be_mcc_wrb_context *)(void *)(size_t)(*(u64 *)p); - - ASSERT(wrb_context); - - wrb_index = (u32) (((u64)(size_t)wrb_context->ring_wrb - - (u64)(size_t)mcc->sq.ring.va) / sizeof(struct MCC_WRB_AMAP)); - - ASSERT(wrb_index < mcc->sq.ring.num); - - wrb_consumed_in_order = (u32) (wrb_index == mcc->consumed_index); - mcc->consumed_index = be_addc(mcc->consumed_index, 1, mcc->sq.ring.num); - return wrb_consumed_in_order; -} -#endif - -int be_mcc_process_cq(struct be_mcc_object *mcc, bool rearm) -{ - struct be_function_object *pfob = NULL; - struct MCC_CQ_ENTRY_AMAP *cqe; - struct CQ_DB_AMAP db; - struct mp_ring *cq_ring = &mcc->cq.ring; - struct mp_ring *mp_ring = &mcc->sq.ring; - u32 num_processed = 0; - u32 consumed = 0, valid, completed, cqe_consumed, async_event; - - pfob = mcc->parent_function; - - spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq); - - /* - * Verify that only one thread is processing the CQ at once. - * We cannot hold the lock while processing the CQ due to - * the callbacks into the OS. Therefore, this flag is used - * to control it. If any of the threads want to - * rearm the CQ, we need to honor that. - */ - if (mcc->processing != 0) { - mcc->rearm = mcc->rearm || rearm; - goto Error; - } else { - mcc->processing = 1; /* lock processing for this thread. */ - mcc->rearm = rearm; /* set our rearm setting */ - } - - spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq); - - cqe = mp_ring_current(cq_ring); - valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe); - while (valid) { - - if (num_processed >= 8) { - /* coalesce doorbells, but free space in cq - * ring while processing. */ - db.dw[0] = 0; /* clear */ - AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, event, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db, - num_processed); - num_processed = 0; - - PD_WRITE(pfob, cq_db, db.dw[0]); - } - - async_event = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, async_event, cqe); - if (async_event) { - /* This is an asynchronous event. */ - struct ASYNC_EVENT_TRAILER_AMAP *async_trailer = - (struct ASYNC_EVENT_TRAILER_AMAP *) - ((u8 *) cqe + sizeof(struct MCC_CQ_ENTRY_AMAP) - - sizeof(struct ASYNC_EVENT_TRAILER_AMAP)); - u32 event_code; - async_event = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - async_event, async_trailer); - ASSERT(async_event == 1); - - - valid = AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - valid, async_trailer); - ASSERT(valid == 1); - - /* Call the async event handler if it is installed. */ - if (mcc->async_cb) { - event_code = - AMAP_GET_BITS_PTR(ASYNC_EVENT_TRAILER, - event_code, async_trailer); - mcc->async_cb(mcc->async_context, - (u32) event_code, (void *) cqe); - } - - } else { - /* This is a completion entry. */ - - /* No vm forwarding in this driver. */ - - cqe_consumed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, - consumed, cqe); - if (cqe_consumed) { - /* - * A command on the MCC ring was consumed. - * Update the consumer index. - * These occur in order. - */ - ASSERT(be_mcc_wrb_consumed_in_order(mcc, cqe)); - consumed++; - } - - completed = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, - completed, cqe); - if (completed) { - /* A command completed. Use tag to - * determine which command. */ - be_mcc_process_cqe(pfob, cqe); - } - } - - /* Reset the CQE */ - AMAP_SET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe, false); - num_processed++; - - /* Update our tracking for the CQ ring. */ - cqe = mp_ring_next(cq_ring); - valid = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, valid, cqe); - } - - TRACE(DL_INFO, "num_processed:0x%x, and consumed:0x%x", - num_processed, consumed); - /* - * Grab the CQ lock to synchronize the "rearm" setting for - * the doorbell, and for clearing the "processing" flag. - */ - spin_lock_irqsave(&pfob->cq_lock, pfob->cq_irq); - - /* - * Rearm the cq. This is done based on the global mcc->rearm - * flag which combines the rearm parameter from the current - * call to process_cq and any other threads - * that tried to process the CQ while this one was active. - * This handles the situation where a sync. fwcmd was processing - * the CQ while the interrupt/dpc tries to process it. - * The sync process gets to continue -- but it is now - * responsible for the rearming. - */ - if (num_processed > 0 || mcc->rearm == true) { - db.dw[0] = 0; /* clear */ - AMAP_SET_BITS_PTR(CQ_DB, qid, &db, cq_ring->id); - AMAP_SET_BITS_PTR(CQ_DB, rearm, &db, mcc->rearm); - AMAP_SET_BITS_PTR(CQ_DB, event, &db, false); - AMAP_SET_BITS_PTR(CQ_DB, num_popped, &db, num_processed); - - PD_WRITE(pfob, cq_db, db.dw[0]); - } - /* - * Update the consumer index after ringing the CQ doorbell. - * We don't want another thread to post more WRBs before we - * have CQ space available. - */ - mp_ring_consume_multiple(mp_ring, consumed); - - /* Clear the processing flag. */ - mcc->processing = 0; - -Error: - spin_unlock_irqrestore(&pfob->cq_lock, pfob->cq_irq); - /* - * Use the local variable to detect if the current thread - * holds the WRB post lock. If rearm is false, this is - * either a synchronous command, or the upper layer driver is polling - * from a thread. We do not drive the queue from that - * context since the driver may hold the - * wrb post lock already. - */ - if (rearm) - be_drive_mcc_wrb_queue(mcc); - else - pfob->pend_queue_driving = 1; - - return BE_SUCCESS; -} - -/* - *============================================================================ - * P U B L I C R O U T I N E S - *============================================================================ - */ - -/* - This routine creates an MCC object. This object contains an MCC send queue - and a CQ private to the MCC. - - pcontroller - Handle to a function object - - EqObject - EQ object that will be used to dispatch this MCC - - ppMccObject - Pointer to an internal Mcc Object returned. - - Returns BE_SUCCESS if successfull,, otherwise a useful error code - is returned. - - IRQL < DISPATCH_LEVEL - -*/ -int -be_mcc_ring_create(struct be_function_object *pfob, - struct ring_desc *rd, u32 length, - struct be_mcc_wrb_context *context_array, - u32 num_context_entries, - struct be_cq_object *cq, struct be_mcc_object *mcc) -{ - int status = 0; - - struct FWCMD_COMMON_MCC_CREATE *fwcmd = NULL; - struct MCC_WRB_AMAP *wrb = NULL; - u32 num_entries_encoded, n, i; - void *va = NULL; - unsigned long irql; - - if (length < sizeof(struct MCC_WRB_AMAP) * 2) { - TRACE(DL_ERR, "Invalid MCC ring length:%d", length); - return BE_NOT_OK; - } - /* - * Reduce the actual ring size to be less than the number - * of context entries. This ensures that we run out of - * ring WRBs first so the queuing works correctly. We never - * queue based on context structs. - */ - if (num_context_entries + 1 < - length / sizeof(struct MCC_WRB_AMAP) - 1) { - - u32 max_length = - (num_context_entries + 2) * sizeof(struct MCC_WRB_AMAP); - - if (is_power_of_2(max_length)) - length = __roundup_pow_of_two(max_length+1) / 2; - else - length = __roundup_pow_of_two(max_length) / 2; - - ASSERT(length <= max_length); - - TRACE(DL_WARN, - "MCC ring length reduced based on context entries." - " length:%d wrbs:%d context_entries:%d", length, - (int) (length / sizeof(struct MCC_WRB_AMAP)), - num_context_entries); - } - - spin_lock_irqsave(&pfob->post_lock, irql); - - num_entries_encoded = - be_ring_length_to_encoding(length, sizeof(struct MCC_WRB_AMAP)); - - /* Init MCC object. */ - memset(mcc, 0, sizeof(*mcc)); - mcc->parent_function = pfob; - mcc->cq_object = cq; - - INIT_LIST_HEAD(&mcc->backlog); - - wrb = be_function_peek_mcc_wrb(pfob); - if (!wrb) { - ASSERT(wrb); - TRACE(DL_ERR, "No free MCC WRBs in create EQ."); - status = BE_STATUS_NO_MCC_WRB; - goto error; - } - /* Prepares an embedded fwcmd, including request/response sizes. */ - fwcmd = BE_PREPARE_EMBEDDED_FWCMD(pfob, wrb, COMMON_MCC_CREATE); - - fwcmd->params.request.num_pages = DIV_ROUND_UP(length, PAGE_SIZE); - /* - * Program MCC ring context - */ - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, pdid, - &fwcmd->params.request.context, 0); - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, invalid, - &fwcmd->params.request.context, false); - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, ring_size, - &fwcmd->params.request.context, num_entries_encoded); - - n = cq->cq_id; - AMAP_SET_BITS_PTR(MCC_RING_CONTEXT, - cq_id, &fwcmd->params.request.context, n); - be_rd_to_pa_list(rd, fwcmd->params.request.pages, - ARRAY_SIZE(fwcmd->params.request.pages)); - /* Post the f/w command */ - status = be_function_post_mcc_wrb(pfob, wrb, NULL, NULL, NULL, - NULL, NULL, fwcmd, NULL); - if (status != BE_SUCCESS) { - TRACE(DL_ERR, "MCC to create CQ failed."); - goto error; - } - /* - * Create a linked list of context structures - */ - mcc->wrb_context.base = context_array; - mcc->wrb_context.num = num_context_entries; - INIT_LIST_HEAD(&mcc->wrb_context.list_head); - memset(context_array, 0, - sizeof(struct be_mcc_wrb_context) * num_context_entries); - for (i = 0; i < mcc->wrb_context.num; i++) { - list_add_tail(&context_array[i].next, - &mcc->wrb_context.list_head); - } - - /* - * - * Create an mcc_ring for tracking WRB hw ring - */ - va = rd->va; - ASSERT(va); - mp_ring_create(&mcc->sq.ring, length / sizeof(struct MCC_WRB_AMAP), - sizeof(struct MCC_WRB_AMAP), va); - mcc->sq.ring.id = fwcmd->params.response.id; - /* - * Init a mcc_ring for tracking the MCC CQ. - */ - ASSERT(cq->va); - mp_ring_create(&mcc->cq.ring, cq->num_entries, - sizeof(struct MCC_CQ_ENTRY_AMAP), cq->va); - mcc->cq.ring.id = cq->cq_id; - - /* Force zeroing of CQ. */ - memset(cq->va, 0, cq->num_entries * sizeof(struct MCC_CQ_ENTRY_AMAP)); - - /* Initialize debug index. */ - mcc->consumed_index = 0; - - atomic_inc(&cq->ref_count); - pfob->mcc = mcc; - - TRACE(DL_INFO, "MCC ring created. id:%d bytes:%d cq_id:%d cq_entries:%d" - " num_context:%d", mcc->sq.ring.id, length, - cq->cq_id, cq->num_entries, num_context_entries); - -error: - spin_unlock_irqrestore(&pfob->post_lock, irql); - if (pfob->pend_queue_driving && pfob->mcc) { - pfob->pend_queue_driving = 0; - be_drive_mcc_wrb_queue(pfob->mcc); - } - return status; -} - -/* - This routine destroys an MCC send queue - - MccObject - Internal Mcc Object to be destroyed. - - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL < DISPATCH_LEVEL - - The caller of this routine must ensure that no other WRB may be posted - until this routine returns. - -*/ -int be_mcc_ring_destroy(struct be_mcc_object *mcc) -{ - int status = 0; - struct be_function_object *pfob = mcc->parent_function; - - - ASSERT(mcc->processing == 0); - - /* - * Remove the ring from the function object. - * This transitions back to mailbox mode. - */ - pfob->mcc = NULL; - - /* Send fwcmd to destroy the queue. (Using the mailbox.) */ - status = be_function_ring_destroy(mcc->parent_function, mcc->sq.ring.id, - FWCMD_RING_TYPE_MCC, NULL, NULL, NULL, NULL); - ASSERT(status == 0); - - /* Release the SQ reference to the CQ */ - atomic_dec(&mcc->cq_object->ref_count); - - return status; -} - -static void -mcc_wrb_sync_cb(void *context, int staus, struct MCC_WRB_AMAP *wrb) -{ - struct be_mcc_wrb_context *wrb_context = - (struct be_mcc_wrb_context *) context; - ASSERT(wrb_context); - *wrb_context->users_final_status = staus; -} - -/* - This routine posts a command to the MCC send queue - - mcc - Internal Mcc Object to be destroyed. - - wrb - wrb to post. - - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL < DISPATCH_LEVEL if CompletionCallback is not NULL - IRQL <=DISPATCH_LEVEL if CompletionCallback is NULL - - If this routine is called with CompletionCallback != NULL the - call is considered to be asynchronous and will return as soon - as the WRB is posted to the MCC with BE_PENDING. - - If CompletionCallback is NULL, then this routine will not return until - a completion for this MCC command has been processed. - If called at DISPATCH_LEVEL the CompletionCallback must be NULL. - - This routine should only be called if the MPU has been boostraped past - mailbox mode. - - -*/ -int -_be_mpu_post_wrb_ring(struct be_mcc_object *mcc, struct MCC_WRB_AMAP *wrb, - struct be_mcc_wrb_context *wrb_context) -{ - - struct MCC_WRB_AMAP *ring_wrb = NULL; - int status = BE_PENDING; - int final_status = BE_PENDING; - mcc_wrb_cqe_callback cb = NULL; - struct MCC_DB_AMAP mcc_db; - u32 embedded; - - ASSERT(mp_ring_num_empty(&mcc->sq.ring) > 0); - /* - * Input wrb is most likely the next wrb in the ring, since the client - * can peek at the address. - */ - ring_wrb = mp_ring_producer_ptr(&mcc->sq.ring); - if (wrb != ring_wrb) { - /* If not equal, copy it into the ring. */ - memcpy(ring_wrb, wrb, sizeof(struct MCC_WRB_AMAP)); - } -#ifdef BE_DEBUG - wrb_context->ring_wrb = ring_wrb; -#endif - embedded = AMAP_GET_BITS_PTR(MCC_WRB, embedded, ring_wrb); - if (embedded) { - /* embedded commands will have the response within the WRB. */ - wrb_context->wrb = ring_wrb; - } else { - /* - * non-embedded commands will not have the response - * within the WRB, and they may complete out-of-order. - * The WRB will not be valid to inspect - * during the completion. - */ - wrb_context->wrb = NULL; - } - cb = wrb_context->cb; - - if (cb == NULL) { - /* Assign our internal callback if this is a - * synchronous call. */ - wrb_context->cb = mcc_wrb_sync_cb; - wrb_context->cb_context = wrb_context; - wrb_context->users_final_status = &final_status; - } - /* Increment producer index */ - - mcc_db.dw[0] = 0; /* initialize */ - AMAP_SET_BITS_PTR(MCC_DB, rid, &mcc_db, mcc->sq.ring.id); - AMAP_SET_BITS_PTR(MCC_DB, numPosted, &mcc_db, 1); - - mp_ring_produce(&mcc->sq.ring); - PD_WRITE(mcc->parent_function, mpu_mcc_db, mcc_db.dw[0]); - TRACE(DL_INFO, "pidx: %x and cidx: %x.", mcc->sq.ring.pidx, - mcc->sq.ring.cidx); - - if (cb == NULL) { - int polls = 0; /* At >= 1 us per poll */ - /* Wait until this command completes, polling the CQ. */ - do { - TRACE(DL_INFO, "FWCMD submitted in the poll mode."); - /* Do not rearm CQ in this context. */ - be_mcc_process_cq(mcc, false); - - if (final_status == BE_PENDING) { - if ((++polls & 0x7FFFF) == 0) { - TRACE(DL_WARN, - "Warning : polling MCC CQ for %d" - "ms.", polls / 1000); - } - - udelay(1); - } - - /* final_status changed when the command completes */ - } while (final_status == BE_PENDING); - - status = final_status; - } - - return status; -} - -struct MCC_WRB_AMAP * -_be_mpu_peek_ring_wrb(struct be_mcc_object *mcc, bool driving_queue) -{ - /* If we have queued items, do not allow a post to bypass the queue. */ - if (!driving_queue && !list_empty(&mcc->backlog)) - return NULL; - - if (mp_ring_num_empty(&mcc->sq.ring) <= 0) - return NULL; - return (struct MCC_WRB_AMAP *) mp_ring_producer_ptr(&mcc->sq.ring); -} - -int -be_mpu_init_mailbox(struct be_function_object *pfob, struct ring_desc *mailbox) -{ - ASSERT(mailbox); - pfob->mailbox.va = mailbox->va; - pfob->mailbox.pa = cpu_to_le64(mailbox->pa); - pfob->mailbox.length = mailbox->length; - - ASSERT(((u32)(size_t)pfob->mailbox.va & 0xf) == 0); - ASSERT(((u32)(size_t)pfob->mailbox.pa & 0xf) == 0); - /* - * Issue the WRB to set MPU endianness - */ - { - u64 *endian_check = (u64 *) (pfob->mailbox.va + - offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8); - *endian_check = 0xFF1234FFFF5678FFULL; - } - - be_mcc_mailbox_notify_and_wait(pfob); - - return BE_SUCCESS; -} - - -/* - This routine posts a command to the MCC mailbox. - - FuncObj - Function Object to post the WRB on behalf of. - wrb - wrb to post. - CompletionCallback - Address of a callback routine to invoke once the WRB - is completed. - CompletionCallbackContext - Opaque context to be passed during the call to - the CompletionCallback. - Returns BE_SUCCESS if successfull, otherwise an error code is returned. - - IRQL <=DISPATCH_LEVEL if CompletionCallback is NULL - - This routine will block until a completion for this MCC command has been - processed. If called at DISPATCH_LEVEL the CompletionCallback must be NULL. - - This routine should only be called if the MPU has not been boostraped past - mailbox mode. -*/ -int -_be_mpu_post_wrb_mailbox(struct be_function_object *pfob, - struct MCC_WRB_AMAP *wrb, struct be_mcc_wrb_context *wrb_context) -{ - struct MCC_MAILBOX_AMAP *mailbox = NULL; - struct MCC_WRB_AMAP *mb_wrb; - struct MCC_CQ_ENTRY_AMAP *mb_cq; - u32 offset, status; - - ASSERT(pfob->mcc == NULL); - mailbox = pfob->mailbox.va; - ASSERT(mailbox); - - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, wrb)/8; - mb_wrb = (struct MCC_WRB_AMAP *) (u8 *)mailbox + offset; - if (mb_wrb != wrb) { - memset(mailbox, 0, sizeof(*mailbox)); - memcpy(mb_wrb, wrb, sizeof(struct MCC_WRB_AMAP)); - } - /* The callback can inspect the final WRB to get output parameters. */ - wrb_context->wrb = mb_wrb; - - be_mcc_mailbox_notify_and_wait(pfob); - - /* A command completed. Use tag to determine which command. */ - offset = offsetof(struct BE_MCC_MAILBOX_AMAP, cq)/8; - mb_cq = (struct MCC_CQ_ENTRY_AMAP *) ((u8 *)mailbox + offset); - be_mcc_process_cqe(pfob, mb_cq); - - status = AMAP_GET_BITS_PTR(MCC_CQ_ENTRY, completion_status, mb_cq); - if (status) - status = BE_NOT_OK; - return status; -} - -struct be_mcc_wrb_context * -_be_mcc_allocate_wrb_context(struct be_function_object *pfob) -{ - struct be_mcc_wrb_context *context = NULL; - unsigned long irq; - - spin_lock_irqsave(&pfob->mcc_context_lock, irq); - - if (!pfob->mailbox.default_context_allocated) { - /* Use the single default context that we - * always have allocated. */ - pfob->mailbox.default_context_allocated = true; - context = &pfob->mailbox.default_context; - } else if (pfob->mcc) { - /* Get a context from the free list. If any are available. */ - if (!list_empty(&pfob->mcc->wrb_context.list_head)) { - context = list_first_entry( - &pfob->mcc->wrb_context.list_head, - struct be_mcc_wrb_context, next); - } - } - - spin_unlock_irqrestore(&pfob->mcc_context_lock, irq); - - return context; -} - -void -_be_mcc_free_wrb_context(struct be_function_object *pfob, - struct be_mcc_wrb_context *context) -{ - unsigned long irq; - - ASSERT(context); - /* - * Zero during free to try and catch any bugs where the context - * is accessed after a free. - */ - memset(context, 0, sizeof(context)); - - spin_lock_irqsave(&pfob->mcc_context_lock, irq); - - if (context == &pfob->mailbox.default_context) { - /* Free the default context. */ - ASSERT(pfob->mailbox.default_context_allocated); - pfob->mailbox.default_context_allocated = false; - } else { - /* Add to free list. */ - ASSERT(pfob->mcc); - list_add_tail(&context->next, - &pfob->mcc->wrb_context.list_head); - } - - spin_unlock_irqrestore(&pfob->mcc_context_lock, irq); -} - -int -be_mcc_add_async_event_callback(struct be_mcc_object *mcc_object, - mcc_async_event_callback cb, void *cb_context) -{ - /* Lock against anyone trying to change the callback/context pointers - * while being used. */ - spin_lock_irqsave(&mcc_object->parent_function->cq_lock, - mcc_object->parent_function->cq_irq); - - /* Assign the async callback. */ - mcc_object->async_context = cb_context; - mcc_object->async_cb = cb; - - spin_unlock_irqrestore(&mcc_object->parent_function->cq_lock, - mcc_object->parent_function->cq_irq); - - return BE_SUCCESS; -} - -#define MPU_EP_CONTROL 0 -#define MPU_EP_SEMAPHORE 0xac - -/* - *------------------------------------------------------------------- - * Function: be_wait_for_POST_complete - * Waits until the BladeEngine POST completes (either in error or success). - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -static int be_wait_for_POST_complete(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - int s; - u32 post_error, post_stage; - - const u32 us_per_loop = 1000; /* 1000us */ - const u32 print_frequency_loops = 1000000 / us_per_loop; - const u32 max_loops = 60 * print_frequency_loops; - u32 loops = 0; - - /* - * Wait for arm fw indicating it is done or a fatal error happened. - * Note: POST can take some time to complete depending on configuration - * settings (consider ARM attempts to acquire an IP address - * over DHCP!!!). - * - */ - do { - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - error, &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - stage, &status); - if (0 == (loops % print_frequency_loops)) { - /* Print current status */ - TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - } - udelay(us_per_loop); - } while ((post_error != 1) && - (post_stage != POST_STAGE_ARMFW_READY) && - (++loops < max_loops)); - - if (post_error == 1) { - TRACE(DL_ERR, "POST error! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else if (post_stage != POST_STAGE_ARMFW_READY) { - TRACE(DL_ERR, "POST time-out! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else { - s = BE_SUCCESS; - } - return s; -} - -/* - *------------------------------------------------------------------- - * Function: be_kickoff_and_wait_for_POST - * Interacts with the BladeEngine management processor to initiate POST, and - * subsequently waits until POST completes (either in error or success). - * The caller must acquire the reset semaphore before initiating POST - * to prevent multiple drivers interacting with the management processor. - * Once POST is complete the caller must release the reset semaphore. - * Callers who only want to wait for POST complete may call - * be_wait_for_POST_complete. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -static int -be_kickoff_and_wait_for_POST(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - int s; - - const u32 us_per_loop = 1000; /* 1000us */ - const u32 print_frequency_loops = 1000000 / us_per_loop; - const u32 max_loops = 5 * print_frequency_loops; - u32 loops = 0; - u32 post_error, post_stage; - - /* Wait for arm fw awaiting host ready or a fatal error happened. */ - TRACE(DL_INFO, "Wait for BladeEngine ready to POST"); - do { - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - error, &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, - stage, &status); - if (0 == (loops % print_frequency_loops)) { - /* Print current status */ - TRACE(DL_INFO, "POST status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - } - udelay(us_per_loop); - } while ((post_error != 1) && - (post_stage < POST_STAGE_AWAITING_HOST_RDY) && - (++loops < max_loops)); - - if (post_error == 1) { - TRACE(DL_ERR, "Pre-POST error! Status = 0x%x (stage = 0x%x)", - status.dw[0], post_stage); - s = BE_NOT_OK; - } else if (post_stage == POST_STAGE_AWAITING_HOST_RDY) { - iowrite32(POST_STAGE_HOST_RDY, pfob->csr_va + MPU_EP_SEMAPHORE); - - /* Wait for POST to complete */ - s = be_wait_for_POST_complete(pfob); - } else { - /* - * Either a timeout waiting for host ready signal or POST has - * moved ahead without requiring a host ready signal. - * Might as well give POST a chance to complete - * (or timeout again). - */ - s = be_wait_for_POST_complete(pfob); - } - return s; -} - -/* - *------------------------------------------------------------------- - * Function: be_pci_soft_reset - * This function is called to issue a BladeEngine soft reset. - * Callers should acquire the soft reset semaphore before calling this - * function. Additionaly, callers should ensure they cannot be pre-empted - * while the routine executes. Upon completion of this routine, callers - * should release the reset semaphore. This routine implicitly waits - * for BladeEngine POST to complete. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -int be_pci_soft_reset(struct be_function_object *pfob) -{ - struct PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - struct PCICFG_ONLINE0_CSR_AMAP pciOnline0; - struct PCICFG_ONLINE1_CSR_AMAP pciOnline1; - struct EP_CONTROL_CSR_AMAP epControlCsr; - int status = BE_SUCCESS; - u32 i, soft_reset_bit; - - TRACE(DL_NOTE, "PCI reset..."); - - /* Issue soft reset #1 to get BladeEngine into a known state. */ - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1); - PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]); - /* - * wait til soft reset is deasserted - hardware - * deasserts after some time. - */ - i = 0; - do { - udelay(50); - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR, - softreset, soft_reset.dw); - } while (soft_reset_bit && (i++ < 1024)); - if (soft_reset_bit != 0) { - TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected."); - status = BE_NOT_OK; - goto Error_label; - } - /* Mask everything */ - PCICFG0_WRITE(pfob, ue_status_low_mask, 0xFFFFFFFF); - PCICFG0_WRITE(pfob, ue_status_hi_mask, 0xFFFFFFFF); - /* - * Set everything offline except MPU IRAM (it is offline with - * the soft-reset, but soft-reset does not reset the PCICFG registers!) - */ - pciOnline0.dw[0] = 0; - pciOnline1.dw[0] = 0; - AMAP_SET_BITS_PTR(PCICFG_ONLINE1_CSR, mpu_iram_online, - pciOnline1.dw, 1); - PCICFG0_WRITE(pfob, online0, pciOnline0.dw[0]); - PCICFG0_WRITE(pfob, online1, pciOnline1.dw[0]); - - udelay(20000); - - /* Issue soft reset #2. */ - AMAP_SET_BITS_PTR(PCICFG_SOFT_RESET_CSR, softreset, soft_reset.dw, 1); - PCICFG0_WRITE(pfob, host_timer_int_ctrl, soft_reset.dw[0]); - /* - * wait til soft reset is deasserted - hardware - * deasserts after some time. - */ - i = 0; - do { - udelay(50); - soft_reset.dw[0] = PCICFG0_READ(pfob, soft_reset); - soft_reset_bit = AMAP_GET_BITS_PTR(PCICFG_SOFT_RESET_CSR, - softreset, soft_reset.dw); - } while (soft_reset_bit && (i++ < 1024)); - if (soft_reset_bit != 0) { - TRACE(DL_ERR, "Soft-reset #1 did not deassert as expected."); - status = BE_NOT_OK; - goto Error_label; - } - - - udelay(20000); - - /* Take MPU out of reset. */ - - epControlCsr.dw[0] = ioread32(pfob->csr_va + MPU_EP_CONTROL); - AMAP_SET_BITS_PTR(EP_CONTROL_CSR, CPU_reset, &epControlCsr, 0); - iowrite32((u32)epControlCsr.dw[0], pfob->csr_va + MPU_EP_CONTROL); - - /* Kickoff BE POST and wait for completion */ - status = be_kickoff_and_wait_for_POST(pfob); - -Error_label: - return status; -} - - -/* - *------------------------------------------------------------------- - * Function: be_pci_reset_required - * This private function is called to detect if a host entity is - * required to issue a PCI soft reset and subsequently drive - * BladeEngine POST. Scenarios where this is required: - * 1) BIOS-less configuration - * 2) Hot-swap/plug/power-on - * pfob - - * return true if a reset is required, false otherwise - *------------------------------------------------------------------- - */ -static bool be_pci_reset_required(struct be_function_object *pfob) -{ - struct MGMT_HBA_POST_STATUS_STRUCT_AMAP status; - bool do_reset = false; - u32 post_error, post_stage; - - /* - * Read the POST status register - */ - status.dw[0] = ioread32(pfob->csr_va + MPU_EP_SEMAPHORE); - post_error = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, error, - &status); - post_stage = AMAP_GET_BITS_PTR(MGMT_HBA_POST_STATUS_STRUCT, stage, - &status); - if (post_stage <= POST_STAGE_AWAITING_HOST_RDY) { - /* - * If BladeEngine is waiting for host ready indication, - * we want to do a PCI reset. - */ - do_reset = true; - } - - return do_reset; -} - -/* - *------------------------------------------------------------------- - * Function: be_drive_POST - * This function is called to drive BladeEngine POST. The - * caller should ensure they cannot be pre-empted while this routine executes. - * pfob - - * return status - BE_SUCCESS (0) on success. Negative error code on failure. - *------------------------------------------------------------------- - */ -int be_drive_POST(struct be_function_object *pfob) -{ - int status; - - if (false != be_pci_reset_required(pfob)) { - /* PCI reset is needed (implicitly starts and waits for POST) */ - status = be_pci_soft_reset(pfob); - } else { - /* No PCI reset is needed, start POST */ - status = be_kickoff_and_wait_for_POST(pfob); - } - - return status; -} diff --git a/drivers/staging/benet/mpu.h b/drivers/staging/benet/mpu.h deleted file mode 100644 index 41f3f87516e..00000000000 --- a/drivers/staging/benet/mpu.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __mpu_amap_h__ -#define __mpu_amap_h__ -#include "ep.h" - -/* Provide control parameters for the Managment Processor Unit. */ -struct BE_MPU_CSRMAP_AMAP { - struct BE_EP_CSRMAP_AMAP ep; - u8 rsvd0[128]; /* DWORD 64 */ - u8 rsvd1[32]; /* DWORD 68 */ - u8 rsvd2[192]; /* DWORD 69 */ - u8 rsvd3[192]; /* DWORD 75 */ - u8 rsvd4[32]; /* DWORD 81 */ - u8 rsvd5[32]; /* DWORD 82 */ - u8 rsvd6[32]; /* DWORD 83 */ - u8 rsvd7[32]; /* DWORD 84 */ - u8 rsvd8[32]; /* DWORD 85 */ - u8 rsvd9[32]; /* DWORD 86 */ - u8 rsvd10[32]; /* DWORD 87 */ - u8 rsvd11[32]; /* DWORD 88 */ - u8 rsvd12[32]; /* DWORD 89 */ - u8 rsvd13[32]; /* DWORD 90 */ - u8 rsvd14[32]; /* DWORD 91 */ - u8 rsvd15[32]; /* DWORD 92 */ - u8 rsvd16[32]; /* DWORD 93 */ - u8 rsvd17[32]; /* DWORD 94 */ - u8 rsvd18[32]; /* DWORD 95 */ - u8 rsvd19[32]; /* DWORD 96 */ - u8 rsvd20[32]; /* DWORD 97 */ - u8 rsvd21[32]; /* DWORD 98 */ - u8 rsvd22[32]; /* DWORD 99 */ - u8 rsvd23[32]; /* DWORD 100 */ - u8 rsvd24[32]; /* DWORD 101 */ - u8 rsvd25[32]; /* DWORD 102 */ - u8 rsvd26[32]; /* DWORD 103 */ - u8 rsvd27[32]; /* DWORD 104 */ - u8 rsvd28[96]; /* DWORD 105 */ - u8 rsvd29[32]; /* DWORD 108 */ - u8 rsvd30[32]; /* DWORD 109 */ - u8 rsvd31[32]; /* DWORD 110 */ - u8 rsvd32[32]; /* DWORD 111 */ - u8 rsvd33[32]; /* DWORD 112 */ - u8 rsvd34[96]; /* DWORD 113 */ - u8 rsvd35[32]; /* DWORD 116 */ - u8 rsvd36[32]; /* DWORD 117 */ - u8 rsvd37[32]; /* DWORD 118 */ - u8 rsvd38[32]; /* DWORD 119 */ - u8 rsvd39[32]; /* DWORD 120 */ - u8 rsvd40[32]; /* DWORD 121 */ - u8 rsvd41[134][32]; /* DWORD 122 */ -} __packed; -struct MPU_CSRMAP_AMAP { - u32 dw[256]; -}; - -#endif /* __mpu_amap_h__ */ diff --git a/drivers/staging/benet/mpu_context.h b/drivers/staging/benet/mpu_context.h deleted file mode 100644 index 8ce90f9c46c..00000000000 --- a/drivers/staging/benet/mpu_context.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __mpu_context_amap_h__ -#define __mpu_context_amap_h__ - -/* - * Management command and control ring context. The MPUs BTLR_CTRL1 CSR - * controls the writeback behavior of the producer and consumer index values. - */ -struct BE_MCC_RING_CONTEXT_AMAP { - u8 con_index[16]; /* DWORD 0 */ - u8 ring_size[4]; /* DWORD 0 */ - u8 cq_id[11]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 prod_index[16]; /* DWORD 1 */ - u8 pdid[15]; /* DWORD 1 */ - u8 invalid; /* DWORD 1 */ - u8 cmd_pending_current[7]; /* DWORD 2 */ - u8 rsvd1[25]; /* DWORD 2 */ - u8 hpi_port_cq_id[11]; /* DWORD 3 */ - u8 rsvd2[5]; /* DWORD 3 */ - u8 cmd_pending_max[7]; /* DWORD 3 */ - u8 rsvd3[9]; /* DWORD 3 */ -} __packed; -struct MCC_RING_CONTEXT_AMAP { - u32 dw[4]; -}; - -#endif /* __mpu_context_amap_h__ */ diff --git a/drivers/staging/benet/pcicfg.h b/drivers/staging/benet/pcicfg.h deleted file mode 100644 index 7c15684adf4..00000000000 --- a/drivers/staging/benet/pcicfg.h +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __pcicfg_amap_h__ -#define __pcicfg_amap_h__ - -/* Vendor and Device ID Register. */ -struct BE_PCICFG_ID_CSR_AMAP { - u8 vendorid[16]; /* DWORD 0 */ - u8 deviceid[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_ID_CSR_AMAP { - u32 dw[1]; -}; - -/* IO Bar Register. */ -struct BE_PCICFG_IOBAR_CSR_AMAP { - u8 iospace; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ - u8 iobar[24]; /* DWORD 0 */ -} __packed; -struct PCICFG_IOBAR_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 0 Register. */ -struct BE_PCICFG_MEMBAR0_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[10]; /* DWORD 0 */ - u8 membar0[18]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR0_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 1 - Low Address Register. */ -struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[13]; /* DWORD 0 */ - u8 membar1lo[15]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR1_LO_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 1 - High Address Register. */ -struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP { - u8 membar1hi[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR1_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 2 - Low Address Register. */ -struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP { - u8 memspace; /* DWORD 0 */ - u8 type[2]; /* DWORD 0 */ - u8 pf; /* DWORD 0 */ - u8 rsvd0[17]; /* DWORD 0 */ - u8 membar2lo[11]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR2_LO_CSR_AMAP { - u32 dw[1]; -}; - -/* Memory BAR 2 - High Address Register. */ -struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP { - u8 membar2hi[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MEMBAR2_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Subsystem Vendor and ID (Function 0) Register. */ -struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP { - u8 subsys_vendor_id[16]; /* DWORD 0 */ - u8 subsys_id[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP { - u32 dw[1]; -}; - -/* Subsystem Vendor and ID (Function 1) Register. */ -struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP { - u8 subsys_vendor_id[16]; /* DWORD 0 */ - u8 subsys_id[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP { - u32 dw[1]; -}; - -/* Semaphore Register. */ -struct BE_PCICFG_SEMAPHORE_CSR_AMAP { - u8 locked; /* DWORD 0 */ - u8 rsvd0[31]; /* DWORD 0 */ -} __packed; -struct PCICFG_SEMAPHORE_CSR_AMAP { - u32 dw[1]; -}; - -/* Soft Reset Register. */ -struct BE_PCICFG_SOFT_RESET_CSR_AMAP { - u8 rsvd0[7]; /* DWORD 0 */ - u8 softreset; /* DWORD 0 */ - u8 rsvd1[16]; /* DWORD 0 */ - u8 nec_ll_rcvdetect_i[8]; /* DWORD 0 */ -} __packed; -struct PCICFG_SOFT_RESET_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Status (Low) Register. Each bit corresponds to - * an internal Unrecoverable Error. These are set by hardware and may be - * cleared by writing a one to the respective bit(s) to be cleared. Any - * bit being set that is also unmasked will result in Unrecoverable Error - * interrupt notification to the host CPU and/or Server Management chip - * and the transitioning of BladeEngine to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP { - u8 cev_ue_status; /* DWORD 0 */ - u8 ctx_ue_status; /* DWORD 0 */ - u8 dbuf_ue_status; /* DWORD 0 */ - u8 erx_ue_status; /* DWORD 0 */ - u8 host_ue_status; /* DWORD 0 */ - u8 mpu_ue_status; /* DWORD 0 */ - u8 ndma_ue_status; /* DWORD 0 */ - u8 ptc_ue_status; /* DWORD 0 */ - u8 rdma_ue_status; /* DWORD 0 */ - u8 rxf_ue_status; /* DWORD 0 */ - u8 rxips_ue_status; /* DWORD 0 */ - u8 rxulp0_ue_status; /* DWORD 0 */ - u8 rxulp1_ue_status; /* DWORD 0 */ - u8 rxulp2_ue_status; /* DWORD 0 */ - u8 tim_ue_status; /* DWORD 0 */ - u8 tpost_ue_status; /* DWORD 0 */ - u8 tpre_ue_status; /* DWORD 0 */ - u8 txips_ue_status; /* DWORD 0 */ - u8 txulp0_ue_status; /* DWORD 0 */ - u8 txulp1_ue_status; /* DWORD 0 */ - u8 uc_ue_status; /* DWORD 0 */ - u8 wdma_ue_status; /* DWORD 0 */ - u8 txulp2_ue_status; /* DWORD 0 */ - u8 host1_ue_status; /* DWORD 0 */ - u8 p0_ob_link_ue_status; /* DWORD 0 */ - u8 p1_ob_link_ue_status; /* DWORD 0 */ - u8 host_gpio_ue_status; /* DWORD 0 */ - u8 mbox_netw_ue_status; /* DWORD 0 */ - u8 mbox_stor_ue_status; /* DWORD 0 */ - u8 axgmac0_ue_status; /* DWORD 0 */ - u8 axgmac1_ue_status; /* DWORD 0 */ - u8 mpu_intpend_ue_status; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_LOW_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Status (High) Register. Each bit corresponds to - * an internal Unrecoverable Error. These are set by hardware and may be - * cleared by writing a one to the respective bit(s) to be cleared. Any - * bit being set that is also unmasked will result in Unrecoverable Error - * interrupt notification to the host CPU and/or Server Management chip; - * and the transitioning of BladeEngine to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP { - u8 jtag_ue_status; /* DWORD 0 */ - u8 lpcmemhost_ue_status; /* DWORD 0 */ - u8 mgmt_mac_ue_status; /* DWORD 0 */ - u8 mpu_iram_ue_status; /* DWORD 0 */ - u8 pcs0online_ue_status; /* DWORD 0 */ - u8 pcs1online_ue_status; /* DWORD 0 */ - u8 pctl0_ue_status; /* DWORD 0 */ - u8 pctl1_ue_status; /* DWORD 0 */ - u8 pmem_ue_status; /* DWORD 0 */ - u8 rr_ue_status; /* DWORD 0 */ - u8 rxpp_ue_status; /* DWORD 0 */ - u8 txpb_ue_status; /* DWORD 0 */ - u8 txp_ue_status; /* DWORD 0 */ - u8 xaui_ue_status; /* DWORD 0 */ - u8 arm_ue_status; /* DWORD 0 */ - u8 ipc_ue_status; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Mask (Low) Register. Each bit, when set to one, - * will mask the associated Unrecoverable Error status bit from notification - * of Unrecoverable Error to the host CPU and/or Server Managment chip and the - * transitioning of all BladeEngine units to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP { - u8 cev_ue_mask; /* DWORD 0 */ - u8 ctx_ue_mask; /* DWORD 0 */ - u8 dbuf_ue_mask; /* DWORD 0 */ - u8 erx_ue_mask; /* DWORD 0 */ - u8 host_ue_mask; /* DWORD 0 */ - u8 mpu_ue_mask; /* DWORD 0 */ - u8 ndma_ue_mask; /* DWORD 0 */ - u8 ptc_ue_mask; /* DWORD 0 */ - u8 rdma_ue_mask; /* DWORD 0 */ - u8 rxf_ue_mask; /* DWORD 0 */ - u8 rxips_ue_mask; /* DWORD 0 */ - u8 rxulp0_ue_mask; /* DWORD 0 */ - u8 rxulp1_ue_mask; /* DWORD 0 */ - u8 rxulp2_ue_mask; /* DWORD 0 */ - u8 tim_ue_mask; /* DWORD 0 */ - u8 tpost_ue_mask; /* DWORD 0 */ - u8 tpre_ue_mask; /* DWORD 0 */ - u8 txips_ue_mask; /* DWORD 0 */ - u8 txulp0_ue_mask; /* DWORD 0 */ - u8 txulp1_ue_mask; /* DWORD 0 */ - u8 uc_ue_mask; /* DWORD 0 */ - u8 wdma_ue_mask; /* DWORD 0 */ - u8 txulp2_ue_mask; /* DWORD 0 */ - u8 host1_ue_mask; /* DWORD 0 */ - u8 p0_ob_link_ue_mask; /* DWORD 0 */ - u8 p1_ob_link_ue_mask; /* DWORD 0 */ - u8 host_gpio_ue_mask; /* DWORD 0 */ - u8 mbox_netw_ue_mask; /* DWORD 0 */ - u8 mbox_stor_ue_mask; /* DWORD 0 */ - u8 axgmac0_ue_mask; /* DWORD 0 */ - u8 axgmac1_ue_mask; /* DWORD 0 */ - u8 mpu_intpend_ue_mask; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP { - u32 dw[1]; -}; - -/* Unrecoverable Error Mask (High) Register. Each bit, when set to one, - * will mask the associated Unrecoverable Error status bit from notification - * of Unrecoverable Error to the host CPU and/or Server Managment chip and the - * transitioning of all BladeEngine units to an Offline state. - */ -struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP { - u8 jtag_ue_mask; /* DWORD 0 */ - u8 lpcmemhost_ue_mask; /* DWORD 0 */ - u8 mgmt_mac_ue_mask; /* DWORD 0 */ - u8 mpu_iram_ue_mask; /* DWORD 0 */ - u8 pcs0online_ue_mask; /* DWORD 0 */ - u8 pcs1online_ue_mask; /* DWORD 0 */ - u8 pctl0_ue_mask; /* DWORD 0 */ - u8 pctl1_ue_mask; /* DWORD 0 */ - u8 pmem_ue_mask; /* DWORD 0 */ - u8 rr_ue_mask; /* DWORD 0 */ - u8 rxpp_ue_mask; /* DWORD 0 */ - u8 txpb_ue_mask; /* DWORD 0 */ - u8 txp_ue_mask; /* DWORD 0 */ - u8 xaui_ue_mask; /* DWORD 0 */ - u8 arm_ue_mask; /* DWORD 0 */ - u8 ipc_ue_mask; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_UE_STATUS_HI_MASK_CSR_AMAP { - u32 dw[1]; -}; - -/* Online Control Register 0. This register controls various units within - * BladeEngine being in an Online or Offline state. - */ -struct BE_PCICFG_ONLINE0_CSR_AMAP { - u8 cev_online; /* DWORD 0 */ - u8 ctx_online; /* DWORD 0 */ - u8 dbuf_online; /* DWORD 0 */ - u8 erx_online; /* DWORD 0 */ - u8 host_online; /* DWORD 0 */ - u8 mpu_online; /* DWORD 0 */ - u8 ndma_online; /* DWORD 0 */ - u8 ptc_online; /* DWORD 0 */ - u8 rdma_online; /* DWORD 0 */ - u8 rxf_online; /* DWORD 0 */ - u8 rxips_online; /* DWORD 0 */ - u8 rxulp0_online; /* DWORD 0 */ - u8 rxulp1_online; /* DWORD 0 */ - u8 rxulp2_online; /* DWORD 0 */ - u8 tim_online; /* DWORD 0 */ - u8 tpost_online; /* DWORD 0 */ - u8 tpre_online; /* DWORD 0 */ - u8 txips_online; /* DWORD 0 */ - u8 txulp0_online; /* DWORD 0 */ - u8 txulp1_online; /* DWORD 0 */ - u8 uc_online; /* DWORD 0 */ - u8 wdma_online; /* DWORD 0 */ - u8 txulp2_online; /* DWORD 0 */ - u8 host1_online; /* DWORD 0 */ - u8 p0_ob_link_online; /* DWORD 0 */ - u8 p1_ob_link_online; /* DWORD 0 */ - u8 host_gpio_online; /* DWORD 0 */ - u8 mbox_netw_online; /* DWORD 0 */ - u8 mbox_stor_online; /* DWORD 0 */ - u8 axgmac0_online; /* DWORD 0 */ - u8 axgmac1_online; /* DWORD 0 */ - u8 mpu_intpend_online; /* DWORD 0 */ -} __packed; -struct PCICFG_ONLINE0_CSR_AMAP { - u32 dw[1]; -}; - -/* Online Control Register 1. This register controls various units within - * BladeEngine being in an Online or Offline state. - */ -struct BE_PCICFG_ONLINE1_CSR_AMAP { - u8 jtag_online; /* DWORD 0 */ - u8 lpcmemhost_online; /* DWORD 0 */ - u8 mgmt_mac_online; /* DWORD 0 */ - u8 mpu_iram_online; /* DWORD 0 */ - u8 pcs0online_online; /* DWORD 0 */ - u8 pcs1online_online; /* DWORD 0 */ - u8 pctl0_online; /* DWORD 0 */ - u8 pctl1_online; /* DWORD 0 */ - u8 pmem_online; /* DWORD 0 */ - u8 rr_online; /* DWORD 0 */ - u8 rxpp_online; /* DWORD 0 */ - u8 txpb_online; /* DWORD 0 */ - u8 txp_online; /* DWORD 0 */ - u8 xaui_online; /* DWORD 0 */ - u8 arm_online; /* DWORD 0 */ - u8 ipc_online; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_ONLINE1_CSR_AMAP { - u32 dw[1]; -}; - -/* Host Timer Register. */ -struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP { - u8 hosttimer[24]; /* DWORD 0 */ - u8 hostintr; /* DWORD 0 */ - u8 rsvd0[7]; /* DWORD 0 */ -} __packed; -struct PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP { - u32 dw[1]; -}; - -/* Scratchpad Register (for software use). */ -struct BE_PCICFG_SCRATCHPAD_CSR_AMAP { - u8 scratchpad[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_SCRATCHPAD_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Capabilities Register. */ -struct BE_PCICFG_PCIE_CAP_CSR_AMAP { - u8 capid[8]; /* DWORD 0 */ - u8 nextcap[8]; /* DWORD 0 */ - u8 capver[4]; /* DWORD 0 */ - u8 devport[4]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 rsvd1[2]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_CAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Device Capabilities Register. */ -struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP { - u8 payload[3]; /* DWORD 0 */ - u8 rsvd0[3]; /* DWORD 0 */ - u8 lo_lat[3]; /* DWORD 0 */ - u8 l1_lat[3]; /* DWORD 0 */ - u8 rsvd1[3]; /* DWORD 0 */ - u8 rsvd2[3]; /* DWORD 0 */ - u8 pwr_value[8]; /* DWORD 0 */ - u8 pwr_scale[2]; /* DWORD 0 */ - u8 rsvd3[4]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_DEVCAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Device Control/Status Registers. */ -struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP { - u8 CorrErrReportEn; /* DWORD 0 */ - u8 NonFatalErrReportEn; /* DWORD 0 */ - u8 FatalErrReportEn; /* DWORD 0 */ - u8 UnsuppReqReportEn; /* DWORD 0 */ - u8 EnableRelaxOrder; /* DWORD 0 */ - u8 Max_Payload_Size[3]; /* DWORD 0 */ - u8 ExtendTagFieldEnable; /* DWORD 0 */ - u8 PhantomFnEnable; /* DWORD 0 */ - u8 AuxPwrPMEnable; /* DWORD 0 */ - u8 EnableNoSnoop; /* DWORD 0 */ - u8 Max_Read_Req_Size[3]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 CorrErrDetect; /* DWORD 0 */ - u8 NonFatalErrDetect; /* DWORD 0 */ - u8 FatalErrDetect; /* DWORD 0 */ - u8 UnsuppReqDetect; /* DWORD 0 */ - u8 AuxPwrDetect; /* DWORD 0 */ - u8 TransPending; /* DWORD 0 */ - u8 rsvd1[10]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Link Capabilities Register. */ -struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP { - u8 MaxLinkSpeed[4]; /* DWORD 0 */ - u8 MaxLinkWidth[6]; /* DWORD 0 */ - u8 ASPMSupport[2]; /* DWORD 0 */ - u8 L0sExitLat[3]; /* DWORD 0 */ - u8 L1ExitLat[3]; /* DWORD 0 */ - u8 rsvd0[6]; /* DWORD 0 */ - u8 PortNum[8]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_LINK_CAP_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express Link Status Register. */ -struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP { - u8 ASPMCtl[2]; /* DWORD 0 */ - u8 rsvd0; /* DWORD 0 */ - u8 ReadCmplBndry; /* DWORD 0 */ - u8 LinkDisable; /* DWORD 0 */ - u8 RetrainLink; /* DWORD 0 */ - u8 CommonClkConfig; /* DWORD 0 */ - u8 ExtendSync; /* DWORD 0 */ - u8 rsvd1[8]; /* DWORD 0 */ - u8 LinkSpeed[4]; /* DWORD 0 */ - u8 NegLinkWidth[6]; /* DWORD 0 */ - u8 LinkTrainErr; /* DWORD 0 */ - u8 LinkTrain; /* DWORD 0 */ - u8 SlotClkConfig; /* DWORD 0 */ - u8 rsvd2[3]; /* DWORD 0 */ -} __packed; -struct PCICFG_PCIE_LINK_STATUS_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI Configuration Register. */ -struct BE_PCICFG_MSI_CSR_AMAP { - u8 capid[8]; /* DWORD 0 */ - u8 nextptr[8]; /* DWORD 0 */ - u8 tablesize[11]; /* DWORD 0 */ - u8 rsvd0[3]; /* DWORD 0 */ - u8 funcmask; /* DWORD 0 */ - u8 en; /* DWORD 0 */ -} __packed; -struct PCICFG_MSI_CSR_AMAP { - u32 dw[1]; -}; - -/* MSI-X Table Offset Register. */ -struct BE_PCICFG_MSIX_TABLE_CSR_AMAP { - u8 tablebir[3]; /* DWORD 0 */ - u8 offset[29]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_TABLE_CSR_AMAP { - u32 dw[1]; -}; - -/* MSI-X PBA Offset Register. */ -struct BE_PCICFG_MSIX_PBA_CSR_AMAP { - u8 pbabir[3]; /* DWORD 0 */ - u8 offset[29]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_PBA_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Vector Control Register. */ -struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP { - u8 vector_control; /* DWORD 0 */ - u8 rsvd0[31]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Data Register. */ -struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP { - u8 data[16]; /* DWORD 0 */ - u8 rsvd0[16]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_DATA_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Address Register - High Part. */ -struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP { - u8 addr[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP { - u32 dw[1]; -}; - -/* PCI Express MSI-X Message Address Register - Low Part. */ -struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP { - u8 rsvd0[2]; /* DWORD 0 */ - u8 addr[30]; /* DWORD 0 */ -} __packed; -struct PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_18_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_18_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_19_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_19_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_20_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[25][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_20_RSVD_AMAP { - u32 dw[26]; -}; - -struct BE_PCICFG_ANON_21_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[1919][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_21_RSVD_AMAP { - u32 dw[1920]; -}; - -struct BE_PCICFG_ANON_22_MESSAGE_AMAP { - struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl; - struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data; - struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi; - struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low; -} __packed; -struct PCICFG_ANON_22_MESSAGE_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_23_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[895][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_23_RSVD_AMAP { - u32 dw[896]; -}; - -/* These PCI Configuration Space registers are for the Storage Function of - * BladeEngine (Function 0). In the memory map of the registers below their - * table, - */ -struct BE_PCICFG0_CSRMAP_AMAP { - struct BE_PCICFG_ID_CSR_AMAP id; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - struct BE_PCICFG_IOBAR_CSR_AMAP iobar; - struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0; - struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo; - struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi; - struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo; - struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi; - u8 rsvd3[32]; /* DWORD 10 */ - struct BE_PCICFG_SUBSYSTEM_ID_F0_CSR_AMAP subsystem_id; - u8 rsvd4[32]; /* DWORD 12 */ - u8 rsvd5[32]; /* DWORD 13 */ - u8 rsvd6[32]; /* DWORD 14 */ - u8 rsvd7[32]; /* DWORD 15 */ - struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4]; - struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - u8 rsvd8[32]; /* DWORD 21 */ - struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad; - u8 rsvd9[32]; /* DWORD 23 */ - u8 rsvd10[32]; /* DWORD 24 */ - u8 rsvd11[32]; /* DWORD 25 */ - u8 rsvd12[32]; /* DWORD 26 */ - u8 rsvd13[32]; /* DWORD 27 */ - u8 rsvd14[2][32]; /* DWORD 28 */ - u8 rsvd15[32]; /* DWORD 30 */ - u8 rsvd16[32]; /* DWORD 31 */ - u8 rsvd17[8][32]; /* DWORD 32 */ - struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low; - struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi; - struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask; - struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask; - struct BE_PCICFG_ONLINE0_CSR_AMAP online0; - struct BE_PCICFG_ONLINE1_CSR_AMAP online1; - u8 rsvd18[32]; /* DWORD 46 */ - u8 rsvd19[32]; /* DWORD 47 */ - u8 rsvd20[32]; /* DWORD 48 */ - u8 rsvd21[32]; /* DWORD 49 */ - struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl; - u8 rsvd22[32]; /* DWORD 51 */ - struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap; - struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap; - struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status; - struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap; - struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status; - struct BE_PCICFG_MSI_CSR_AMAP msi; - struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset; - struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset; - u8 rsvd23[32]; /* DWORD 60 */ - u8 rsvd24[32]; /* DWORD 61 */ - u8 rsvd25[32]; /* DWORD 62 */ - u8 rsvd26[32]; /* DWORD 63 */ - u8 rsvd27[32]; /* DWORD 64 */ - u8 rsvd28[32]; /* DWORD 65 */ - u8 rsvd29[32]; /* DWORD 66 */ - u8 rsvd30[32]; /* DWORD 67 */ - u8 rsvd31[32]; /* DWORD 68 */ - u8 rsvd32[32]; /* DWORD 69 */ - u8 rsvd33[32]; /* DWORD 70 */ - u8 rsvd34[32]; /* DWORD 71 */ - u8 rsvd35[32]; /* DWORD 72 */ - u8 rsvd36[32]; /* DWORD 73 */ - u8 rsvd37[32]; /* DWORD 74 */ - u8 rsvd38[32]; /* DWORD 75 */ - u8 rsvd39[32]; /* DWORD 76 */ - u8 rsvd40[32]; /* DWORD 77 */ - u8 rsvd41[32]; /* DWORD 78 */ - u8 rsvd42[32]; /* DWORD 79 */ - u8 rsvd43[32]; /* DWORD 80 */ - u8 rsvd44[32]; /* DWORD 81 */ - u8 rsvd45[32]; /* DWORD 82 */ - u8 rsvd46[32]; /* DWORD 83 */ - u8 rsvd47[32]; /* DWORD 84 */ - u8 rsvd48[32]; /* DWORD 85 */ - u8 rsvd49[32]; /* DWORD 86 */ - u8 rsvd50[32]; /* DWORD 87 */ - u8 rsvd51[32]; /* DWORD 88 */ - u8 rsvd52[32]; /* DWORD 89 */ - u8 rsvd53[32]; /* DWORD 90 */ - u8 rsvd54[32]; /* DWORD 91 */ - u8 rsvd55[32]; /* DWORD 92 */ - u8 rsvd56[832]; /* DWORD 93 */ - u8 rsvd57[32]; /* DWORD 119 */ - u8 rsvd58[32]; /* DWORD 120 */ - u8 rsvd59[32]; /* DWORD 121 */ - u8 rsvd60[32]; /* DWORD 122 */ - u8 rsvd61[32]; /* DWORD 123 */ - u8 rsvd62[32]; /* DWORD 124 */ - u8 rsvd63[32]; /* DWORD 125 */ - u8 rsvd64[32]; /* DWORD 126 */ - u8 rsvd65[32]; /* DWORD 127 */ - u8 rsvd66[61440]; /* DWORD 128 */ - struct BE_PCICFG_ANON_22_MESSAGE_AMAP message[32]; - u8 rsvd67[28672]; /* DWORD 2176 */ - u8 rsvd68[32]; /* DWORD 3072 */ - u8 rsvd69[1023][32]; /* DWORD 3073 */ -} __packed; -struct PCICFG0_CSRMAP_AMAP { - u32 dw[4096]; -}; - -struct BE_PCICFG_ANON_24_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_24_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_25_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_25_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_26_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ -} __packed; -struct PCICFG_ANON_26_RSVD_AMAP { - u32 dw[1]; -}; - -struct BE_PCICFG_ANON_27_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_27_RSVD_AMAP { - u32 dw[2]; -}; - -struct BE_PCICFG_ANON_28_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[3][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_28_RSVD_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_29_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[36][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_29_RSVD_AMAP { - u32 dw[37]; -}; - -struct BE_PCICFG_ANON_30_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[1930][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_30_RSVD_AMAP { - u32 dw[1931]; -}; - -struct BE_PCICFG_ANON_31_MESSAGE_AMAP { - struct BE_PCICFG_MSIX_VECTOR_CONTROL_CSR_AMAP vec_ctrl; - struct BE_PCICFG_MSIX_MSG_DATA_CSR_AMAP msg_data; - struct BE_PCICFG_MSIX_MSG_ADDR_HI_CSR_AMAP addr_hi; - struct BE_PCICFG_MSIX_MSG_ADDR_LO_CSR_AMAP addr_low; -} __packed; -struct PCICFG_ANON_31_MESSAGE_AMAP { - u32 dw[4]; -}; - -struct BE_PCICFG_ANON_32_RSVD_AMAP { - u8 rsvd0[32]; /* DWORD 0 */ - u8 rsvd1[895][32]; /* DWORD 1 */ -} __packed; -struct PCICFG_ANON_32_RSVD_AMAP { - u32 dw[896]; -}; - -/* This PCI configuration space register map is for the Networking Function of - * BladeEngine (Function 1). - */ -struct BE_PCICFG1_CSRMAP_AMAP { - struct BE_PCICFG_ID_CSR_AMAP id; - u8 rsvd0[32]; /* DWORD 1 */ - u8 rsvd1[32]; /* DWORD 2 */ - u8 rsvd2[32]; /* DWORD 3 */ - struct BE_PCICFG_IOBAR_CSR_AMAP iobar; - struct BE_PCICFG_MEMBAR0_CSR_AMAP membar0; - struct BE_PCICFG_MEMBAR1_LO_CSR_AMAP membar1_lo; - struct BE_PCICFG_MEMBAR1_HI_CSR_AMAP membar1_hi; - struct BE_PCICFG_MEMBAR2_LO_CSR_AMAP membar2_lo; - struct BE_PCICFG_MEMBAR2_HI_CSR_AMAP membar2_hi; - u8 rsvd3[32]; /* DWORD 10 */ - struct BE_PCICFG_SUBSYSTEM_ID_F1_CSR_AMAP subsystem_id; - u8 rsvd4[32]; /* DWORD 12 */ - u8 rsvd5[32]; /* DWORD 13 */ - u8 rsvd6[32]; /* DWORD 14 */ - u8 rsvd7[32]; /* DWORD 15 */ - struct BE_PCICFG_SEMAPHORE_CSR_AMAP semaphore[4]; - struct BE_PCICFG_SOFT_RESET_CSR_AMAP soft_reset; - u8 rsvd8[32]; /* DWORD 21 */ - struct BE_PCICFG_SCRATCHPAD_CSR_AMAP scratchpad; - u8 rsvd9[32]; /* DWORD 23 */ - u8 rsvd10[32]; /* DWORD 24 */ - u8 rsvd11[32]; /* DWORD 25 */ - u8 rsvd12[32]; /* DWORD 26 */ - u8 rsvd13[32]; /* DWORD 27 */ - u8 rsvd14[2][32]; /* DWORD 28 */ - u8 rsvd15[32]; /* DWORD 30 */ - u8 rsvd16[32]; /* DWORD 31 */ - u8 rsvd17[8][32]; /* DWORD 32 */ - struct BE_PCICFG_UE_STATUS_LOW_CSR_AMAP ue_status_low; - struct BE_PCICFG_UE_STATUS_HI_CSR_AMAP ue_status_hi; - struct BE_PCICFG_UE_STATUS_LOW_MASK_CSR_AMAP ue_status_low_mask; - struct BE_PCICFG_UE_STATUS_HI_MASK_CSR_AMAP ue_status_hi_mask; - struct BE_PCICFG_ONLINE0_CSR_AMAP online0; - struct BE_PCICFG_ONLINE1_CSR_AMAP online1; - u8 rsvd18[32]; /* DWORD 46 */ - u8 rsvd19[32]; /* DWORD 47 */ - u8 rsvd20[32]; /* DWORD 48 */ - u8 rsvd21[32]; /* DWORD 49 */ - struct BE_PCICFG_HOST_TIMER_INT_CTRL_CSR_AMAP host_timer_int_ctrl; - u8 rsvd22[32]; /* DWORD 51 */ - struct BE_PCICFG_PCIE_CAP_CSR_AMAP pcie_cap; - struct BE_PCICFG_PCIE_DEVCAP_CSR_AMAP pcie_devcap; - struct BE_PCICFG_PCIE_CONTROL_STATUS_CSR_AMAP pcie_control_status; - struct BE_PCICFG_PCIE_LINK_CAP_CSR_AMAP pcie_link_cap; - struct BE_PCICFG_PCIE_LINK_STATUS_CSR_AMAP pcie_link_status; - struct BE_PCICFG_MSI_CSR_AMAP msi; - struct BE_PCICFG_MSIX_TABLE_CSR_AMAP msix_table_offset; - struct BE_PCICFG_MSIX_PBA_CSR_AMAP msix_pba_offset; - u8 rsvd23[64]; /* DWORD 60 */ - u8 rsvd24[32]; /* DWORD 62 */ - u8 rsvd25[32]; /* DWORD 63 */ - u8 rsvd26[32]; /* DWORD 64 */ - u8 rsvd27[32]; /* DWORD 65 */ - u8 rsvd28[32]; /* DWORD 66 */ - u8 rsvd29[32]; /* DWORD 67 */ - u8 rsvd30[32]; /* DWORD 68 */ - u8 rsvd31[32]; /* DWORD 69 */ - u8 rsvd32[32]; /* DWORD 70 */ - u8 rsvd33[32]; /* DWORD 71 */ - u8 rsvd34[32]; /* DWORD 72 */ - u8 rsvd35[32]; /* DWORD 73 */ - u8 rsvd36[32]; /* DWORD 74 */ - u8 rsvd37[128]; /* DWORD 75 */ - u8 rsvd38[32]; /* DWORD 79 */ - u8 rsvd39[1184]; /* DWORD 80 */ - u8 rsvd40[61792]; /* DWORD 117 */ - struct BE_PCICFG_ANON_31_MESSAGE_AMAP message[32]; - u8 rsvd41[28672]; /* DWORD 2176 */ - u8 rsvd42[32]; /* DWORD 3072 */ - u8 rsvd43[1023][32]; /* DWORD 3073 */ -} __packed; -struct PCICFG1_CSRMAP_AMAP { - u32 dw[4096]; -}; - -#endif /* __pcicfg_amap_h__ */ diff --git a/drivers/staging/benet/post_codes.h b/drivers/staging/benet/post_codes.h deleted file mode 100644 index 6d1621f5f5f..00000000000 --- a/drivers/staging/benet/post_codes.h +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __post_codes_amap_h__ -#define __post_codes_amap_h__ - -/* --- MGMT_HBA_POST_STAGE_ENUM --- */ -#define POST_STAGE_POWER_ON_RESET (0) /* State after a cold or warm boot. */ -#define POST_STAGE_AWAITING_HOST_RDY (1) /* ARM boot code awaiting a - go-ahed from the host. */ -#define POST_STAGE_HOST_RDY (2) /* Host has given go-ahed to ARM. */ -#define POST_STAGE_BE_RESET (3) /* Host wants to reset chip, this is a chip - workaround */ -#define POST_STAGE_SEEPROM_CS_START (256) /* SEEPROM checksum - test start. */ -#define POST_STAGE_SEEPROM_CS_DONE (257) /* SEEPROM checksum test - done. */ -#define POST_STAGE_DDR_CONFIG_START (512) /* DDR configuration start. */ -#define POST_STAGE_DDR_CONFIG_DONE (513) /* DDR configuration done. */ -#define POST_STAGE_DDR_CALIBRATE_START (768) /* DDR calibration start. */ -#define POST_STAGE_DDR_CALIBRATE_DONE (769) /* DDR calibration done. */ -#define POST_STAGE_DDR_TEST_START (1024) /* DDR memory test start. */ -#define POST_STAGE_DDR_TEST_DONE (1025) /* DDR memory test done. */ -#define POST_STAGE_REDBOOT_INIT_START (1536) /* Redboot starts execution. */ -#define POST_STAGE_REDBOOT_INIT_DONE (1537) /* Redboot done execution. */ -#define POST_STAGE_FW_IMAGE_LOAD_START (1792) /* Firmware image load to - DDR start. */ -#define POST_STAGE_FW_IMAGE_LOAD_DONE (1793) /* Firmware image load - to DDR done. */ -#define POST_STAGE_ARMFW_START (2048) /* ARMfw runtime code - starts execution. */ -#define POST_STAGE_DHCP_QUERY_START (2304) /* DHCP server query start. */ -#define POST_STAGE_DHCP_QUERY_DONE (2305) /* DHCP server query done. */ -#define POST_STAGE_BOOT_TARGET_DISCOVERY_START (2560) /* Boot Target - Discovery Start. */ -#define POST_STAGE_BOOT_TARGET_DISCOVERY_DONE (2561) /* Boot Target - Discovery Done. */ -#define POST_STAGE_RC_OPTION_SET (2816) /* Remote configuration - option is set in SEEPROM */ -#define POST_STAGE_SWITCH_LINK (2817) /* Wait for link up on switch */ -#define POST_STAGE_SEND_ICDS_MESSAGE (2818) /* Send the ICDS message - to switch */ -#define POST_STAGE_PERFROM_TFTP (2819) /* Download xml using TFTP */ -#define POST_STAGE_PARSE_XML (2820) /* Parse XML file */ -#define POST_STAGE_DOWNLOAD_IMAGE (2821) /* Download IMAGE from - TFTP server */ -#define POST_STAGE_FLASH_IMAGE (2822) /* Flash the IMAGE */ -#define POST_STAGE_RC_DONE (2823) /* Remote configuration - complete */ -#define POST_STAGE_REBOOT_SYSTEM (2824) /* Upgrade IMAGE done, - reboot required */ -#define POST_STAGE_MAC_ADDRESS (3072) /* MAC Address Check */ -#define POST_STAGE_ARMFW_READY (49152) /* ARMfw is done with POST - and ready. */ -#define POST_STAGE_ARMFW_UE (61440) /* ARMfw has asserted an - unrecoverable error. The - lower 3 hex digits of the - stage code identify the - unique error code. - */ - -/* This structure defines the format of the MPU semaphore - * register when used for POST. - */ -struct BE_MGMT_HBA_POST_STATUS_STRUCT_AMAP { - u8 stage[16]; /* DWORD 0 */ - u8 rsvd0[10]; /* DWORD 0 */ - u8 iscsi_driver_loaded; /* DWORD 0 */ - u8 option_rom_installed; /* DWORD 0 */ - u8 iscsi_ip_conflict; /* DWORD 0 */ - u8 iscsi_no_ip; /* DWORD 0 */ - u8 backup_fw; /* DWORD 0 */ - u8 error; /* DWORD 0 */ -} __packed; -struct MGMT_HBA_POST_STATUS_STRUCT_AMAP { - u32 dw[1]; -}; - -/* --- MGMT_HBA_POST_DUMMY_BITS_ENUM --- */ -#define POST_BIT_ISCSI_LOADED (26) -#define POST_BIT_OPTROM_INST (27) -#define POST_BIT_BAD_IP_ADDR (28) -#define POST_BIT_NO_IP_ADDR (29) -#define POST_BIT_BACKUP_FW (30) -#define POST_BIT_ERROR (31) - -/* --- MGMT_HBA_POST_DUMMY_VALUES_ENUM --- */ -#define POST_ISCSI_DRIVER_LOADED (67108864) -#define POST_OPTROM_INSTALLED (134217728) -#define POST_ISCSI_IP_ADDRESS_CONFLICT (268435456) -#define POST_ISCSI_NO_IP_ADDRESS (536870912) -#define POST_BACKUP_FW_LOADED (1073741824) -#define POST_FATAL_ERROR (2147483648) - -#endif /* __post_codes_amap_h__ */ diff --git a/drivers/staging/benet/regmap.h b/drivers/staging/benet/regmap.h deleted file mode 100644 index e816ba210e8..00000000000 --- a/drivers/staging/benet/regmap.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2005 - 2008 ServerEngines - * All rights reserved. - * - * 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. The full GNU General - * Public License is included in this distribution in the file called COPYING. - * - * Contact Information: - * linux-drivers@serverengines.com - * - * ServerEngines - * 209 N. Fair Oaks Ave - * Sunnyvale, CA 94085 - */ -/* - * Autogenerated by srcgen version: 0127 - */ -#ifndef __regmap_amap_h__ -#define __regmap_amap_h__ -#include "pcicfg.h" -#include "ep.h" -#include "cev.h" -#include "mpu.h" -#include "doorbells.h" - -/* - * This is the control and status register map for BladeEngine, showing - * the relative size and offset of each sub-module. The CSR registers - * are identical for the network and storage PCI functions. The - * CSR map is shown below, followed by details of each block, - * in sub-sections. The sub-sections begin with a description - * of CSRs that are instantiated in multiple blocks. - */ -struct BE_BLADE_ENGINE_CSRMAP_AMAP { - struct BE_MPU_CSRMAP_AMAP mpu; - u8 rsvd0[8192]; /* DWORD 256 */ - u8 rsvd1[8192]; /* DWORD 512 */ - struct BE_CEV_CSRMAP_AMAP cev; - u8 rsvd2[8192]; /* DWORD 1024 */ - u8 rsvd3[8192]; /* DWORD 1280 */ - u8 rsvd4[8192]; /* DWORD 1536 */ - u8 rsvd5[8192]; /* DWORD 1792 */ - u8 rsvd6[8192]; /* DWORD 2048 */ - u8 rsvd7[8192]; /* DWORD 2304 */ - u8 rsvd8[8192]; /* DWORD 2560 */ - u8 rsvd9[8192]; /* DWORD 2816 */ - u8 rsvd10[8192]; /* DWORD 3072 */ - u8 rsvd11[8192]; /* DWORD 3328 */ - u8 rsvd12[8192]; /* DWORD 3584 */ - u8 rsvd13[8192]; /* DWORD 3840 */ - u8 rsvd14[8192]; /* DWORD 4096 */ - u8 rsvd15[8192]; /* DWORD 4352 */ - u8 rsvd16[8192]; /* DWORD 4608 */ - u8 rsvd17[8192]; /* DWORD 4864 */ - u8 rsvd18[8192]; /* DWORD 5120 */ - u8 rsvd19[8192]; /* DWORD 5376 */ - u8 rsvd20[8192]; /* DWORD 5632 */ - u8 rsvd21[8192]; /* DWORD 5888 */ - u8 rsvd22[8192]; /* DWORD 6144 */ - u8 rsvd23[17152][32]; /* DWORD 6400 */ -} __packed; -struct BLADE_ENGINE_CSRMAP_AMAP { - u32 dw[23552]; -}; - -#endif /* __regmap_amap_h__ */ -- cgit v1.2.3 From 9cd88b90a6008b0d744187fab80ade4c81c6536f Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 19 Mar 2009 10:05:58 +0000 Subject: sh: sh-rtc carry interrupt rework This patch modifies the SuperH RTC driver to only enable carry interrupts when needed. So by default no interrupts are enabled with this patch. Without this patch a suspending system will most likely wake up by the carry interrupt regardless if the alarm interrupt has been enabled or not. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/rtc/rtc-sh.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index aeff2511197..21e7435daec 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -319,6 +319,25 @@ static int sh_rtc_proc(struct device *dev, struct seq_file *seq) return 0; } +static inline void sh_rtc_setcie(struct device *dev, unsigned int enable) +{ + struct sh_rtc *rtc = dev_get_drvdata(dev); + unsigned int tmp; + + spin_lock_irq(&rtc->lock); + + tmp = readb(rtc->regbase + RCR1); + + if (!enable) + tmp &= ~RCR1_CIE; + else + tmp |= RCR1_CIE; + + writeb(tmp, rtc->regbase + RCR1); + + spin_unlock_irq(&rtc->lock); +} + static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct sh_rtc *rtc = dev_get_drvdata(dev); @@ -335,9 +354,11 @@ static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) break; case RTC_UIE_OFF: rtc->periodic_freq &= ~PF_OXS; + sh_rtc_setcie(dev, 0); break; case RTC_UIE_ON: rtc->periodic_freq |= PF_OXS; + sh_rtc_setcie(dev, 1); break; case RTC_IRQP_READ: ret = put_user(rtc->rtc_dev->irq_freq, @@ -400,6 +421,10 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec--; #endif + /* only keep the carry interrupt enabled if UIE is on */ + if (!(rtc->periodic_freq & PF_OXS)) + sh_rtc_setcie(dev, 0); + dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " "mday=%d, mon=%d, year=%d, wday=%d\n", __func__, @@ -616,7 +641,6 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) { struct sh_rtc *rtc; struct resource *res; - unsigned int tmp; int ret; rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL); @@ -676,8 +700,6 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) } rtc->rtc_dev->max_user_freq = 256; - rtc->rtc_dev->irq_freq = 1; - rtc->periodic_freq = 0x60; platform_set_drvdata(pdev, rtc); @@ -724,11 +746,12 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) } } - tmp = readb(rtc->regbase + RCR1); - tmp &= ~RCR1_CF; - tmp |= RCR1_CIE; - writeb(tmp, rtc->regbase + RCR1); - + /* everything disabled by default */ + rtc->periodic_freq = 0; + rtc->rtc_dev->irq_freq = 0; + sh_rtc_setpie(&pdev->dev, 0); + sh_rtc_setaie(&pdev->dev, 0); + sh_rtc_setcie(&pdev->dev, 0); return 0; err_unmap: @@ -750,6 +773,7 @@ static int __devexit sh_rtc_remove(struct platform_device *pdev) sh_rtc_setpie(&pdev->dev, 0); sh_rtc_setaie(&pdev->dev, 0); + sh_rtc_setcie(&pdev->dev, 0); free_irq(rtc->periodic_irq, rtc); if (rtc->carry_irq > 0) { -- cgit v1.2.3 From edf22477dab5ff3be612af56ee4300ca63e11d06 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 19 Mar 2009 10:10:44 +0000 Subject: sh: sh-rtc invalid time rework This patch modifies invalid time handling in the SuperH RTC driver. Instead of zeroing the returned value at read-out time we just return an error code and reset invalid values during probe. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/rtc/rtc-sh.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 21e7435daec..9ab660c28fe 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -431,12 +431,7 @@ static int sh_rtc_read_time(struct device *dev, struct rtc_time *tm) tm->tm_sec, tm->tm_min, tm->tm_hour, tm->tm_mday, tm->tm_mon + 1, tm->tm_year, tm->tm_wday); - if (rtc_valid_tm(tm) < 0) { - dev_err(dev, "invalid date\n"); - rtc_time_to_tm(0, tm); - } - - return 0; + return rtc_valid_tm(tm); } static int sh_rtc_set_time(struct device *dev, struct rtc_time *tm) @@ -641,6 +636,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) { struct sh_rtc *rtc; struct resource *res; + struct rtc_time r; int ret; rtc = kzalloc(sizeof(struct sh_rtc), GFP_KERNEL); @@ -752,6 +748,13 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) sh_rtc_setpie(&pdev->dev, 0); sh_rtc_setaie(&pdev->dev, 0); sh_rtc_setcie(&pdev->dev, 0); + + /* reset rtc to epoch 0 if time is invalid */ + if (rtc_read_time(rtc->rtc_dev, &r) < 0) { + rtc_time_to_tm(0, &r); + rtc_set_time(rtc->rtc_dev, &r); + } + return 0; err_unmap: -- cgit v1.2.3 From 7a8fe8e320251d25274e89f610ffee936769250a Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Thu, 19 Mar 2009 10:14:41 +0000 Subject: sh: sh-rtc wakeup support Flag that the SuperH RTC supports wakeup. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/rtc/rtc-sh.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c index 9ab660c28fe..4898f7fe851 100644 --- a/drivers/rtc/rtc-sh.c +++ b/drivers/rtc/rtc-sh.c @@ -755,6 +755,7 @@ static int __devinit sh_rtc_probe(struct platform_device *pdev) rtc_set_time(rtc->rtc_dev, &r); } + device_init_wakeup(&pdev->dev, 1); return 0; err_unmap: -- cgit v1.2.3 From e88cd6ff2ce14ed7025d253b7f7f468d38415f77 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Sat, 21 Mar 2009 14:19:04 +0800 Subject: hwrng: timeriomem - Breaks an allyesconfig build on s390: CC drivers/char/hw_random/timeriomem-rng.o drivers/char/hw_random/timeriomem-rng.c: In function 'timeriomem_rng_data_read': drivers/char/hw_random/timeriomem-rng.c:60: error: implicit declaration of function 'readl' Signed-off-by: Heiko Carstens Signed-off-by: Herbert Xu --- drivers/char/hw_random/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index e86dd425a70..5fab6470f4b 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig @@ -22,7 +22,7 @@ config HW_RANDOM config HW_RANDOM_TIMERIOMEM tristate "Timer IOMEM HW Random Number Generator support" - depends on HW_RANDOM + depends on HW_RANDOM && HAS_IOMEM ---help--- This driver provides kernel-side support for a generic Random Number Generator used by reading a 'dumb' iomem address that -- cgit v1.2.3 From 18a0d89e54ca0f6f33582f99ae39867b2c975559 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Fri, 20 Mar 2009 09:22:30 +1100 Subject: radeonfb: Whack the PCI PM register until it sticks This fixes a regression introduced when we switched to using the core pci_set_power_state(). The chip seems to need the state to be written over and over again until it sticks, so we do that. Note that the code is a bit blunt, without timeout, etc... but that's pretty much because I put back in there the code exactly as it used to be before the regression. I still add a call to pci_set_power_state() at the end so that ACPI gets called appropriately on x86. Signed-off-by: Benjamin Herrenschmidt Tested-by: Raymond Wooninck Acked-by: Rafael J. Wysocki Cc: Jesse Barnes Cc: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/aty/radeon_pm.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/video/aty/radeon_pm.c b/drivers/video/aty/radeon_pm.c index 81603f85e17..c6d7cc76516 100644 --- a/drivers/video/aty/radeon_pm.c +++ b/drivers/video/aty/radeon_pm.c @@ -2507,6 +2507,25 @@ static void radeon_reinitialize_QW(struct radeonfb_info *rinfo) #endif /* CONFIG_PPC_OF */ +static void radeonfb_whack_power_state(struct radeonfb_info *rinfo, pci_power_t state) +{ + u16 pwr_cmd; + + for (;;) { + pci_read_config_word(rinfo->pdev, + rinfo->pm_reg+PCI_PM_CTRL, + &pwr_cmd); + if (pwr_cmd & 2) + break; + pwr_cmd = (pwr_cmd & ~PCI_PM_CTRL_STATE_MASK) | 2; + pci_write_config_word(rinfo->pdev, + rinfo->pm_reg+PCI_PM_CTRL, + pwr_cmd); + msleep(500); + } + rinfo->pdev->current_state = state; +} + static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) { u32 tmp; @@ -2558,6 +2577,11 @@ static void radeon_set_suspend(struct radeonfb_info *rinfo, int suspend) /* Switch PCI power management to D2. */ pci_disable_device(rinfo->pdev); pci_save_state(rinfo->pdev); + /* The chip seems to need us to whack the PM register + * repeatedly until it sticks. We do that -prior- to + * calling pci_set_power_state() + */ + radeonfb_whack_power_state(rinfo, PCI_D2); pci_set_power_state(rinfo->pdev, PCI_D2); } else { printk(KERN_DEBUG "radeonfb (%s): switching to D0 state...\n", -- cgit v1.2.3 From 7610c4f5efc495d8e15ef608c4a66932f895379a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:38 +0100 Subject: ide: fix IDE_DFLAG_NO_IO_32BIT handling * IDE_DFLAG_NO_IO_32BIT may be set by cmd640's ->init_dev method so don't clear it in ide_port_tune_devices() (+ no need to do it). * Move IDE_DFLAG_NO_IO_32BIT handling to ide_port_init_devices(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index ee8e3e7cad5..97ea5328c8e 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -848,13 +848,6 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) ide_set_dma(drive); } } - - ide_port_for_each_dev(i, drive, hwif) { - if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) - drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT; - else - drive->dev_flags &= ~IDE_DFLAG_NO_IO_32BIT; - } } /* @@ -1192,6 +1185,8 @@ static void ide_port_init_devices(ide_hwif_t *hwif) if (hwif->host_flags & IDE_HFLAG_IO_32BIT) drive->io_32bit = 1; + if (hwif->host_flags & IDE_HFLAG_NO_IO_32BIT) + drive->dev_flags |= IDE_DFLAG_NO_IO_32BIT; if (hwif->host_flags & IDE_HFLAG_UNMASK_IRQS) drive->dev_flags |= IDE_DFLAG_UNMASK; if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS) -- cgit v1.2.3 From 7a254df007b3db88bd430474030fec92e7bab22a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:39 +0100 Subject: ide: move ide_pktcmd_tf_load() to ide-atapi.c Then make it static and remove 'dma' argument. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 21 ++++++++++++++++++++- drivers/ide/ide-io.c | 20 -------------------- 2 files changed, 20 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index e9d042dba0e..09ae30f4607 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -456,6 +456,25 @@ next_irq: return ide_started; } +static void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount) +{ + ide_hwif_t *hwif = drive->hwif; + ide_task_t task; + u8 dma = drive->dma; + + memset(&task, 0, sizeof(task)); + task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM | + IDE_TFLAG_OUT_FEATURE | tf_flags; + task.tf.feature = dma; /* Use PIO/DMA */ + task.tf.lbam = bcount & 0xff; + task.tf.lbah = (bcount >> 8) & 0xff; + + ide_tf_dump(drive->name, &task.tf); + hwif->tp_ops->set_irq(hwif, 1); + SELECT_MASK(drive, 0); + hwif->tp_ops->tf_load(drive, &task); +} + static u8 ide_read_ireason(ide_drive_t *drive) { ide_task_t task; @@ -629,7 +648,7 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive) : WAIT_TAPE_CMD; } - ide_pktcmd_tf_load(drive, tf_flags, bcount, drive->dma); + ide_pktcmd_tf_load(drive, tf_flags, bcount); /* Issue the packet command */ if (drive->atapi_flags & IDE_AFLAG_DRQ_INTERRUPT) { diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index a9a6c208288..4344b6119d7 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1192,26 +1192,6 @@ void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq) } EXPORT_SYMBOL(ide_do_drive_cmd); -void ide_pktcmd_tf_load(ide_drive_t *drive, u32 tf_flags, u16 bcount, u8 dma) -{ - ide_hwif_t *hwif = drive->hwif; - ide_task_t task; - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_OUT_LBAH | IDE_TFLAG_OUT_LBAM | - IDE_TFLAG_OUT_FEATURE | tf_flags; - task.tf.feature = dma; /* Use PIO/DMA */ - task.tf.lbam = bcount & 0xff; - task.tf.lbah = (bcount >> 8) & 0xff; - - ide_tf_dump(drive->name, &task.tf); - hwif->tp_ops->set_irq(hwif, 1); - SELECT_MASK(drive, 0); - hwif->tp_ops->tf_load(drive, &task); -} - -EXPORT_SYMBOL_GPL(ide_pktcmd_tf_load); - void ide_pad_transfer(ide_drive_t *drive, int write, int len) { ide_hwif_t *hwif = drive->hwif; -- cgit v1.2.3 From d336ae3cf567185fb8fc03c10e9394920f7d5ab1 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:39 +0100 Subject: ide: no need to touch local IRQs in ide_probe_port() Remove superfluous local_save_flags() local_irq_enable_in_hardirq() ... local_irq_restore() combo. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 97ea5328c8e..eebd4ed2906 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -779,7 +779,6 @@ EXPORT_SYMBOL_GPL(ide_undecoded_slave); static int ide_probe_port(ide_hwif_t *hwif) { ide_drive_t *drive; - unsigned long flags; unsigned int irqd; int i, rc = -ENODEV; @@ -797,9 +796,6 @@ static int ide_probe_port(ide_hwif_t *hwif) if (irqd) disable_irq(hwif->irq); - local_save_flags(flags); - local_irq_enable_in_hardirq(); - if (ide_port_wait_ready(hwif) == -EBUSY) printk(KERN_DEBUG "%s: Wait for ready failed before probe !\n", hwif->name); @@ -813,8 +809,6 @@ static int ide_probe_port(ide_hwif_t *hwif) rc = 0; } - local_irq_restore(flags); - /* * Use cached IRQ number. It might be (and is...) changed by probe * code above -- cgit v1.2.3 From 7362951b4818763b6abaecd3f870739125145cc1 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:39 +0100 Subject: ide: move ->lock and ->timer init from init_irq() to ide_init_port_data() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index eebd4ed2906..63f67e3c255 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -941,11 +941,6 @@ static int init_irq (ide_hwif_t *hwif) int sa = 0; mutex_lock(&ide_cfg_mtx); - spin_lock_init(&hwif->lock); - - init_timer(&hwif->timer); - hwif->timer.function = &ide_timer_expiry; - hwif->timer.data = (unsigned long)hwif; irq_handler = hwif->host->irq_handler; if (irq_handler == NULL) @@ -1306,6 +1301,12 @@ static void ide_init_port_data(ide_hwif_t *hwif, unsigned int index) hwif->name[2] = 'e'; hwif->name[3] = '0' + index; + spin_lock_init(&hwif->lock); + + init_timer(&hwif->timer); + hwif->timer.function = &ide_timer_expiry; + hwif->timer.data = (unsigned long)hwif; + init_completion(&hwif->gendev_rel_comp); hwif->tp_ops = &default_tp_ops; -- cgit v1.2.3 From 0688d3a6ba9bf4e1df62ce627ad1daa0e2bf9148 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:39 +0100 Subject: ide: init_irq() doesn't need to hold ide_cfg_mtx Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 63f67e3c255..5deb7e71733 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -940,8 +940,6 @@ static int init_irq (ide_hwif_t *hwif) irq_handler_t irq_handler; int sa = 0; - mutex_lock(&ide_cfg_mtx); - irq_handler = hwif->host->irq_handler; if (irq_handler == NULL) irq_handler = ide_intr; @@ -979,10 +977,8 @@ static int init_irq (ide_hwif_t *hwif) printk(KERN_CONT " (serialized)"); printk(KERN_CONT "\n"); - mutex_unlock(&ide_cfg_mtx); return 0; out_up: - mutex_unlock(&ide_cfg_mtx); return 1; } -- cgit v1.2.3 From 1902a253e4b14378405de761cb444dfeef15e500 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:40 +0100 Subject: ide: remove superfluous check from ide_proc_port_register_devices() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-proc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index a7b9287ee0d..417cde56eaf 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -600,7 +600,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif) int i; ide_port_for_each_dev(i, drive, hwif) { - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0 || drive->proc) + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) continue; drive->proc = proc_mkdir(drive->name, parent); -- cgit v1.2.3 From 94635d3ecfd478ada7cedcffd9d53709074444fc Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:41 +0100 Subject: ide-acpi: no need to zero ->acpidata for devices ide_acpi_init() takes care of it. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index ec7d07fa570..0ac5c786a31 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -712,8 +712,6 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) * Send IDENTIFY for each drive */ ide_port_for_each_dev(i, drive, hwif) { - memset(drive->acpidata, 0, sizeof(*drive->acpidata)); - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) continue; -- cgit v1.2.3 From 8cd3c605624035b7f57deb8894e17c5ba6d05b2e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:41 +0100 Subject: ide-acpi: init ACPI handles early for devices Init ACPI handles for devices in ide_acpi_port_init_devices() and remove no longer needed ide_acpi_drive_get_handle(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 65 ++++++++++++++++---------------------------------- 1 file changed, 21 insertions(+), 44 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 0ac5c786a31..a3bebba1842 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -201,40 +201,6 @@ static acpi_handle ide_acpi_hwif_get_handle(ide_hwif_t *hwif) return chan_handle; } -/** - * ide_acpi_drive_get_handle - Get ACPI object handle for a given drive - * @drive: device to locate - * - * Retrieves the object handle of a given drive. According to the ACPI - * spec the drive is a child of the hwif. - * - * Returns handle on success, 0 on error. - */ -static acpi_handle ide_acpi_drive_get_handle(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - int port; - acpi_handle drive_handle; - - if (!hwif->acpidata) - return NULL; - - if (!hwif->acpidata->obj_handle) - return NULL; - - port = hwif->channel ? drive->dn - 2: drive->dn; - - DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", - drive->name, hwif->channel, port); - - - /* TBD: could also check ACPI object VALID bits */ - drive_handle = acpi_get_child(hwif->acpidata->obj_handle, port); - DEBPRINT("drive %s handle 0x%p\n", drive->name, drive_handle); - - return drive_handle; -} - /** * do_drive_get_GTF - get the drive bootup default taskfile settings * @drive: the drive for which the taskfile settings should be retrieved @@ -290,14 +256,9 @@ static int do_drive_get_GTF(ide_drive_t *drive, goto out; } - /* Get this drive's _ADR info. if not already known. */ if (!drive->acpidata->obj_handle) { - drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive); - if (!drive->acpidata->obj_handle) { - DEBPRINT("No ACPI object found for %s\n", - drive->name); - goto out; - } + DEBPRINT("No ACPI object found for %s\n", drive->name); + goto out; } /* Setting up output buffer */ @@ -652,9 +613,6 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); ide_port_for_each_dev(i, drive, hwif) { - if (!drive->acpidata->obj_handle) - drive->acpidata->obj_handle = ide_acpi_drive_get_handle(drive); - if (drive->acpidata->obj_handle && (drive->dev_flags & IDE_DFLAG_PRESENT)) { acpi_bus_set_power(drive->acpidata->obj_handle, @@ -708,6 +666,25 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) hwif->devices[0]->acpidata = &hwif->acpidata->master; hwif->devices[1]->acpidata = &hwif->acpidata->slave; + /* get _ADR info for each device */ + ide_port_for_each_dev(i, drive, hwif) { + acpi_handle dev_handle; + + if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) + continue; + + DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", + drive->name, hwif->channel, drive->dn & 1); + + /* TBD: could also check ACPI object VALID bits */ + dev_handle = acpi_get_child(hwif->acpidata->obj_handle, + drive->dn & 1); + + DEBPRINT("drive %s handle 0x%p\n", drive->name, dev_handle); + + drive->acpidata->obj_handle = dev_handle; + } + /* * Send IDENTIFY for each drive */ -- cgit v1.2.3 From 7ed5b157d9dff55bf477b4c8b4708d5d45476677 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:41 +0100 Subject: ide: add ide_for_each_present_dev() iterator * Add ide_for_each_present_dev() iterator and convert IDE code to use it. * Do some drive-by CodingStyle fixups in ide-acpi.c while at it. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 30 ++++++++++-------------------- drivers/ide/ide-iops.c | 5 ++--- drivers/ide/ide-probe.c | 38 +++++++++++++------------------------- 3 files changed, 25 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index a3bebba1842..8d6d31fcbfb 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -608,17 +608,17 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) DEBPRINT("no ACPI data for %s\n", hwif->name); return; } + /* channel first and then drives for power on and verse versa for power off */ if (on) acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D0); - ide_port_for_each_dev(i, drive, hwif) { - if (drive->acpidata->obj_handle && - (drive->dev_flags & IDE_DFLAG_PRESENT)) { + ide_port_for_each_present_dev(i, drive, hwif) { + if (drive->acpidata->obj_handle) acpi_bus_set_power(drive->acpidata->obj_handle, - on? ACPI_STATE_D0: ACPI_STATE_D3); - } + on ? ACPI_STATE_D0 : ACPI_STATE_D3); } + if (!on) acpi_bus_set_power(hwif->acpidata->obj_handle, ACPI_STATE_D3); } @@ -667,12 +667,9 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) hwif->devices[1]->acpidata = &hwif->acpidata->slave; /* get _ADR info for each device */ - ide_port_for_each_dev(i, drive, hwif) { + ide_port_for_each_present_dev(i, drive, hwif) { acpi_handle dev_handle; - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - continue; - DEBPRINT("ENTER: %s at channel#: %d port#: %d\n", drive->name, hwif->channel, drive->dn & 1); @@ -685,13 +682,8 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) drive->acpidata->obj_handle = dev_handle; } - /* - * Send IDENTIFY for each drive - */ - ide_port_for_each_dev(i, drive, hwif) { - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - continue; - + /* send IDENTIFY for each device */ + ide_port_for_each_present_dev(i, drive, hwif) { err = taskfile_lib_get_identify(drive, drive->acpidata->idbuff); if (err) DEBPRINT("identify device %s failed (%d)\n", @@ -711,9 +703,7 @@ void ide_acpi_port_init_devices(ide_hwif_t *hwif) ide_acpi_get_timing(hwif); ide_acpi_push_timing(hwif); - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) - /* Execute ACPI startup code */ - ide_acpi_exec_tfs(drive); + ide_port_for_each_present_dev(i, drive, hwif) { + ide_acpi_exec_tfs(drive); } } diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index b1892bd95c6..02fed32a404 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -1103,9 +1103,8 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE); timeout = jiffies; - ide_port_for_each_dev(i, tdrive, hwif) { - if (tdrive->dev_flags & IDE_DFLAG_PRESENT && - tdrive->dev_flags & IDE_DFLAG_PARKED && + ide_port_for_each_present_dev(i, tdrive, hwif) { + if ((tdrive->dev_flags & IDE_DFLAG_PARKED) && time_after(tdrive->sleep, timeout)) timeout = tdrive->sleep; } diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 5deb7e71733..eb0a38cd83c 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -825,22 +825,18 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) ide_drive_t *drive; int i; - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) { - if (port_ops && port_ops->quirkproc) - port_ops->quirkproc(drive); - } + ide_port_for_each_present_dev(i, drive, hwif) { + if (port_ops && port_ops->quirkproc) + port_ops->quirkproc(drive); } - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) { - ide_set_max_pio(drive); + ide_port_for_each_present_dev(i, drive, hwif) { + ide_set_max_pio(drive); - drive->dev_flags |= IDE_DFLAG_NICE1; + drive->dev_flags |= IDE_DFLAG_NICE1; - if (hwif->dma_ops) - ide_set_dma(drive); - } + if (hwif->dma_ops) + ide_set_dma(drive); } } @@ -911,10 +907,7 @@ static int ide_port_setup_devices(ide_hwif_t *hwif) int i, j = 0; mutex_lock(&ide_cfg_mtx); - ide_port_for_each_dev(i, drive, hwif) { - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - continue; - + ide_port_for_each_present_dev(i, drive, hwif) { if (ide_init_queue(drive)) { printk(KERN_ERR "ide: failed to init %s\n", drive->name); @@ -1139,13 +1132,10 @@ static void hwif_register_devices(ide_hwif_t *hwif) ide_drive_t *drive; unsigned int i; - ide_port_for_each_dev(i, drive, hwif) { + ide_port_for_each_present_dev(i, drive, hwif) { struct device *dev = &drive->gendev; int ret; - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - continue; - dev_set_name(dev, "%u.%u", hwif->index, i); dev->parent = &hwif->gendev; dev->bus = &ide_bus_type; @@ -1610,11 +1600,9 @@ static void __ide_port_unregister_devices(ide_hwif_t *hwif) ide_drive_t *drive; int i; - ide_port_for_each_dev(i, drive, hwif) { - if (drive->dev_flags & IDE_DFLAG_PRESENT) { - device_unregister(&drive->gendev); - wait_for_completion(&drive->gendev_rel_comp); - } + ide_port_for_each_present_dev(i, drive, hwif) { + device_unregister(&drive->gendev); + wait_for_completion(&drive->gendev_rel_comp); } } -- cgit v1.2.3 From 8b803bd184e3f6892284d4b50801b9ec85cd9b96 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:41 +0100 Subject: ide: sanitize ACPI initialization * ide_acpi_init() -> ide_acpi_init_port() * ide_acpi_blacklist() -> ide_acpi_init() * Call ide_acpi_init() only once (do it during IDE core initialization) and cleanup the function accordingly. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 12 +++--------- drivers/ide/ide-probe.c | 2 +- drivers/ide/ide.c | 2 ++ 3 files changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 8d6d31fcbfb..ba5932d7b1b 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -89,12 +89,8 @@ static const struct dmi_system_id ide_acpi_dmi_table[] = { { } /* terminate list */ }; -static int ide_acpi_blacklist(void) +int ide_acpi_init(void) { - static int done; - if (done) - return 0; - done = 1; dmi_check_system(ide_acpi_dmi_table); return 0; } @@ -624,7 +620,7 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) } /** - * ide_acpi_init - initialize the ACPI link for an IDE interface + * ide_acpi_init_port - initialize the ACPI link for an IDE interface * @hwif: target IDE interface (channel) * * The ACPI spec is not quite clear when the drive identify buffer @@ -634,10 +630,8 @@ void ide_acpi_set_state(ide_hwif_t *hwif, int on) * So we get the information during startup; but this means that * any changes during run-time will be lost after resume. */ -void ide_acpi_init(ide_hwif_t *hwif) +void ide_acpi_init_port(ide_hwif_t *hwif) { - ide_acpi_blacklist(); - hwif->acpidata = kzalloc(sizeof(struct ide_acpi_hwif_link), GFP_KERNEL); if (!hwif->acpidata) return; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index eb0a38cd83c..a51ad2bd62b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1543,7 +1543,7 @@ int ide_host_register(struct ide_host *host, const struct ide_port_info *d, j++; - ide_acpi_init(hwif); + ide_acpi_init_port(hwif); if (hwif->present) ide_acpi_port_init_devices(hwif); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 0920e3b0c96..c779aa24dbe 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -527,6 +527,8 @@ static int __init ide_init(void) goto out_port_class; } + ide_acpi_init(); + proc_ide_create(); return 0; -- cgit v1.2.3 From 2f0d0fd2a605666d38e290c5c0d2907484352dc4 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:42 +0100 Subject: ide-acpi: cleanup do_drive_get_GTF() * ide_noacpi is already checked by ide_acpi_exec_tfs() which is the only user of do_drive_get_GTF(). * ide_acpi_exec_tfs() prints sufficient debug info about the device so no need to have excessive data about port/host. * It is sufficient to check for drive->acpidata->obj_handle as it will be NULL if dev == NULL or hwif->acpidata == NULL or device is not present. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index ba5932d7b1b..6b3123612f1 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -219,39 +219,12 @@ static int do_drive_get_GTF(ide_drive_t *drive, acpi_status status; struct acpi_buffer output; union acpi_object *out_obj; - ide_hwif_t *hwif = drive->hwif; - struct device *dev = hwif->gendev.parent; int err = -ENODEV; - int port; *gtf_length = 0; *gtf_address = 0UL; *obj_loc = 0UL; - if (ide_noacpi) - return 0; - - if (!dev) { - DEBPRINT("no PCI device for %s\n", hwif->name); - goto out; - } - - if (!hwif->acpidata) { - DEBPRINT("no ACPI data for %s\n", hwif->name); - goto out; - } - - port = hwif->channel ? drive->dn - 2: drive->dn; - - DEBPRINT("ENTER: %s at %s, port#: %d, hard_port#: %d\n", - hwif->name, dev_name(dev), port, hwif->channel); - - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) { - DEBPRINT("%s drive %d:%d not present\n", - hwif->name, hwif->channel, port); - goto out; - } - if (!drive->acpidata->obj_handle) { DEBPRINT("No ACPI object found for %s\n", drive->name); goto out; -- cgit v1.2.3 From 1f5892a5d21c905b1614cbd6bd8c5ad2cfbc106f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:42 +0100 Subject: ide-acpi: cleanup do_drive_set_taskfiles() * ide_noacpi is already checked by ide_acpi_exec_tfs() which is the only user of do_drive_set_taskfiles(). * ide_acpi_exec_tfs() prints sufficient debug info about the device so no need to do it again. * do_drive_get_GTF() + ide_acpi_exec_tfs() make sure that this function will never be called with incorrect gtf_length argument or if device is not present. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index 6b3123612f1..ce5b213e2bc 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -334,32 +334,14 @@ static int do_drive_set_taskfiles(ide_drive_t *drive, unsigned int gtf_length, unsigned long gtf_address) { - int rc = -ENODEV, err; + int rc = 0, err; int gtf_count = gtf_length / REGS_PER_GTF; int ix; struct taskfile_array *gtf; - if (ide_noacpi) - return 0; - - DEBPRINT("ENTER: %s, hard_port#: %d\n", drive->name, drive->dn); - - if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) - goto out; - - if (!gtf_count) /* shouldn't be here */ - goto out; - DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n", gtf_length, gtf_length, gtf_count, gtf_address); - if (gtf_length % REGS_PER_GTF) { - printk(KERN_ERR "%s: unexpected GTF length (%d)\n", - __func__, gtf_length); - goto out; - } - - rc = 0; for (ix = 0; ix < gtf_count; ix++) { gtf = (struct taskfile_array *) (gtf_address + ix * REGS_PER_GTF); @@ -370,7 +352,6 @@ static int do_drive_set_taskfiles(ide_drive_t *drive, rc = err; } -out: return rc; } -- cgit v1.2.3 From b0b391430bea405ced6038e4cf4d8cf831511935 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:42 +0100 Subject: ide-acpi: remove taskfile_load_raw() * taskfile_load_raw() is used only by do_drive_set_taskfiles() so inline it there. While at it: - rename 'args' variable to 'task' - remove struct taskfile_array - do ide_acpigtf check early - use REGS_PER_GTF Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-acpi.c | 71 +++++++++++++++++--------------------------------- 1 file changed, 24 insertions(+), 47 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-acpi.c b/drivers/ide/ide-acpi.c index ce5b213e2bc..5b704f1ea90 100644 --- a/drivers/ide/ide-acpi.c +++ b/drivers/ide/ide-acpi.c @@ -20,9 +20,6 @@ #include #define REGS_PER_GTF 7 -struct taskfile_array { - u8 tfa[REGS_PER_GTF]; /* regs. 0x1f1 - 0x1f7 */ -}; struct GTM_buffer { u32 PIO_speed0; @@ -284,43 +281,6 @@ out: return err; } -/** - * taskfile_load_raw - send taskfile registers to drive - * @drive: drive to which output is sent - * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7) - * - * Outputs IDE taskfile to the drive. - */ -static int taskfile_load_raw(ide_drive_t *drive, - const struct taskfile_array *gtf) -{ - ide_task_t args; - int err = 0; - - DEBPRINT("(0x1f1-1f7): hex: " - "%02x %02x %02x %02x %02x %02x %02x\n", - gtf->tfa[0], gtf->tfa[1], gtf->tfa[2], - gtf->tfa[3], gtf->tfa[4], gtf->tfa[5], gtf->tfa[6]); - - memset(&args, 0, sizeof(ide_task_t)); - - /* convert gtf to IDE Taskfile */ - memcpy(&args.tf_array[7], >f->tfa, 7); - args.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - - if (!ide_acpigtf) { - DEBPRINT("_GTF execution disabled\n"); - return err; - } - - err = ide_no_data_taskfile(drive, &args); - if (err) - printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n", - __func__, err); - - return err; -} - /** * do_drive_set_taskfiles - write the drive taskfile settings from _GTF * @drive: the drive to which the taskfile command should be sent @@ -337,19 +297,36 @@ static int do_drive_set_taskfiles(ide_drive_t *drive, int rc = 0, err; int gtf_count = gtf_length / REGS_PER_GTF; int ix; - struct taskfile_array *gtf; DEBPRINT("total GTF bytes=%u (0x%x), gtf_count=%d, addr=0x%lx\n", gtf_length, gtf_length, gtf_count, gtf_address); + /* send all taskfile registers (0x1f1-0x1f7) *in*that*order* */ for (ix = 0; ix < gtf_count; ix++) { - gtf = (struct taskfile_array *) - (gtf_address + ix * REGS_PER_GTF); - - /* send all TaskFile registers (0x1f1-0x1f7) *in*that*order* */ - err = taskfile_load_raw(drive, gtf); - if (err) + u8 *gtf = (u8 *)(gtf_address + ix * REGS_PER_GTF); + ide_task_t task; + + DEBPRINT("(0x1f1-1f7): " + "hex: %02x %02x %02x %02x %02x %02x %02x\n", + gtf[0], gtf[1], gtf[2], + gtf[3], gtf[4], gtf[5], gtf[6]); + + if (!ide_acpigtf) { + DEBPRINT("_GTF execution disabled\n"); + continue; + } + + /* convert GTF to taskfile */ + memset(&task, 0, sizeof(ide_task_t)); + memcpy(&task.tf_array[7], gtf, REGS_PER_GTF); + task.tf_flags = IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + + err = ide_no_data_taskfile(drive, &task); + if (err) { + printk(KERN_ERR "%s: ide_no_data_taskfile failed: %u\n", + __func__, err); rc = err; + } } return rc; -- cgit v1.2.3 From 2b9ae4608ffbdb57c1d5fe9db440810a995a91fa Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:42 +0100 Subject: ide: remove stale comments from drive_is_ready() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 9 --------- 1 file changed, 9 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 02fed32a404..cd1f2e464c4 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -438,9 +438,6 @@ void ide_fixstring (u8 *s, const int bytecount, const int byteswap) EXPORT_SYMBOL(ide_fixstring); -/* - * Needed for PCI irq sharing - */ int drive_is_ready (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; @@ -449,12 +446,6 @@ int drive_is_ready (ide_drive_t *drive) if (drive->waiting_for_dma) return hwif->dma_ops->dma_test_irq(drive); - /* - * We do a passive status test under shared PCI interrupts on - * cards that truly share the ATA side interrupt, but may also share - * an interrupt with another pci card/device. We make no assumptions - * about possible isa-pnp and pci-pnp issues yet. - */ if (hwif->io_ports.ctl_addr && (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) stat = hwif->tp_ops->read_altstatus(hwif); -- cgit v1.2.3 From 75a0cff4e8ed47584dd15fbde2172ebc4c051bb2 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:43 +0100 Subject: ide: unexport ide_devset_execute() There are no modular ide_devset_execute() users left so unexport it. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 4344b6119d7..d90cf5d0814 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -513,7 +513,6 @@ int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, return ret; } -EXPORT_SYMBOL_GPL(ide_devset_execute); static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) { -- cgit v1.2.3 From b6a45a0b1e9a358b81201659cf87b023e3ec73e0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:43 +0100 Subject: ide: move drive_is_ready() to ide-io.c Move drive_is_ready() to ide-io.c, then make it static. Also make some minor CodingStyle fixups while at it. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 23 +++++++++++++++++++++++ drivers/ide/ide-iops.c | 25 ------------------------- 2 files changed, 23 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index d90cf5d0814..835cf646bb0 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -887,6 +887,29 @@ static void ide_plug_device(ide_drive_t *drive) spin_unlock_irqrestore(q->queue_lock, flags); } +static int drive_is_ready(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u8 stat = 0; + + if (drive->waiting_for_dma) + return hwif->dma_ops->dma_test_irq(drive); + + if (hwif->io_ports.ctl_addr && + (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) + stat = hwif->tp_ops->read_altstatus(hwif); + else + /* Note: this may clear a pending IRQ!! */ + stat = hwif->tp_ops->read_status(hwif); + + if (stat & ATA_BUSY) + /* drive busy: definitely not interrupting */ + return 0; + + /* drive ready: *might* be interrupting */ + return 1; +} + /** * ide_timer_expiry - handle lack of an IDE interrupt * @data: timer callback magic (hwif) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index cd1f2e464c4..ee9c6034278 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -438,31 +438,6 @@ void ide_fixstring (u8 *s, const int bytecount, const int byteswap) EXPORT_SYMBOL(ide_fixstring); -int drive_is_ready (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 stat = 0; - - if (drive->waiting_for_dma) - return hwif->dma_ops->dma_test_irq(drive); - - if (hwif->io_ports.ctl_addr && - (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) - stat = hwif->tp_ops->read_altstatus(hwif); - else - /* Note: this may clear a pending IRQ!! */ - stat = hwif->tp_ops->read_status(hwif); - - if (stat & ATA_BUSY) - /* drive busy: definitely not interrupting */ - return 0; - - /* drive ready: *might* be interrupting */ - return 1; -} - -EXPORT_SYMBOL(drive_is_ready); - /* * This routine busy-waits for the drive status to be not "busy". * It then checks the status for all of the "good" bits and none -- cgit v1.2.3 From 65ca5377322c7543163066f373ae9e6b0ad8de8a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:43 +0100 Subject: ide: move ide_dma_timeout_retry() to ide-dma.c Move ide_dma_timeout_retry() to ide-dma.c and add static inline version for CONFIG_BLK_DEV_IDEDMA=n. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-dma.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ drivers/ide/ide-io.c | 57 --------------------------------------------------- 2 files changed, 57 insertions(+), 57 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index 059c90bb5ad..a878f4734f8 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c @@ -470,6 +470,63 @@ void ide_dma_timeout(ide_drive_t *drive) } EXPORT_SYMBOL_GPL(ide_dma_timeout); +/* + * un-busy the port etc, and clear any pending DMA status. we want to + * retry the current request in pio mode instead of risking tossing it + * all away + */ +ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) +{ + ide_hwif_t *hwif = drive->hwif; + struct request *rq; + ide_startstop_t ret = ide_stopped; + + /* + * end current dma transaction + */ + + if (error < 0) { + printk(KERN_WARNING "%s: DMA timeout error\n", drive->name); + (void)hwif->dma_ops->dma_end(drive); + ret = ide_error(drive, "dma timeout error", + hwif->tp_ops->read_status(hwif)); + } else { + printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name); + hwif->dma_ops->dma_timeout(drive); + } + + /* + * disable dma for now, but remember that we did so because of + * a timeout -- we'll reenable after we finish this next request + * (or rather the first chunk of it) in pio. + */ + drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY; + drive->retry_pio++; + ide_dma_off_quietly(drive); + + /* + * un-busy drive etc and make sure request is sane + */ + + rq = hwif->rq; + if (!rq) + goto out; + + hwif->rq = NULL; + + rq->errors = 0; + + if (!rq->bio) + goto out; + + rq->sector = rq->bio->bi_sector; + rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; + rq->hard_cur_sectors = rq->current_nr_sectors; + rq->buffer = bio_data(rq->bio); +out: + return ret; +} + void ide_release_dma_engine(ide_hwif_t *hwif) { if (hwif->dmatable_cpu) { diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 835cf646bb0..557b15700ea 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -819,63 +819,6 @@ plug_device_2: blk_plug_device(q); } -/* - * un-busy the port etc, and clear any pending DMA status. we want to - * retry the current request in pio mode instead of risking tossing it - * all away - */ -static ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) -{ - ide_hwif_t *hwif = drive->hwif; - struct request *rq; - ide_startstop_t ret = ide_stopped; - - /* - * end current dma transaction - */ - - if (error < 0) { - printk(KERN_WARNING "%s: DMA timeout error\n", drive->name); - (void)hwif->dma_ops->dma_end(drive); - ret = ide_error(drive, "dma timeout error", - hwif->tp_ops->read_status(hwif)); - } else { - printk(KERN_WARNING "%s: DMA timeout retry\n", drive->name); - hwif->dma_ops->dma_timeout(drive); - } - - /* - * disable dma for now, but remember that we did so because of - * a timeout -- we'll reenable after we finish this next request - * (or rather the first chunk of it) in pio. - */ - drive->dev_flags |= IDE_DFLAG_DMA_PIO_RETRY; - drive->retry_pio++; - ide_dma_off_quietly(drive); - - /* - * un-busy drive etc and make sure request is sane - */ - - rq = hwif->rq; - if (!rq) - goto out; - - hwif->rq = NULL; - - rq->errors = 0; - - if (!rq->bio) - goto out; - - rq->sector = rq->bio->bi_sector; - rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; - rq->hard_cur_sectors = rq->current_nr_sectors; - rq->buffer = bio_data(rq->bio); -out: - return ret; -} - static void ide_plug_device(ide_drive_t *drive) { struct request_queue *q = drive->queue; -- cgit v1.2.3 From 1866082339597930c5b77aad8de34ab4fbb5724f Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:44 +0100 Subject: ide: remove ide_do_drive_cmd() * Use elv_add_request() instead of __elv_add_request() in ide_do_drive_cmd(). * ide_do_drive_cmd() is used only in ide-{atapi,cd}.c so inline it there. There should be no functional changes caused by this patch. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 5 ++++- drivers/ide/ide-cd.c | 4 +++- drivers/ide/ide-io.c | 28 ---------------------------- 3 files changed, 7 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 09ae30f4607..3044c51c06a 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -149,7 +149,10 @@ static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, memcpy(rq->cmd, pc->c, 12); if (drive->media == ide_tape) rq->cmd[13] = REQ_IDETAPE_PC1; - ide_do_drive_cmd(drive, rq); + + drive->hwif->rq = NULL; + + elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); } /* diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index ddfbea41d29..2177cd11664 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -242,7 +242,9 @@ static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x\n", failed_command->cmd[0]); - ide_do_drive_cmd(drive, rq); + drive->hwif->rq = NULL; + + elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); } static void cdrom_end_request(ide_drive_t *drive, int uptodate) diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 557b15700ea..56be3375bee 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -1129,34 +1129,6 @@ out_early: } EXPORT_SYMBOL_GPL(ide_intr); -/** - * ide_do_drive_cmd - issue IDE special command - * @drive: device to issue command - * @rq: request to issue - * - * This function issues a special IDE device request - * onto the request queue. - * - * the rq is queued at the head of the request queue, displacing - * the currently-being-processed request and this function - * returns immediately without waiting for the new rq to be - * completed. This is VERY DANGEROUS, and is intended for - * careful use by the ATAPI tape/cdrom driver code. - */ - -void ide_do_drive_cmd(ide_drive_t *drive, struct request *rq) -{ - struct request_queue *q = drive->queue; - unsigned long flags; - - drive->hwif->rq = NULL; - - spin_lock_irqsave(q->queue_lock, flags); - __elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 0); - spin_unlock_irqrestore(q->queue_lock, flags); -} -EXPORT_SYMBOL(ide_do_drive_cmd); - void ide_pad_transfer(ide_drive_t *drive, int write, int len) { ide_hwif_t *hwif = drive->hwif; -- cgit v1.2.3 From 1bc6daae4aba9194f8ff6801af8367a1a4718965 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:44 +0100 Subject: ide: factor out processing of special commands from ide_special_rq() Factor out processing of special commands from ide_special_rq() to ide_do_devset() and ide_do_park_unpark(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 75 ++++++++++++++++++++++++++++------------------------ 1 file changed, 41 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 56be3375bee..c37883ae266 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -514,46 +514,53 @@ int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, return ret; } +static ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) +{ + int err, (*setfunc)(ide_drive_t *, int) = rq->special; + + err = setfunc(drive, *(int *)&rq->cmd[1]); + if (err) + rq->errors = err; + else + err = 1; + ide_end_request(drive, err, 0); + return ide_stopped; +} + +static ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq) +{ + ide_task_t task; + struct ide_taskfile *tf = &task.tf; + + memset(&task, 0, sizeof(task)); + if (rq->cmd[0] == REQ_PARK_HEADS) { + drive->sleep = *(unsigned long *)rq->special; + drive->dev_flags |= IDE_DFLAG_SLEEPING; + tf->command = ATA_CMD_IDLEIMMEDIATE; + tf->feature = 0x44; + tf->lbal = 0x4c; + tf->lbam = 0x4e; + tf->lbah = 0x55; + task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; + } else /* cmd == REQ_UNPARK_HEADS */ + tf->command = ATA_CMD_CHK_POWER; + + task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + task.rq = rq; + drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA; + return do_rw_taskfile(drive, &task); +} + static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) { u8 cmd = rq->cmd[0]; - if (cmd == REQ_PARK_HEADS || cmd == REQ_UNPARK_HEADS) { - ide_task_t task; - struct ide_taskfile *tf = &task.tf; - - memset(&task, 0, sizeof(task)); - if (cmd == REQ_PARK_HEADS) { - drive->sleep = *(unsigned long *)rq->special; - drive->dev_flags |= IDE_DFLAG_SLEEPING; - tf->command = ATA_CMD_IDLEIMMEDIATE; - tf->feature = 0x44; - tf->lbal = 0x4c; - tf->lbam = 0x4e; - tf->lbah = 0x55; - task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; - } else /* cmd == REQ_UNPARK_HEADS */ - tf->command = ATA_CMD_CHK_POWER; - - task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - task.rq = rq; - drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA; - return do_rw_taskfile(drive, &task); - } - switch (cmd) { + case REQ_PARK_HEADS: + case REQ_UNPARK_HEADS: + return ide_do_park_unpark(drive, rq); case REQ_DEVSET_EXEC: - { - int err, (*setfunc)(ide_drive_t *, int) = rq->special; - - err = setfunc(drive, *(int *)&rq->cmd[1]); - if (err) - rq->errors = err; - else - err = 1; - ide_end_request(drive, err, 0); - return ide_stopped; - } + return ide_do_devset(drive, rq); case REQ_DRIVE_RESET: return ide_do_reset(drive); default: -- cgit v1.2.3 From c4e66c36cce3f23d68013c4112013123ffe80bdb Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:44 +0100 Subject: ide: move ide_do_park_unpark() to ide-park.c Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-io.c | 24 ------------------------ drivers/ide/ide-park.c | 25 +++++++++++++++++++++++++ 2 files changed, 25 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index c37883ae266..16e47989fcf 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -527,30 +527,6 @@ static ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) return ide_stopped; } -static ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq) -{ - ide_task_t task; - struct ide_taskfile *tf = &task.tf; - - memset(&task, 0, sizeof(task)); - if (rq->cmd[0] == REQ_PARK_HEADS) { - drive->sleep = *(unsigned long *)rq->special; - drive->dev_flags |= IDE_DFLAG_SLEEPING; - tf->command = ATA_CMD_IDLEIMMEDIATE; - tf->feature = 0x44; - tf->lbal = 0x4c; - tf->lbam = 0x4e; - tf->lbah = 0x55; - task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; - } else /* cmd == REQ_UNPARK_HEADS */ - tf->command = ATA_CMD_CHK_POWER; - - task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE; - task.rq = rq; - drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA; - return do_rw_taskfile(drive, &task); -} - static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) { u8 cmd = rq->cmd[0]; diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index c875a957596..f30e52152fc 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c @@ -1,5 +1,6 @@ #include #include +#include #include #include @@ -60,6 +61,30 @@ out: return; } +ide_startstop_t ide_do_park_unpark(ide_drive_t *drive, struct request *rq) +{ + ide_task_t task; + struct ide_taskfile *tf = &task.tf; + + memset(&task, 0, sizeof(task)); + if (rq->cmd[0] == REQ_PARK_HEADS) { + drive->sleep = *(unsigned long *)rq->special; + drive->dev_flags |= IDE_DFLAG_SLEEPING; + tf->command = ATA_CMD_IDLEIMMEDIATE; + tf->feature = 0x44; + tf->lbal = 0x4c; + tf->lbam = 0x4e; + tf->lbah = 0x55; + task.tf_flags |= IDE_TFLAG_CUSTOM_HANDLER; + } else /* cmd == REQ_UNPARK_HEADS */ + tf->command = ATA_CMD_CHK_POWER; + + task.tf_flags |= IDE_TFLAG_TF | IDE_TFLAG_DEVICE; + task.rq = rq; + drive->hwif->data_phase = task.data_phase = TASKFILE_NO_DATA; + return do_rw_taskfile(drive, &task); +} + ssize_t ide_park_show(struct device *dev, struct device_attribute *attr, char *buf) { -- cgit v1.2.3 From 11938c929022bb92b1a42f5e1289524a1e465dc0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:44 +0100 Subject: ide: move device settings code to ide-devsets.c Remove stale comment from ide.c while at it. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Makefile | 3 +- drivers/ide/ide-devsets.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++ drivers/ide/ide-io.c | 37 --------- drivers/ide/ide.c | 154 ------------------------------------- 4 files changed, 192 insertions(+), 192 deletions(-) create mode 100644 drivers/ide/ide-devsets.c (limited to 'drivers') diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 1c326d94aa6..83a970ee4bf 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -5,7 +5,8 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ - ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o ide-sysfs.o + ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o \ + ide-sysfs.o ide-devsets.o # core IDE code ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o diff --git a/drivers/ide/ide-devsets.c b/drivers/ide/ide-devsets.c new file mode 100644 index 00000000000..7c3953414d4 --- /dev/null +++ b/drivers/ide/ide-devsets.c @@ -0,0 +1,190 @@ + +#include +#include + +DEFINE_MUTEX(ide_setting_mtx); + +ide_devset_get(io_32bit, io_32bit); + +static int set_io_32bit(ide_drive_t *drive, int arg) +{ + if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) + return -EPERM; + + if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) + return -EINVAL; + + drive->io_32bit = arg; + + return 0; +} + +ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS); + +static int set_ksettings(ide_drive_t *drive, int arg) +{ + if (arg < 0 || arg > 1) + return -EINVAL; + + if (arg) + drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS; + else + drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS; + + return 0; +} + +ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA); + +static int set_using_dma(ide_drive_t *drive, int arg) +{ +#ifdef CONFIG_BLK_DEV_IDEDMA + int err = -EPERM; + + if (arg < 0 || arg > 1) + return -EINVAL; + + if (ata_id_has_dma(drive->id) == 0) + goto out; + + if (drive->hwif->dma_ops == NULL) + goto out; + + err = 0; + + if (arg) { + if (ide_set_dma(drive)) + err = -EIO; + } else + ide_dma_off(drive); + +out: + return err; +#else + if (arg < 0 || arg > 1) + return -EINVAL; + + return -EPERM; +#endif +} + +/* + * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away + */ +static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) +{ + switch (req_pio) { + case 202: + case 201: + case 200: + case 102: + case 101: + case 100: + return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0; + case 9: + case 8: + return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0; + case 7: + case 6: + return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0; + default: + return 0; + } +} + +static int set_pio_mode(ide_drive_t *drive, int arg) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (arg < 0 || arg > 255) + return -EINVAL; + + if (port_ops == NULL || port_ops->set_pio_mode == NULL || + (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) + return -ENOSYS; + + if (set_pio_mode_abuse(drive->hwif, arg)) { + if (arg == 8 || arg == 9) { + unsigned long flags; + + /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ + spin_lock_irqsave(&hwif->lock, flags); + port_ops->set_pio_mode(drive, arg); + spin_unlock_irqrestore(&hwif->lock, flags); + } else + port_ops->set_pio_mode(drive, arg); + } else { + int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); + + ide_set_pio(drive, arg); + + if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) { + if (keep_dma) + ide_dma_on(drive); + } + } + + return 0; +} + +ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK); + +static int set_unmaskirq(ide_drive_t *drive, int arg) +{ + if (drive->dev_flags & IDE_DFLAG_NO_UNMASK) + return -EPERM; + + if (arg < 0 || arg > 1) + return -EINVAL; + + if (arg) + drive->dev_flags |= IDE_DFLAG_UNMASK; + else + drive->dev_flags &= ~IDE_DFLAG_UNMASK; + + return 0; +} + +ide_ext_devset_rw_sync(io_32bit, io_32bit); +ide_ext_devset_rw_sync(keepsettings, ksettings); +ide_ext_devset_rw_sync(unmaskirq, unmaskirq); +ide_ext_devset_rw_sync(using_dma, using_dma); +__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); + +int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, + int arg) +{ + struct request_queue *q = drive->queue; + struct request *rq; + int ret = 0; + + if (!(setting->flags & DS_SYNC)) + return setting->set(drive, arg); + + rq = blk_get_request(q, READ, __GFP_WAIT); + rq->cmd_type = REQ_TYPE_SPECIAL; + rq->cmd_len = 5; + rq->cmd[0] = REQ_DEVSET_EXEC; + *(int *)&rq->cmd[1] = arg; + rq->special = setting->set; + + if (blk_execute_rq(q, NULL, rq, 0)) + ret = rq->errors; + blk_put_request(rq); + + return ret; +} + +ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) +{ + int err, (*setfunc)(ide_drive_t *, int) = rq->special; + + err = setfunc(drive, *(int *)&rq->cmd[1]); + if (err) + rq->errors = err; + else + err = 1; + ide_end_request(drive, err, 0); + return ide_stopped; +} diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 16e47989fcf..74d1a3e6825 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -490,43 +490,6 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, return ide_stopped; } -int ide_devset_execute(ide_drive_t *drive, const struct ide_devset *setting, - int arg) -{ - struct request_queue *q = drive->queue; - struct request *rq; - int ret = 0; - - if (!(setting->flags & DS_SYNC)) - return setting->set(drive, arg); - - rq = blk_get_request(q, READ, __GFP_WAIT); - rq->cmd_type = REQ_TYPE_SPECIAL; - rq->cmd_len = 5; - rq->cmd[0] = REQ_DEVSET_EXEC; - *(int *)&rq->cmd[1] = arg; - rq->special = setting->set; - - if (blk_execute_rq(q, NULL, rq, 0)) - ret = rq->errors; - blk_put_request(rq); - - return ret; -} - -static ide_startstop_t ide_do_devset(ide_drive_t *drive, struct request *rq) -{ - int err, (*setfunc)(ide_drive_t *, int) = rq->special; - - err = setfunc(drive, *(int *)&rq->cmd[1]); - if (err) - rq->errors = err; - else - err = 1; - ide_end_request(drive, err, 0); - return ide_stopped; -} - static ide_startstop_t ide_special_rq(ide_drive_t *drive, struct request *rq) { u8 cmd = rq->cmd[0]; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index c779aa24dbe..92c9b90931e 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -62,160 +62,6 @@ struct class *ide_port_class; -/* - * Locks for IDE setting functionality - */ - -DEFINE_MUTEX(ide_setting_mtx); - -ide_devset_get(io_32bit, io_32bit); - -static int set_io_32bit(ide_drive_t *drive, int arg) -{ - if (drive->dev_flags & IDE_DFLAG_NO_IO_32BIT) - return -EPERM; - - if (arg < 0 || arg > 1 + (SUPPORT_VLB_SYNC << 1)) - return -EINVAL; - - drive->io_32bit = arg; - - return 0; -} - -ide_devset_get_flag(ksettings, IDE_DFLAG_KEEP_SETTINGS); - -static int set_ksettings(ide_drive_t *drive, int arg) -{ - if (arg < 0 || arg > 1) - return -EINVAL; - - if (arg) - drive->dev_flags |= IDE_DFLAG_KEEP_SETTINGS; - else - drive->dev_flags &= ~IDE_DFLAG_KEEP_SETTINGS; - - return 0; -} - -ide_devset_get_flag(using_dma, IDE_DFLAG_USING_DMA); - -static int set_using_dma(ide_drive_t *drive, int arg) -{ -#ifdef CONFIG_BLK_DEV_IDEDMA - int err = -EPERM; - - if (arg < 0 || arg > 1) - return -EINVAL; - - if (ata_id_has_dma(drive->id) == 0) - goto out; - - if (drive->hwif->dma_ops == NULL) - goto out; - - err = 0; - - if (arg) { - if (ide_set_dma(drive)) - err = -EIO; - } else - ide_dma_off(drive); - -out: - return err; -#else - if (arg < 0 || arg > 1) - return -EINVAL; - - return -EPERM; -#endif -} - -/* - * handle HDIO_SET_PIO_MODE ioctl abusers here, eventually it will go away - */ -static int set_pio_mode_abuse(ide_hwif_t *hwif, u8 req_pio) -{ - switch (req_pio) { - case 202: - case 201: - case 200: - case 102: - case 101: - case 100: - return (hwif->host_flags & IDE_HFLAG_ABUSE_DMA_MODES) ? 1 : 0; - case 9: - case 8: - return (hwif->host_flags & IDE_HFLAG_ABUSE_PREFETCH) ? 1 : 0; - case 7: - case 6: - return (hwif->host_flags & IDE_HFLAG_ABUSE_FAST_DEVSEL) ? 1 : 0; - default: - return 0; - } -} - -static int set_pio_mode(ide_drive_t *drive, int arg) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (arg < 0 || arg > 255) - return -EINVAL; - - if (port_ops == NULL || port_ops->set_pio_mode == NULL || - (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) - return -ENOSYS; - - if (set_pio_mode_abuse(drive->hwif, arg)) { - if (arg == 8 || arg == 9) { - unsigned long flags; - - /* take lock for IDE_DFLAG_[NO_]UNMASK/[NO_]IO_32BIT */ - spin_lock_irqsave(&hwif->lock, flags); - port_ops->set_pio_mode(drive, arg); - spin_unlock_irqrestore(&hwif->lock, flags); - } else - port_ops->set_pio_mode(drive, arg); - } else { - int keep_dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); - - ide_set_pio(drive, arg); - - if (hwif->host_flags & IDE_HFLAG_SET_PIO_MODE_KEEP_DMA) { - if (keep_dma) - ide_dma_on(drive); - } - } - - return 0; -} - -ide_devset_get_flag(unmaskirq, IDE_DFLAG_UNMASK); - -static int set_unmaskirq(ide_drive_t *drive, int arg) -{ - if (drive->dev_flags & IDE_DFLAG_NO_UNMASK) - return -EPERM; - - if (arg < 0 || arg > 1) - return -EINVAL; - - if (arg) - drive->dev_flags |= IDE_DFLAG_UNMASK; - else - drive->dev_flags &= ~IDE_DFLAG_UNMASK; - - return 0; -} - -ide_ext_devset_rw_sync(io_32bit, io_32bit); -ide_ext_devset_rw_sync(keepsettings, ksettings); -ide_ext_devset_rw_sync(unmaskirq, unmaskirq); -ide_ext_devset_rw_sync(using_dma, using_dma); -__IDE_DEVSET(pio_mode, DS_SYNC, NULL, set_pio_mode); - /** * ide_device_get - get an additional reference to a ide_drive_t * @drive: device to get a reference to -- cgit v1.2.3 From 7eeaaaa52285d5e6cb79f515e99c591dcb9d04fe Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:46 +0100 Subject: ide: move xfer mode tuning code to ide-xfer-mode.c * Move xfer mode tuning code to ide-xfer-mode.c. * Add CONFIG_IDE_XFER_MODE config option to be selected by host drivers that support xfer mode tuning. * Add CONFIG_IDE_XFER_MODE=n static inline versions of ide_set_pio() and ide_set_xfer_rate(). * Make IDE_TIMINGS and BLK_DEV_IDEDMA config options select IDE_XFER_MODE, also add explicit selects for few host drivers that need it. * Build/link ide-xfer-mode.o and ide-pio-blacklist.o (it is needed only by ide-xfer-mode.o) only if CONFIG_IDE_XFER_MODE=y. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Kconfig | 8 ++ drivers/ide/Makefile | 4 +- drivers/ide/ide-lib.c | 240 ------------------------------------------ drivers/ide/ide-xfer-mode.c | 246 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 256 insertions(+), 242 deletions(-) create mode 100644 drivers/ide/ide-xfer-mode.c (limited to 'drivers') diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 5ea3bfad172..640c9920724 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -56,8 +56,12 @@ if IDE comment "Please see Documentation/ide/ide.txt for help/info on IDE drives" +config IDE_XFER_MODE + bool + config IDE_TIMINGS bool + select IDE_XFER_MODE config IDE_ATAPI bool @@ -698,6 +702,7 @@ config BLK_DEV_IDE_PMAC_ATA100FIRST config BLK_DEV_IDE_AU1XXX bool "IDE for AMD Alchemy Au1200" depends on SOC_AU1200 + select IDE_XFER_MODE choice prompt "IDE Mode for AMD Alchemy Au1200" default CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA @@ -871,6 +876,7 @@ config BLK_DEV_ALI14XX config BLK_DEV_DTC2278 tristate "DTC-2278 support" + select IDE_XFER_MODE select IDE_LEGACY help This driver is enabled at runtime using the "dtc2278.probe" kernel @@ -902,6 +908,7 @@ config BLK_DEV_QD65XX config BLK_DEV_UMC8672 tristate "UMC-8672 support" + select IDE_XFER_MODE select IDE_LEGACY help This driver is enabled at runtime using the "umc8672.probe" kernel @@ -915,5 +922,6 @@ endif config BLK_DEV_IDEDMA def_bool BLK_DEV_IDEDMA_SFF || \ BLK_DEV_IDEDMA_ICS || BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA + select IDE_XFER_MODE endif # IDE diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index 83a970ee4bf..d0976e6ee09 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -5,10 +5,10 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ - ide-taskfile.o ide-pm.o ide-park.o ide-pio-blacklist.o \ - ide-sysfs.o ide-devsets.o + ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o # core IDE code +ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o ide-core-$(CONFIG_IDE_TIMINGS) += ide-timings.o ide-core-$(CONFIG_IDE_ATAPI) += ide-atapi.o ide-core-$(CONFIG_BLK_DEV_IDEPCI) += setup-pci.o diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 09526a0de73..f6c683dd298 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c @@ -5,163 +5,6 @@ #include #include -static const char *udma_str[] = - { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", - "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; -static const char *mwdma_str[] = - { "MWDMA0", "MWDMA1", "MWDMA2" }; -static const char *swdma_str[] = - { "SWDMA0", "SWDMA1", "SWDMA2" }; -static const char *pio_str[] = - { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" }; - -/** - * ide_xfer_verbose - return IDE mode names - * @mode: transfer mode - * - * Returns a constant string giving the name of the mode - * requested. - */ - -const char *ide_xfer_verbose(u8 mode) -{ - const char *s; - u8 i = mode & 0xf; - - if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7) - s = udma_str[i]; - else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2) - s = mwdma_str[i]; - else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2) - s = swdma_str[i]; - else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5) - s = pio_str[i & 0x7]; - else if (mode == XFER_PIO_SLOW) - s = "PIO SLOW"; - else - s = "XFER ERROR"; - - return s; -} -EXPORT_SYMBOL(ide_xfer_verbose); - -/** - * ide_rate_filter - filter transfer mode - * @drive: IDE device - * @speed: desired speed - * - * Given the available transfer modes this function returns - * the best available speed at or below the speed requested. - * - * TODO: check device PIO capabilities - */ - -static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) -{ - ide_hwif_t *hwif = drive->hwif; - u8 mode = ide_find_dma_mode(drive, speed); - - if (mode == 0) { - if (hwif->pio_mask) - mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0; - else - mode = XFER_PIO_4; - } - -/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */ - - return min(speed, mode); -} - -/** - * ide_get_best_pio_mode - get PIO mode from drive - * @drive: drive to consider - * @mode_wanted: preferred mode - * @max_mode: highest allowed mode - * - * This routine returns the recommended PIO settings for a given drive, - * based on the drive->id information and the ide_pio_blacklist[]. - * - * Drive PIO mode is auto-selected if 255 is passed as mode_wanted. - * This is used by most chipset support modules when "auto-tuning". - */ - -u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode) -{ - u16 *id = drive->id; - int pio_mode = -1, overridden = 0; - - if (mode_wanted != 255) - return min_t(u8, mode_wanted, max_mode); - - if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0) - pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]); - - if (pio_mode != -1) { - printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name); - } else { - pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8; - if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ - pio_mode = 2; - overridden = 1; - } - - if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */ - if (ata_id_has_iordy(id)) { - if (id[ATA_ID_PIO_MODES] & 7) { - overridden = 0; - if (id[ATA_ID_PIO_MODES] & 4) - pio_mode = 5; - else if (id[ATA_ID_PIO_MODES] & 2) - pio_mode = 4; - else - pio_mode = 3; - } - } - } - - if (overridden) - printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n", - drive->name); - } - - if (pio_mode > max_mode) - pio_mode = max_mode; - - return pio_mode; -} -EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); - -/* req_pio == "255" for auto-tune */ -void ide_set_pio(ide_drive_t *drive, u8 req_pio) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - u8 host_pio, pio; - - if (port_ops == NULL || port_ops->set_pio_mode == NULL || - (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) - return; - - BUG_ON(hwif->pio_mask == 0x00); - - host_pio = fls(hwif->pio_mask) - 1; - - pio = ide_get_best_pio_mode(drive, req_pio, host_pio); - - /* - * TODO: - * - report device max PIO mode - * - check req_pio != 255 against device max PIO mode - */ - printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n", - drive->name, host_pio, req_pio, - req_pio == 255 ? "(auto-tune)" : "", pio); - - (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio); -} -EXPORT_SYMBOL_GPL(ide_set_pio); - /** * ide_toggle_bounce - handle bounce buffering * @drive: drive to update @@ -188,89 +31,6 @@ void ide_toggle_bounce(ide_drive_t *drive, int on) blk_queue_bounce_limit(drive->queue, addr); } -int ide_set_pio_mode(ide_drive_t *drive, const u8 mode) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) - return 0; - - if (port_ops == NULL || port_ops->set_pio_mode == NULL) - return -1; - - /* - * TODO: temporary hack for some legacy host drivers that didn't - * set transfer mode on the device in ->set_pio_mode method... - */ - if (port_ops->set_dma_mode == NULL) { - port_ops->set_pio_mode(drive, mode - XFER_PIO_0); - return 0; - } - - if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { - if (ide_config_drive_speed(drive, mode)) - return -1; - port_ops->set_pio_mode(drive, mode - XFER_PIO_0); - return 0; - } else { - port_ops->set_pio_mode(drive, mode - XFER_PIO_0); - return ide_config_drive_speed(drive, mode); - } -} - -int ide_set_dma_mode(ide_drive_t *drive, const u8 mode) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) - return 0; - - if (port_ops == NULL || port_ops->set_dma_mode == NULL) - return -1; - - if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { - if (ide_config_drive_speed(drive, mode)) - return -1; - port_ops->set_dma_mode(drive, mode); - return 0; - } else { - port_ops->set_dma_mode(drive, mode); - return ide_config_drive_speed(drive, mode); - } -} -EXPORT_SYMBOL_GPL(ide_set_dma_mode); - -/** - * ide_set_xfer_rate - set transfer rate - * @drive: drive to set - * @rate: speed to attempt to set - * - * General helper for setting the speed of an IDE device. This - * function knows about user enforced limits from the configuration - * which ->set_pio_mode/->set_dma_mode does not. - */ - -int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - - if (port_ops == NULL || port_ops->set_dma_mode == NULL || - (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) - return -1; - - rate = ide_rate_filter(drive, rate); - - BUG_ON(rate < XFER_PIO_0); - - if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5) - return ide_set_pio_mode(drive, rate); - - return ide_set_dma_mode(drive, rate); -} - static void ide_dump_opcode(ide_drive_t *drive) { struct request *rq = drive->hwif->rq; diff --git a/drivers/ide/ide-xfer-mode.c b/drivers/ide/ide-xfer-mode.c new file mode 100644 index 00000000000..6910f6a257e --- /dev/null +++ b/drivers/ide/ide-xfer-mode.c @@ -0,0 +1,246 @@ +#include +#include +#include +#include +#include +#include + +static const char *udma_str[] = + { "UDMA/16", "UDMA/25", "UDMA/33", "UDMA/44", + "UDMA/66", "UDMA/100", "UDMA/133", "UDMA7" }; +static const char *mwdma_str[] = + { "MWDMA0", "MWDMA1", "MWDMA2" }; +static const char *swdma_str[] = + { "SWDMA0", "SWDMA1", "SWDMA2" }; +static const char *pio_str[] = + { "PIO0", "PIO1", "PIO2", "PIO3", "PIO4", "PIO5" }; + +/** + * ide_xfer_verbose - return IDE mode names + * @mode: transfer mode + * + * Returns a constant string giving the name of the mode + * requested. + */ + +const char *ide_xfer_verbose(u8 mode) +{ + const char *s; + u8 i = mode & 0xf; + + if (mode >= XFER_UDMA_0 && mode <= XFER_UDMA_7) + s = udma_str[i]; + else if (mode >= XFER_MW_DMA_0 && mode <= XFER_MW_DMA_2) + s = mwdma_str[i]; + else if (mode >= XFER_SW_DMA_0 && mode <= XFER_SW_DMA_2) + s = swdma_str[i]; + else if (mode >= XFER_PIO_0 && mode <= XFER_PIO_5) + s = pio_str[i & 0x7]; + else if (mode == XFER_PIO_SLOW) + s = "PIO SLOW"; + else + s = "XFER ERROR"; + + return s; +} +EXPORT_SYMBOL(ide_xfer_verbose); + +/** + * ide_get_best_pio_mode - get PIO mode from drive + * @drive: drive to consider + * @mode_wanted: preferred mode + * @max_mode: highest allowed mode + * + * This routine returns the recommended PIO settings for a given drive, + * based on the drive->id information and the ide_pio_blacklist[]. + * + * Drive PIO mode is auto-selected if 255 is passed as mode_wanted. + * This is used by most chipset support modules when "auto-tuning". + */ + +u8 ide_get_best_pio_mode(ide_drive_t *drive, u8 mode_wanted, u8 max_mode) +{ + u16 *id = drive->id; + int pio_mode = -1, overridden = 0; + + if (mode_wanted != 255) + return min_t(u8, mode_wanted, max_mode); + + if ((drive->hwif->host_flags & IDE_HFLAG_PIO_NO_BLACKLIST) == 0) + pio_mode = ide_scan_pio_blacklist((char *)&id[ATA_ID_PROD]); + + if (pio_mode != -1) { + printk(KERN_INFO "%s: is on PIO blacklist\n", drive->name); + } else { + pio_mode = id[ATA_ID_OLD_PIO_MODES] >> 8; + if (pio_mode > 2) { /* 2 is maximum allowed tPIO value */ + pio_mode = 2; + overridden = 1; + } + + if (id[ATA_ID_FIELD_VALID] & 2) { /* ATA2? */ + if (ata_id_has_iordy(id)) { + if (id[ATA_ID_PIO_MODES] & 7) { + overridden = 0; + if (id[ATA_ID_PIO_MODES] & 4) + pio_mode = 5; + else if (id[ATA_ID_PIO_MODES] & 2) + pio_mode = 4; + else + pio_mode = 3; + } + } + } + + if (overridden) + printk(KERN_INFO "%s: tPIO > 2, assuming tPIO = 2\n", + drive->name); + } + + if (pio_mode > max_mode) + pio_mode = max_mode; + + return pio_mode; +} +EXPORT_SYMBOL_GPL(ide_get_best_pio_mode); + +int ide_set_pio_mode(ide_drive_t *drive, const u8 mode) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) + return 0; + + if (port_ops == NULL || port_ops->set_pio_mode == NULL) + return -1; + + /* + * TODO: temporary hack for some legacy host drivers that didn't + * set transfer mode on the device in ->set_pio_mode method... + */ + if (port_ops->set_dma_mode == NULL) { + port_ops->set_pio_mode(drive, mode - XFER_PIO_0); + return 0; + } + + if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { + if (ide_config_drive_speed(drive, mode)) + return -1; + port_ops->set_pio_mode(drive, mode - XFER_PIO_0); + return 0; + } else { + port_ops->set_pio_mode(drive, mode - XFER_PIO_0); + return ide_config_drive_speed(drive, mode); + } +} + +int ide_set_dma_mode(ide_drive_t *drive, const u8 mode) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (hwif->host_flags & IDE_HFLAG_NO_SET_MODE) + return 0; + + if (port_ops == NULL || port_ops->set_dma_mode == NULL) + return -1; + + if (hwif->host_flags & IDE_HFLAG_POST_SET_MODE) { + if (ide_config_drive_speed(drive, mode)) + return -1; + port_ops->set_dma_mode(drive, mode); + return 0; + } else { + port_ops->set_dma_mode(drive, mode); + return ide_config_drive_speed(drive, mode); + } +} +EXPORT_SYMBOL_GPL(ide_set_dma_mode); + +/* req_pio == "255" for auto-tune */ +void ide_set_pio(ide_drive_t *drive, u8 req_pio) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + u8 host_pio, pio; + + if (port_ops == NULL || port_ops->set_pio_mode == NULL || + (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) + return; + + BUG_ON(hwif->pio_mask == 0x00); + + host_pio = fls(hwif->pio_mask) - 1; + + pio = ide_get_best_pio_mode(drive, req_pio, host_pio); + + /* + * TODO: + * - report device max PIO mode + * - check req_pio != 255 against device max PIO mode + */ + printk(KERN_DEBUG "%s: host max PIO%d wanted PIO%d%s selected PIO%d\n", + drive->name, host_pio, req_pio, + req_pio == 255 ? "(auto-tune)" : "", pio); + + (void)ide_set_pio_mode(drive, XFER_PIO_0 + pio); +} +EXPORT_SYMBOL_GPL(ide_set_pio); + +/** + * ide_rate_filter - filter transfer mode + * @drive: IDE device + * @speed: desired speed + * + * Given the available transfer modes this function returns + * the best available speed at or below the speed requested. + * + * TODO: check device PIO capabilities + */ + +static u8 ide_rate_filter(ide_drive_t *drive, u8 speed) +{ + ide_hwif_t *hwif = drive->hwif; + u8 mode = ide_find_dma_mode(drive, speed); + + if (mode == 0) { + if (hwif->pio_mask) + mode = fls(hwif->pio_mask) - 1 + XFER_PIO_0; + else + mode = XFER_PIO_4; + } + +/* printk("%s: mode 0x%02x, speed 0x%02x\n", __func__, mode, speed); */ + + return min(speed, mode); +} + +/** + * ide_set_xfer_rate - set transfer rate + * @drive: drive to set + * @rate: speed to attempt to set + * + * General helper for setting the speed of an IDE device. This + * function knows about user enforced limits from the configuration + * which ->set_pio_mode/->set_dma_mode does not. + */ + +int ide_set_xfer_rate(ide_drive_t *drive, u8 rate) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + + if (port_ops == NULL || port_ops->set_dma_mode == NULL || + (hwif->host_flags & IDE_HFLAG_NO_SET_MODE)) + return -1; + + rate = ide_rate_filter(drive, rate); + + BUG_ON(rate < XFER_PIO_0); + + if (rate >= XFER_PIO_0 && rate <= XFER_PIO_5) + return ide_set_pio_mode(drive, rate); + + return ide_set_dma_mode(drive, rate); +} -- cgit v1.2.3 From 0d6a9754c06e173552b0ad5fad45f69786b6de99 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:46 +0100 Subject: ide: move ide_read_bcount_and_ireason() to ide-atapi.c Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-atapi.c | 15 +++++++++++++++ drivers/ide/ide-iops.c | 15 --------------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 3044c51c06a..6adc5b4a440 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c @@ -300,6 +300,21 @@ int ide_cd_get_xferlen(struct request *rq) } EXPORT_SYMBOL_GPL(ide_cd_get_xferlen); +void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason) +{ + ide_task_t task; + + memset(&task, 0, sizeof(task)); + task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM | + IDE_TFLAG_IN_NSECT; + + drive->hwif->tp_ops->tf_read(drive, &task); + + *bcount = (task.tf.lbah << 8) | task.tf.lbam; + *ireason = task.tf.nsect & 3; +} +EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); + /* * This is the usual interrupt handler which will be called during a packet * command. We will transfer some of the data (as requested by the drive) diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index ee9c6034278..d24add69212 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -362,21 +362,6 @@ u8 ide_read_error(ide_drive_t *drive) } EXPORT_SYMBOL_GPL(ide_read_error); -void ide_read_bcount_and_ireason(ide_drive_t *drive, u16 *bcount, u8 *ireason) -{ - ide_task_t task; - - memset(&task, 0, sizeof(task)); - task.tf_flags = IDE_TFLAG_IN_LBAH | IDE_TFLAG_IN_LBAM | - IDE_TFLAG_IN_NSECT; - - drive->hwif->tp_ops->tf_read(drive, &task); - - *bcount = (task.tf.lbah << 8) | task.tf.lbam; - *ireason = task.tf.nsect & 3; -} -EXPORT_SYMBOL_GPL(ide_read_bcount_and_ireason); - const struct ide_tp_ops default_tp_ops = { .exec_command = ide_exec_command, .read_status = ide_read_status, -- cgit v1.2.3 From 1574cf6cb4800525be769ee6023c567113fa2d18 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:46 +0100 Subject: ide: move standard I/O code to ide-io-std.c Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Makefile | 3 +- drivers/ide/ide-io-std.c | 316 +++++++++++++++++++++++++++++++++++++++++++++++ drivers/ide/ide-iops.c | 313 ---------------------------------------------- 3 files changed, 318 insertions(+), 314 deletions(-) create mode 100644 drivers/ide/ide-io-std.c (limited to 'drivers') diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index d0976e6ee09..cbb1aea2aea 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -5,7 +5,8 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ - ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o + ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \ + ide-io-std.o # core IDE code ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o diff --git a/drivers/ide/ide-io-std.c b/drivers/ide/ide-io-std.c new file mode 100644 index 00000000000..45b43dd49cd --- /dev/null +++ b/drivers/ide/ide-io-std.c @@ -0,0 +1,316 @@ + +#include +#include + +/* + * Conventional PIO operations for ATA devices + */ + +static u8 ide_inb(unsigned long port) +{ + return (u8) inb(port); +} + +static void ide_outb(u8 val, unsigned long port) +{ + outb(val, port); +} + +/* + * MMIO operations, typically used for SATA controllers + */ + +static u8 ide_mm_inb(unsigned long port) +{ + return (u8) readb((void __iomem *) port); +} + +static void ide_mm_outb(u8 value, unsigned long port) +{ + writeb(value, (void __iomem *) port); +} + +void ide_exec_command(ide_hwif_t *hwif, u8 cmd) +{ + if (hwif->host_flags & IDE_HFLAG_MMIO) + writeb(cmd, (void __iomem *)hwif->io_ports.command_addr); + else + outb(cmd, hwif->io_ports.command_addr); +} +EXPORT_SYMBOL_GPL(ide_exec_command); + +u8 ide_read_status(ide_hwif_t *hwif) +{ + if (hwif->host_flags & IDE_HFLAG_MMIO) + return readb((void __iomem *)hwif->io_ports.status_addr); + else + return inb(hwif->io_ports.status_addr); +} +EXPORT_SYMBOL_GPL(ide_read_status); + +u8 ide_read_altstatus(ide_hwif_t *hwif) +{ + if (hwif->host_flags & IDE_HFLAG_MMIO) + return readb((void __iomem *)hwif->io_ports.ctl_addr); + else + return inb(hwif->io_ports.ctl_addr); +} +EXPORT_SYMBOL_GPL(ide_read_altstatus); + +void ide_set_irq(ide_hwif_t *hwif, int on) +{ + u8 ctl = ATA_DEVCTL_OBS; + + if (on == 4) { /* hack for SRST */ + ctl |= 4; + on &= ~4; + } + + ctl |= on ? 0 : 2; + + if (hwif->host_flags & IDE_HFLAG_MMIO) + writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); + else + outb(ctl, hwif->io_ports.ctl_addr); +} +EXPORT_SYMBOL_GPL(ide_set_irq); + +void ide_tf_load(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + void (*tf_outb)(u8 addr, unsigned long port); + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; + + if (mmio) + tf_outb = ide_mm_outb; + else + tf_outb = ide_outb; + + if (task->tf_flags & IDE_TFLAG_FLAGGED) + HIHI = 0xFF; + + if (task->tf_flags & IDE_TFLAG_OUT_DATA) { + u16 data = (tf->hob_data << 8) | tf->data; + + if (mmio) + writew(data, (void __iomem *)io_ports->data_addr); + else + outw(data, io_ports->data_addr); + } + + if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) + tf_outb(tf->hob_feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) + tf_outb(tf->hob_nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) + tf_outb(tf->hob_lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) + tf_outb(tf->hob_lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) + tf_outb(tf->hob_lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) + tf_outb(tf->feature, io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_OUT_NSECT) + tf_outb(tf->nsect, io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAL) + tf_outb(tf->lbal, io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAM) + tf_outb(tf->lbam, io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_OUT_LBAH) + tf_outb(tf->lbah, io_ports->lbah_addr); + + if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) + tf_outb((tf->device & HIHI) | drive->select, + io_ports->device_addr); +} +EXPORT_SYMBOL_GPL(ide_tf_load); + +void ide_tf_read(ide_drive_t *drive, ide_task_t *task) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + struct ide_taskfile *tf = &task->tf; + void (*tf_outb)(u8 addr, unsigned long port); + u8 (*tf_inb)(unsigned long port); + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + + if (mmio) { + tf_outb = ide_mm_outb; + tf_inb = ide_mm_inb; + } else { + tf_outb = ide_outb; + tf_inb = ide_inb; + } + + if (task->tf_flags & IDE_TFLAG_IN_DATA) { + u16 data; + + if (mmio) + data = readw((void __iomem *)io_ports->data_addr); + else + data = inw(io_ports->data_addr); + + tf->data = data & 0xff; + tf->hob_data = (data >> 8) & 0xff; + } + + /* be sure we're looking at the low order bits */ + tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_FEATURE) + tf->feature = tf_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_NSECT) + tf->nsect = tf_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAL) + tf->lbal = tf_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAM) + tf->lbam = tf_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_LBAH) + tf->lbah = tf_inb(io_ports->lbah_addr); + if (task->tf_flags & IDE_TFLAG_IN_DEVICE) + tf->device = tf_inb(io_ports->device_addr); + + if (task->tf_flags & IDE_TFLAG_LBA48) { + tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); + + if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) + tf->hob_feature = tf_inb(io_ports->feature_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) + tf->hob_nsect = tf_inb(io_ports->nsect_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) + tf->hob_lbal = tf_inb(io_ports->lbal_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) + tf->hob_lbam = tf_inb(io_ports->lbam_addr); + if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) + tf->hob_lbah = tf_inb(io_ports->lbah_addr); + } +} +EXPORT_SYMBOL_GPL(ide_tf_read); + +/* + * Some localbus EIDE interfaces require a special access sequence + * when using 32-bit I/O instructions to transfer data. We call this + * the "vlb_sync" sequence, which consists of three successive reads + * of the sector count register location, with interrupts disabled + * to ensure that the reads all happen together. + */ +static void ata_vlb_sync(unsigned long port) +{ + (void)inb(port); + (void)inb(port); + (void)inb(port); +} + +/* + * This is used for most PIO data transfers *from* the IDE interface + * + * These routines will round up any request for an odd number of bytes, + * so if an odd len is specified, be sure that there's at least one + * extra byte allocated for the buffer. + */ +void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf, + unsigned int len) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + unsigned long data_addr = io_ports->data_addr; + u8 io_32bit = drive->io_32bit; + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + + len++; + + if (io_32bit) { + unsigned long uninitialized_var(flags); + + if ((io_32bit & 2) && !mmio) { + local_irq_save(flags); + ata_vlb_sync(io_ports->nsect_addr); + } + + if (mmio) + __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); + else + insl(data_addr, buf, len / 4); + + if ((io_32bit & 2) && !mmio) + local_irq_restore(flags); + + if ((len & 3) >= 2) { + if (mmio) + __ide_mm_insw((void __iomem *)data_addr, + (u8 *)buf + (len & ~3), 1); + else + insw(data_addr, (u8 *)buf + (len & ~3), 1); + } + } else { + if (mmio) + __ide_mm_insw((void __iomem *)data_addr, buf, len / 2); + else + insw(data_addr, buf, len / 2); + } +} +EXPORT_SYMBOL_GPL(ide_input_data); + +/* + * This is used for most PIO data transfers *to* the IDE interface + */ +void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf, + unsigned int len) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + unsigned long data_addr = io_ports->data_addr; + u8 io_32bit = drive->io_32bit; + u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; + + len++; + + if (io_32bit) { + unsigned long uninitialized_var(flags); + + if ((io_32bit & 2) && !mmio) { + local_irq_save(flags); + ata_vlb_sync(io_ports->nsect_addr); + } + + if (mmio) + __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); + else + outsl(data_addr, buf, len / 4); + + if ((io_32bit & 2) && !mmio) + local_irq_restore(flags); + + if ((len & 3) >= 2) { + if (mmio) + __ide_mm_outsw((void __iomem *)data_addr, + (u8 *)buf + (len & ~3), 1); + else + outsw(data_addr, (u8 *)buf + (len & ~3), 1); + } + } else { + if (mmio) + __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2); + else + outsw(data_addr, buf, len / 2); + } +} +EXPORT_SYMBOL_GPL(ide_output_data); + +const struct ide_tp_ops default_tp_ops = { + .exec_command = ide_exec_command, + .read_status = ide_read_status, + .read_altstatus = ide_read_altstatus, + + .set_irq = ide_set_irq, + + .tf_load = ide_tf_load, + .tf_read = ide_tf_read, + + .input_data = ide_input_data, + .output_data = ide_output_data, +}; diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index d24add69212..91a49b543bd 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -27,34 +27,6 @@ #include #include -/* - * Conventional PIO operations for ATA devices - */ - -static u8 ide_inb (unsigned long port) -{ - return (u8) inb(port); -} - -static void ide_outb (u8 val, unsigned long port) -{ - outb(val, port); -} - -/* - * MMIO operations, typically used for SATA controllers - */ - -static u8 ide_mm_inb (unsigned long port) -{ - return (u8) readb((void __iomem *) port); -} - -static void ide_mm_outb (u8 value, unsigned long port) -{ - writeb(value, (void __iomem *) port); -} - void SELECT_DRIVE (ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; @@ -78,277 +50,6 @@ void SELECT_MASK(ide_drive_t *drive, int mask) port_ops->maskproc(drive, mask); } -void ide_exec_command(ide_hwif_t *hwif, u8 cmd) -{ - if (hwif->host_flags & IDE_HFLAG_MMIO) - writeb(cmd, (void __iomem *)hwif->io_ports.command_addr); - else - outb(cmd, hwif->io_ports.command_addr); -} -EXPORT_SYMBOL_GPL(ide_exec_command); - -u8 ide_read_status(ide_hwif_t *hwif) -{ - if (hwif->host_flags & IDE_HFLAG_MMIO) - return readb((void __iomem *)hwif->io_ports.status_addr); - else - return inb(hwif->io_ports.status_addr); -} -EXPORT_SYMBOL_GPL(ide_read_status); - -u8 ide_read_altstatus(ide_hwif_t *hwif) -{ - if (hwif->host_flags & IDE_HFLAG_MMIO) - return readb((void __iomem *)hwif->io_ports.ctl_addr); - else - return inb(hwif->io_ports.ctl_addr); -} -EXPORT_SYMBOL_GPL(ide_read_altstatus); - -void ide_set_irq(ide_hwif_t *hwif, int on) -{ - u8 ctl = ATA_DEVCTL_OBS; - - if (on == 4) { /* hack for SRST */ - ctl |= 4; - on &= ~4; - } - - ctl |= on ? 0 : 2; - - if (hwif->host_flags & IDE_HFLAG_MMIO) - writeb(ctl, (void __iomem *)hwif->io_ports.ctl_addr); - else - outb(ctl, hwif->io_ports.ctl_addr); -} -EXPORT_SYMBOL_GPL(ide_set_irq); - -void ide_tf_load(ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - void (*tf_outb)(u8 addr, unsigned long port); - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - u8 HIHI = (task->tf_flags & IDE_TFLAG_LBA48) ? 0xE0 : 0xEF; - - if (mmio) - tf_outb = ide_mm_outb; - else - tf_outb = ide_outb; - - if (task->tf_flags & IDE_TFLAG_FLAGGED) - HIHI = 0xFF; - - if (task->tf_flags & IDE_TFLAG_OUT_DATA) { - u16 data = (tf->hob_data << 8) | tf->data; - - if (mmio) - writew(data, (void __iomem *)io_ports->data_addr); - else - outw(data, io_ports->data_addr); - } - - if (task->tf_flags & IDE_TFLAG_OUT_HOB_FEATURE) - tf_outb(tf->hob_feature, io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_NSECT) - tf_outb(tf->hob_nsect, io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAL) - tf_outb(tf->hob_lbal, io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAM) - tf_outb(tf->hob_lbam, io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_OUT_HOB_LBAH) - tf_outb(tf->hob_lbah, io_ports->lbah_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_FEATURE) - tf_outb(tf->feature, io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_OUT_NSECT) - tf_outb(tf->nsect, io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAL) - tf_outb(tf->lbal, io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAM) - tf_outb(tf->lbam, io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_OUT_LBAH) - tf_outb(tf->lbah, io_ports->lbah_addr); - - if (task->tf_flags & IDE_TFLAG_OUT_DEVICE) - tf_outb((tf->device & HIHI) | drive->select, - io_ports->device_addr); -} -EXPORT_SYMBOL_GPL(ide_tf_load); - -void ide_tf_read(ide_drive_t *drive, ide_task_t *task) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - struct ide_taskfile *tf = &task->tf; - void (*tf_outb)(u8 addr, unsigned long port); - u8 (*tf_inb)(unsigned long port); - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - - if (mmio) { - tf_outb = ide_mm_outb; - tf_inb = ide_mm_inb; - } else { - tf_outb = ide_outb; - tf_inb = ide_inb; - } - - if (task->tf_flags & IDE_TFLAG_IN_DATA) { - u16 data; - - if (mmio) - data = readw((void __iomem *)io_ports->data_addr); - else - data = inw(io_ports->data_addr); - - tf->data = data & 0xff; - tf->hob_data = (data >> 8) & 0xff; - } - - /* be sure we're looking at the low order bits */ - tf_outb(ATA_DEVCTL_OBS & ~0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_FEATURE) - tf->feature = tf_inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_NSECT) - tf->nsect = tf_inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAL) - tf->lbal = tf_inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAM) - tf->lbam = tf_inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_LBAH) - tf->lbah = tf_inb(io_ports->lbah_addr); - if (task->tf_flags & IDE_TFLAG_IN_DEVICE) - tf->device = tf_inb(io_ports->device_addr); - - if (task->tf_flags & IDE_TFLAG_LBA48) { - tf_outb(ATA_DEVCTL_OBS | 0x80, io_ports->ctl_addr); - - if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE) - tf->hob_feature = tf_inb(io_ports->feature_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_NSECT) - tf->hob_nsect = tf_inb(io_ports->nsect_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAL) - tf->hob_lbal = tf_inb(io_ports->lbal_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAM) - tf->hob_lbam = tf_inb(io_ports->lbam_addr); - if (task->tf_flags & IDE_TFLAG_IN_HOB_LBAH) - tf->hob_lbah = tf_inb(io_ports->lbah_addr); - } -} -EXPORT_SYMBOL_GPL(ide_tf_read); - -/* - * Some localbus EIDE interfaces require a special access sequence - * when using 32-bit I/O instructions to transfer data. We call this - * the "vlb_sync" sequence, which consists of three successive reads - * of the sector count register location, with interrupts disabled - * to ensure that the reads all happen together. - */ -static void ata_vlb_sync(unsigned long port) -{ - (void)inb(port); - (void)inb(port); - (void)inb(port); -} - -/* - * This is used for most PIO data transfers *from* the IDE interface - * - * These routines will round up any request for an odd number of bytes, - * so if an odd len is specified, be sure that there's at least one - * extra byte allocated for the buffer. - */ -void ide_input_data(ide_drive_t *drive, struct request *rq, void *buf, - unsigned int len) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - unsigned long data_addr = io_ports->data_addr; - u8 io_32bit = drive->io_32bit; - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - - len++; - - if (io_32bit) { - unsigned long uninitialized_var(flags); - - if ((io_32bit & 2) && !mmio) { - local_irq_save(flags); - ata_vlb_sync(io_ports->nsect_addr); - } - - if (mmio) - __ide_mm_insl((void __iomem *)data_addr, buf, len / 4); - else - insl(data_addr, buf, len / 4); - - if ((io_32bit & 2) && !mmio) - local_irq_restore(flags); - - if ((len & 3) >= 2) { - if (mmio) - __ide_mm_insw((void __iomem *)data_addr, - (u8 *)buf + (len & ~3), 1); - else - insw(data_addr, (u8 *)buf + (len & ~3), 1); - } - } else { - if (mmio) - __ide_mm_insw((void __iomem *)data_addr, buf, len / 2); - else - insw(data_addr, buf, len / 2); - } -} -EXPORT_SYMBOL_GPL(ide_input_data); - -/* - * This is used for most PIO data transfers *to* the IDE interface - */ -void ide_output_data(ide_drive_t *drive, struct request *rq, void *buf, - unsigned int len) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - unsigned long data_addr = io_ports->data_addr; - u8 io_32bit = drive->io_32bit; - u8 mmio = (hwif->host_flags & IDE_HFLAG_MMIO) ? 1 : 0; - - len++; - - if (io_32bit) { - unsigned long uninitialized_var(flags); - - if ((io_32bit & 2) && !mmio) { - local_irq_save(flags); - ata_vlb_sync(io_ports->nsect_addr); - } - - if (mmio) - __ide_mm_outsl((void __iomem *)data_addr, buf, len / 4); - else - outsl(data_addr, buf, len / 4); - - if ((io_32bit & 2) && !mmio) - local_irq_restore(flags); - - if ((len & 3) >= 2) { - if (mmio) - __ide_mm_outsw((void __iomem *)data_addr, - (u8 *)buf + (len & ~3), 1); - else - outsw(data_addr, (u8 *)buf + (len & ~3), 1); - } - } else { - if (mmio) - __ide_mm_outsw((void __iomem *)data_addr, buf, len / 2); - else - outsw(data_addr, buf, len / 2); - } -} -EXPORT_SYMBOL_GPL(ide_output_data); - u8 ide_read_error(ide_drive_t *drive) { ide_task_t task; @@ -362,20 +63,6 @@ u8 ide_read_error(ide_drive_t *drive) } EXPORT_SYMBOL_GPL(ide_read_error); -const struct ide_tp_ops default_tp_ops = { - .exec_command = ide_exec_command, - .read_status = ide_read_status, - .read_altstatus = ide_read_altstatus, - - .set_irq = ide_set_irq, - - .tf_load = ide_tf_load, - .tf_read = ide_tf_read, - - .input_data = ide_input_data, - .output_data = ide_output_data, -}; - void ide_fix_driveid(u16 *id) { #ifndef __LITTLE_ENDIAN -- cgit v1.2.3 From 4d7bb471ce0283f586817abea81254b67598aae6 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:47 +0100 Subject: ide: fix printk() levels in [atapi_]reset_pollfunc() Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 91a49b543bd..aad0d52ff1e 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -549,7 +549,7 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) stat = hwif->tp_ops->read_status(hwif); if (OK_STAT(stat, 0, ATA_BUSY)) - printk("%s: ATAPI reset complete\n", drive->name); + printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name); else { if (time_before(jiffies, hwif->poll_timeout)) { ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); @@ -558,8 +558,8 @@ static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) } /* end of polling */ hwif->polling = 0; - printk("%s: ATAPI reset timed-out, status=0x%02x\n", - drive->name, stat); + printk(KERN_ERR "%s: ATAPI reset timed-out, status=0x%02x\n", + drive->name, stat); /* do it the old fashioned way */ return do_reset1(drive, 1); } @@ -618,7 +618,8 @@ static ide_startstop_t reset_pollfunc (ide_drive_t *drive) /* continue polling */ return ide_started; } - printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp); + printk(KERN_ERR "%s: reset timed-out, status=0x%02x\n", + hwif->name, tmp); drive->failures++; err = -EIO; } else { -- cgit v1.2.3 From ee1b1cc974816b59af2ba0be1912e1c2a200ae11 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:47 +0100 Subject: ide: fix comments in ide_config_drive_speed() Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index aad0d52ff1e..73ff16bf9f1 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -369,18 +369,15 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) * but for some reason these don't work at * this point (lost interrupt). */ - /* - * Select the drive, and issue the SETFEATURES command - */ - disable_irq_nosync(hwif->irq); - + /* * FIXME: we race against the running IRQ here if * this is called from non IRQ context. If we use * disable_irq() we hang on the error path. Work * is needed. */ - + disable_irq_nosync(hwif->irq); + udelay(1); SELECT_DRIVE(drive); SELECT_MASK(drive, 1); -- cgit v1.2.3 From 122f06f8bce406169d61242a3eb667027e27cca7 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:47 +0100 Subject: ide: checkpatch.pl fixes for ide-iops.c Fix following checkpatch.pl warnings/errors: - WARNING: space prohibited between function name and open parenthesis '(' - WARNING: EXPORT_SYMBOL(foo); should immediately follow its function/variable - WARNING: line over 80 characters - ERROR: trailing whitespace - ERROR: space required before the open parenthesis '(' Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 73ff16bf9f1..cf6c3036ae7 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -27,7 +27,7 @@ #include #include -void SELECT_DRIVE (ide_drive_t *drive) +void SELECT_DRIVE(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; const struct ide_port_ops *port_ops = hwif->port_ops; @@ -84,7 +84,7 @@ void ide_fix_driveid(u16 *id) * returned by the ATA_CMD_ID_ATA[PI] commands. */ -void ide_fixstring (u8 *s, const int bytecount, const int byteswap) +void ide_fixstring(u8 *s, const int bytecount, const int byteswap) { u8 *p, *end = &s[bytecount & ~1]; /* bytecount must be even */ @@ -107,7 +107,6 @@ void ide_fixstring (u8 *s, const int bytecount, const int byteswap) while (p != end) *p++ = '\0'; } - EXPORT_SYMBOL(ide_fixstring); /* @@ -121,7 +120,8 @@ EXPORT_SYMBOL(ide_fixstring); * setting a timer to wake up at half second intervals thereafter, * until timeout is achieved, before timing out. */ -static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout, u8 *rstat) +static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, + unsigned long timeout, u8 *rstat) { ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; @@ -179,7 +179,8 @@ static int __ide_wait_stat(ide_drive_t *drive, u8 good, u8 bad, unsigned long ti * The caller should return the updated value of "startstop" in this case, * "startstop" is unchanged when the function returns 0. */ -int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 bad, unsigned long timeout) +int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, + u8 bad, unsigned long timeout) { int err; u8 stat; @@ -199,7 +200,6 @@ int ide_wait_stat(ide_startstop_t *startstop, ide_drive_t *drive, u8 good, u8 ba return err; } - EXPORT_SYMBOL(ide_wait_stat); /** @@ -220,7 +220,6 @@ int ide_in_drive_list(u16 *id, const struct drive_list_entry *table) return 1; return 0; } - EXPORT_SYMBOL_GPL(ide_in_drive_list); /* @@ -245,7 +244,7 @@ static const struct drive_list_entry ivb_list[] = { * All hosts that use the 80c ribbon must use! * The name is derived from upper byte of word 93 and the 80c ribbon. */ -u8 eighty_ninty_three (ide_drive_t *drive) +u8 eighty_ninty_three(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; u16 *id = drive->id; @@ -470,9 +469,8 @@ void ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, __ide_set_handler(drive, handler, timeout, expiry); spin_unlock_irqrestore(&hwif->lock, flags); } - EXPORT_SYMBOL(ide_set_handler); - + /** * ide_execute_command - execute an IDE command * @drive: IDE drive to issue the command against @@ -482,7 +480,7 @@ EXPORT_SYMBOL(ide_set_handler); * @expiry: handler to run on timeout * * Helper function to issue an IDE command. This handles the - * atomicity requirements, command timing and ensures that the + * atomicity requirements, command timing and ensures that the * handler and IRQ setup do not race. All IDE command kick off * should go via this function or do equivalent locking. */ @@ -528,28 +526,29 @@ static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) } /* needed below */ -static ide_startstop_t do_reset1 (ide_drive_t *, int); +static ide_startstop_t do_reset1(ide_drive_t *, int); /* - * atapi_reset_pollfunc() gets invoked to poll the interface for completion every 50ms - * during an atapi drive reset operation. If the drive has not yet responded, - * and we have not yet hit our maximum waiting time, then the timer is restarted - * for another 50ms. + * atapi_reset_pollfunc() gets invoked to poll the interface for completion + * every 50ms during an atapi drive reset operation. If the drive has not yet + * responded, and we have not yet hit our maximum waiting time, then the timer + * is restarted for another 50ms. */ -static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive) +static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; u8 stat; SELECT_DRIVE(drive); - udelay (10); + udelay(10); stat = hwif->tp_ops->read_status(hwif); if (OK_STAT(stat, 0, ATA_BUSY)) printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name); else { if (time_before(jiffies, hwif->poll_timeout)) { - ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); + ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, + NULL); /* continue polling */ return ide_started; } @@ -591,7 +590,7 @@ static void ide_reset_report_error(ide_hwif_t *hwif, u8 err) * and we have not yet hit our maximum waiting time, then the timer is restarted * for another 50ms. */ -static ide_startstop_t reset_pollfunc (ide_drive_t *drive) +static ide_startstop_t reset_pollfunc(ide_drive_t *drive) { ide_hwif_t *hwif = drive->hwif; const struct ide_port_ops *port_ops = hwif->port_ops; @@ -703,7 +702,7 @@ static void pre_reset(ide_drive_t *drive) * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, * we set a timer to poll at 50ms intervals. */ -static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) +static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi) { ide_hwif_t *hwif = drive->hwif; struct ide_io_ports *io_ports = &hwif->io_ports; @@ -723,7 +722,7 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) if (drive->media != ide_disk && !do_not_try_atapi) { pre_reset(drive); SELECT_DRIVE(drive); - udelay (20); + udelay(20); tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); ndelay(400); hwif->poll_timeout = jiffies + WAIT_WORSTCASE; @@ -807,11 +806,10 @@ static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi) * ide_do_reset() is the entry point to the drive/interface reset code. */ -ide_startstop_t ide_do_reset (ide_drive_t *drive) +ide_startstop_t ide_do_reset(ide_drive_t *drive) { return do_reset1(drive, 0); } - EXPORT_SYMBOL(ide_do_reset); /* @@ -822,7 +820,7 @@ int ide_wait_not_busy(ide_hwif_t *hwif, unsigned long timeout) { u8 stat = 0; - while(timeout--) { + while (timeout--) { /* * Turn this into a schedule() sleep once I'm sure * about locking issues (2.5 work ?). -- cgit v1.2.3 From 327fa1c29466b8fe471a91fc11e9c6171163c81a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:47 +0100 Subject: ide: move error handling code to ide-eh.c (v2) Do some CodingStyle fixups in while at it. v2: Add missing include (reported by Stephen Rothwell). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/Makefile | 2 +- drivers/ide/ide-eh.c | 428 +++++++++++++++++++++++++++++++++++++++++++++++++ drivers/ide/ide-io.c | 129 +-------------- drivers/ide/ide-iops.c | 299 +--------------------------------- 4 files changed, 432 insertions(+), 426 deletions(-) create mode 100644 drivers/ide/ide-eh.c (limited to 'drivers') diff --git a/drivers/ide/Makefile b/drivers/ide/Makefile index cbb1aea2aea..9b4bbe1cdc1 100644 --- a/drivers/ide/Makefile +++ b/drivers/ide/Makefile @@ -6,7 +6,7 @@ EXTRA_CFLAGS += -Idrivers/ide ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \ ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \ - ide-io-std.o + ide-io-std.o ide-eh.o # core IDE code ide-core-$(CONFIG_IDE_XFER_MODE) += ide-pio-blacklist.o ide-xfer-mode.o diff --git a/drivers/ide/ide-eh.c b/drivers/ide/ide-eh.c new file mode 100644 index 00000000000..1231b5e486f --- /dev/null +++ b/drivers/ide/ide-eh.c @@ -0,0 +1,428 @@ + +#include +#include +#include + +static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, + u8 stat, u8 err) +{ + ide_hwif_t *hwif = drive->hwif; + + if ((stat & ATA_BUSY) || + ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } else if (stat & ATA_ERR) { + /* err has different meaning on cdrom and tape */ + if (err == ATA_ABORTED) { + if ((drive->dev_flags & IDE_DFLAG_LBA) && + /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */ + hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS) + return ide_stopped; + } else if ((err & BAD_CRC) == BAD_CRC) { + /* UDMA crc error, just retry the operation */ + drive->crc_count++; + } else if (err & (ATA_BBK | ATA_UNC)) { + /* retries won't help these */ + rq->errors = ERROR_MAX; + } else if (err & ATA_TRK0NF) { + /* help it find track zero */ + rq->errors |= ERROR_RECAL; + } + } + + if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ && + (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) { + int nsect = drive->mult_count ? drive->mult_count : 1; + + ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE); + } + + if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) { + ide_kill_rq(drive, rq); + return ide_stopped; + } + + if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) + rq->errors |= ERROR_RESET; + + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + + if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) + drive->special.b.recalibrate = 1; + + ++rq->errors; + + return ide_stopped; +} + +static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, + u8 stat, u8 err) +{ + ide_hwif_t *hwif = drive->hwif; + + if ((stat & ATA_BUSY) || + ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { + /* other bits are useless when BUSY */ + rq->errors |= ERROR_RESET; + } else { + /* add decoding error stuff */ + } + + if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) + /* force an abort */ + hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); + + if (rq->errors >= ERROR_MAX) { + ide_kill_rq(drive, rq); + } else { + if ((rq->errors & ERROR_RESET) == ERROR_RESET) { + ++rq->errors; + return ide_do_reset(drive); + } + ++rq->errors; + } + + return ide_stopped; +} + +static ide_startstop_t __ide_error(ide_drive_t *drive, struct request *rq, + u8 stat, u8 err) +{ + if (drive->media == ide_disk) + return ide_ata_error(drive, rq, stat, err); + return ide_atapi_error(drive, rq, stat, err); +} + +/** + * ide_error - handle an error on the IDE + * @drive: drive the error occurred on + * @msg: message to report + * @stat: status bits + * + * ide_error() takes action based on the error returned by the drive. + * For normal I/O that may well include retries. We deal with + * both new-style (taskfile) and old style command handling here. + * In the case of taskfile command handling there is work left to + * do + */ + +ide_startstop_t ide_error(ide_drive_t *drive, const char *msg, u8 stat) +{ + struct request *rq; + u8 err; + + err = ide_dump_status(drive, msg, stat); + + rq = drive->hwif->rq; + if (rq == NULL) + return ide_stopped; + + /* retry only "normal" I/O: */ + if (!blk_fs_request(rq)) { + rq->errors = 1; + ide_end_drive_cmd(drive, stat, err); + return ide_stopped; + } + + return __ide_error(drive, rq, stat, err); +} +EXPORT_SYMBOL_GPL(ide_error); + +static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) +{ + struct request *rq = drive->hwif->rq; + + if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) + ide_end_request(drive, err ? err : 1, 0); +} + +/* needed below */ +static ide_startstop_t do_reset1(ide_drive_t *, int); + +/* + * atapi_reset_pollfunc() gets invoked to poll the interface for completion + * every 50ms during an atapi drive reset operation. If the drive has not yet + * responded, and we have not yet hit our maximum waiting time, then the timer + * is restarted for another 50ms. + */ +static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + u8 stat; + + SELECT_DRIVE(drive); + udelay(10); + stat = hwif->tp_ops->read_status(hwif); + + if (OK_STAT(stat, 0, ATA_BUSY)) + printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name); + else { + if (time_before(jiffies, hwif->poll_timeout)) { + ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, + NULL); + /* continue polling */ + return ide_started; + } + /* end of polling */ + hwif->polling = 0; + printk(KERN_ERR "%s: ATAPI reset timed-out, status=0x%02x\n", + drive->name, stat); + /* do it the old fashioned way */ + return do_reset1(drive, 1); + } + /* done polling */ + hwif->polling = 0; + ide_complete_drive_reset(drive, 0); + return ide_stopped; +} + +static void ide_reset_report_error(ide_hwif_t *hwif, u8 err) +{ + static const char *err_master_vals[] = + { NULL, "passed", "formatter device error", + "sector buffer error", "ECC circuitry error", + "controlling MPU error" }; + + u8 err_master = err & 0x7f; + + printk(KERN_ERR "%s: reset: master: ", hwif->name); + if (err_master && err_master < 6) + printk(KERN_CONT "%s", err_master_vals[err_master]); + else + printk(KERN_CONT "error (0x%02x?)", err); + if (err & 0x80) + printk(KERN_CONT "; slave: failed"); + printk(KERN_CONT "\n"); +} + +/* + * reset_pollfunc() gets invoked to poll the interface for completion every 50ms + * during an ide reset operation. If the drives have not yet responded, + * and we have not yet hit our maximum waiting time, then the timer is restarted + * for another 50ms. + */ +static ide_startstop_t reset_pollfunc(ide_drive_t *drive) +{ + ide_hwif_t *hwif = drive->hwif; + const struct ide_port_ops *port_ops = hwif->port_ops; + u8 tmp; + int err = 0; + + if (port_ops && port_ops->reset_poll) { + err = port_ops->reset_poll(drive); + if (err) { + printk(KERN_ERR "%s: host reset_poll failure for %s.\n", + hwif->name, drive->name); + goto out; + } + } + + tmp = hwif->tp_ops->read_status(hwif); + + if (!OK_STAT(tmp, 0, ATA_BUSY)) { + if (time_before(jiffies, hwif->poll_timeout)) { + ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); + /* continue polling */ + return ide_started; + } + printk(KERN_ERR "%s: reset timed-out, status=0x%02x\n", + hwif->name, tmp); + drive->failures++; + err = -EIO; + } else { + tmp = ide_read_error(drive); + + if (tmp == 1) { + printk(KERN_INFO "%s: reset: success\n", hwif->name); + drive->failures = 0; + } else { + ide_reset_report_error(hwif, tmp); + drive->failures++; + err = -EIO; + } + } +out: + hwif->polling = 0; /* done polling */ + ide_complete_drive_reset(drive, err); + return ide_stopped; +} + +static void ide_disk_pre_reset(ide_drive_t *drive) +{ + int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; + + drive->special.all = 0; + drive->special.b.set_geometry = legacy; + drive->special.b.recalibrate = legacy; + + drive->mult_count = 0; + drive->dev_flags &= ~IDE_DFLAG_PARKED; + + if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 && + (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) + drive->mult_req = 0; + + if (drive->mult_req != drive->mult_count) + drive->special.b.set_multmode = 1; +} + +static void pre_reset(ide_drive_t *drive) +{ + const struct ide_port_ops *port_ops = drive->hwif->port_ops; + + if (drive->media == ide_disk) + ide_disk_pre_reset(drive); + else + drive->dev_flags |= IDE_DFLAG_POST_RESET; + + if (drive->dev_flags & IDE_DFLAG_USING_DMA) { + if (drive->crc_count) + ide_check_dma_crc(drive); + else + ide_dma_off(drive); + } + + if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) { + if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) { + drive->dev_flags &= ~IDE_DFLAG_UNMASK; + drive->io_32bit = 0; + } + return; + } + + if (port_ops && port_ops->pre_reset) + port_ops->pre_reset(drive); + + if (drive->current_speed != 0xff) + drive->desired_speed = drive->current_speed; + drive->current_speed = 0xff; +} + +/* + * do_reset1() attempts to recover a confused drive by resetting it. + * Unfortunately, resetting a disk drive actually resets all devices on + * the same interface, so it can really be thought of as resetting the + * interface rather than resetting the drive. + * + * ATAPI devices have their own reset mechanism which allows them to be + * individually reset without clobbering other devices on the same interface. + * + * Unfortunately, the IDE interface does not generate an interrupt to let + * us know when the reset operation has finished, so we must poll for this. + * Equally poor, though, is the fact that this may a very long time to complete, + * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, + * we set a timer to poll at 50ms intervals. + */ +static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi) +{ + ide_hwif_t *hwif = drive->hwif; + struct ide_io_ports *io_ports = &hwif->io_ports; + const struct ide_tp_ops *tp_ops = hwif->tp_ops; + const struct ide_port_ops *port_ops; + ide_drive_t *tdrive; + unsigned long flags, timeout; + int i; + DEFINE_WAIT(wait); + + spin_lock_irqsave(&hwif->lock, flags); + + /* We must not reset with running handlers */ + BUG_ON(hwif->handler != NULL); + + /* For an ATAPI device, first try an ATAPI SRST. */ + if (drive->media != ide_disk && !do_not_try_atapi) { + pre_reset(drive); + SELECT_DRIVE(drive); + udelay(20); + tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); + ndelay(400); + hwif->poll_timeout = jiffies + WAIT_WORSTCASE; + hwif->polling = 1; + __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); + spin_unlock_irqrestore(&hwif->lock, flags); + return ide_started; + } + + /* We must not disturb devices in the IDE_DFLAG_PARKED state. */ + do { + unsigned long now; + + prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE); + timeout = jiffies; + ide_port_for_each_present_dev(i, tdrive, hwif) { + if ((tdrive->dev_flags & IDE_DFLAG_PARKED) && + time_after(tdrive->sleep, timeout)) + timeout = tdrive->sleep; + } + + now = jiffies; + if (time_before_eq(timeout, now)) + break; + + spin_unlock_irqrestore(&hwif->lock, flags); + timeout = schedule_timeout_uninterruptible(timeout - now); + spin_lock_irqsave(&hwif->lock, flags); + } while (timeout); + finish_wait(&ide_park_wq, &wait); + + /* + * First, reset any device state data we were maintaining + * for any of the drives on this interface. + */ + ide_port_for_each_dev(i, tdrive, hwif) + pre_reset(tdrive); + + if (io_ports->ctl_addr == 0) { + spin_unlock_irqrestore(&hwif->lock, flags); + ide_complete_drive_reset(drive, -ENXIO); + return ide_stopped; + } + + /* + * Note that we also set nIEN while resetting the device, + * to mask unwanted interrupts from the interface during the reset. + * However, due to the design of PC hardware, this will cause an + * immediate interrupt due to the edge transition it produces. + * This single interrupt gives us a "fast poll" for drives that + * recover from reset very quickly, saving us the first 50ms wait time. + * + * TODO: add ->softreset method and stop abusing ->set_irq + */ + /* set SRST and nIEN */ + tp_ops->set_irq(hwif, 4); + /* more than enough time */ + udelay(10); + /* clear SRST, leave nIEN (unless device is on the quirk list) */ + tp_ops->set_irq(hwif, drive->quirk_list == 2); + /* more than enough time */ + udelay(10); + hwif->poll_timeout = jiffies + WAIT_WORSTCASE; + hwif->polling = 1; + __ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); + + /* + * Some weird controller like resetting themselves to a strange + * state when the disks are reset this way. At least, the Winbond + * 553 documentation says that + */ + port_ops = hwif->port_ops; + if (port_ops && port_ops->resetproc) + port_ops->resetproc(drive); + + spin_unlock_irqrestore(&hwif->lock, flags); + return ide_started; +} + +/* + * ide_do_reset() is the entry point to the drive/interface reset code. + */ + +ide_startstop_t ide_do_reset(ide_drive_t *drive) +{ + return do_reset1(drive, 0); +} +EXPORT_SYMBOL(ide_do_reset); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 74d1a3e6825..2e92497b58a 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -196,7 +196,7 @@ void ide_end_drive_cmd (ide_drive_t *drive, u8 stat, u8 err) } EXPORT_SYMBOL(ide_end_drive_cmd); -static void ide_kill_rq(ide_drive_t *drive, struct request *rq) +void ide_kill_rq(ide_drive_t *drive, struct request *rq) { if (rq->rq_disk) { struct ide_driver *drv; @@ -207,133 +207,6 @@ static void ide_kill_rq(ide_drive_t *drive, struct request *rq) ide_end_request(drive, 0, 0); } -static ide_startstop_t ide_ata_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - ide_hwif_t *hwif = drive->hwif; - - if ((stat & ATA_BUSY) || - ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { - /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else if (stat & ATA_ERR) { - /* err has different meaning on cdrom and tape */ - if (err == ATA_ABORTED) { - if ((drive->dev_flags & IDE_DFLAG_LBA) && - /* some newer drives don't support ATA_CMD_INIT_DEV_PARAMS */ - hwif->tp_ops->read_status(hwif) == ATA_CMD_INIT_DEV_PARAMS) - return ide_stopped; - } else if ((err & BAD_CRC) == BAD_CRC) { - /* UDMA crc error, just retry the operation */ - drive->crc_count++; - } else if (err & (ATA_BBK | ATA_UNC)) { - /* retries won't help these */ - rq->errors = ERROR_MAX; - } else if (err & ATA_TRK0NF) { - /* help it find track zero */ - rq->errors |= ERROR_RECAL; - } - } - - if ((stat & ATA_DRQ) && rq_data_dir(rq) == READ && - (hwif->host_flags & IDE_HFLAG_ERROR_STOPS_FIFO) == 0) { - int nsect = drive->mult_count ? drive->mult_count : 1; - - ide_pad_transfer(drive, READ, nsect * SECTOR_SIZE); - } - - if (rq->errors >= ERROR_MAX || blk_noretry_request(rq)) { - ide_kill_rq(drive, rq); - return ide_stopped; - } - - if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) - rq->errors |= ERROR_RESET; - - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - - if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) - drive->special.b.recalibrate = 1; - - ++rq->errors; - - return ide_stopped; -} - -static ide_startstop_t ide_atapi_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - ide_hwif_t *hwif = drive->hwif; - - if ((stat & ATA_BUSY) || - ((stat & ATA_DF) && (drive->dev_flags & IDE_DFLAG_NOWERR) == 0)) { - /* other bits are useless when BUSY */ - rq->errors |= ERROR_RESET; - } else { - /* add decoding error stuff */ - } - - if (hwif->tp_ops->read_status(hwif) & (ATA_BUSY | ATA_DRQ)) - /* force an abort */ - hwif->tp_ops->exec_command(hwif, ATA_CMD_IDLEIMMEDIATE); - - if (rq->errors >= ERROR_MAX) { - ide_kill_rq(drive, rq); - } else { - if ((rq->errors & ERROR_RESET) == ERROR_RESET) { - ++rq->errors; - return ide_do_reset(drive); - } - ++rq->errors; - } - - return ide_stopped; -} - -static ide_startstop_t -__ide_error(ide_drive_t *drive, struct request *rq, u8 stat, u8 err) -{ - if (drive->media == ide_disk) - return ide_ata_error(drive, rq, stat, err); - return ide_atapi_error(drive, rq, stat, err); -} - -/** - * ide_error - handle an error on the IDE - * @drive: drive the error occurred on - * @msg: message to report - * @stat: status bits - * - * ide_error() takes action based on the error returned by the drive. - * For normal I/O that may well include retries. We deal with - * both new-style (taskfile) and old style command handling here. - * In the case of taskfile command handling there is work left to - * do - */ - -ide_startstop_t ide_error (ide_drive_t *drive, const char *msg, u8 stat) -{ - struct request *rq; - u8 err; - - err = ide_dump_status(drive, msg, stat); - - rq = drive->hwif->rq; - if (rq == NULL) - return ide_stopped; - - /* retry only "normal" I/O: */ - if (!blk_fs_request(rq)) { - rq->errors = 1; - ide_end_drive_cmd(drive, stat, err); - return ide_stopped; - } - - return __ide_error(drive, rq, stat, err); -} -EXPORT_SYMBOL_GPL(ide_error); - static void ide_tf_set_specify_cmd(ide_drive_t *drive, struct ide_taskfile *tf) { tf->nsect = drive->sect; diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index cf6c3036ae7..e0cfa2d2acc 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -446,8 +446,8 @@ int ide_config_drive_speed(ide_drive_t *drive, u8 speed) * * See also ide_execute_command */ -static void __ide_set_handler (ide_drive_t *drive, ide_handler_t *handler, - unsigned int timeout, ide_expiry_t *expiry) +void __ide_set_handler(ide_drive_t *drive, ide_handler_t *handler, + unsigned int timeout, ide_expiry_t *expiry) { ide_hwif_t *hwif = drive->hwif; @@ -517,301 +517,6 @@ void ide_execute_pkt_cmd(ide_drive_t *drive) } EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd); -static inline void ide_complete_drive_reset(ide_drive_t *drive, int err) -{ - struct request *rq = drive->hwif->rq; - - if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET) - ide_end_request(drive, err ? err : 1, 0); -} - -/* needed below */ -static ide_startstop_t do_reset1(ide_drive_t *, int); - -/* - * atapi_reset_pollfunc() gets invoked to poll the interface for completion - * every 50ms during an atapi drive reset operation. If the drive has not yet - * responded, and we have not yet hit our maximum waiting time, then the timer - * is restarted for another 50ms. - */ -static ide_startstop_t atapi_reset_pollfunc(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - u8 stat; - - SELECT_DRIVE(drive); - udelay(10); - stat = hwif->tp_ops->read_status(hwif); - - if (OK_STAT(stat, 0, ATA_BUSY)) - printk(KERN_INFO "%s: ATAPI reset complete\n", drive->name); - else { - if (time_before(jiffies, hwif->poll_timeout)) { - ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, - NULL); - /* continue polling */ - return ide_started; - } - /* end of polling */ - hwif->polling = 0; - printk(KERN_ERR "%s: ATAPI reset timed-out, status=0x%02x\n", - drive->name, stat); - /* do it the old fashioned way */ - return do_reset1(drive, 1); - } - /* done polling */ - hwif->polling = 0; - ide_complete_drive_reset(drive, 0); - return ide_stopped; -} - -static void ide_reset_report_error(ide_hwif_t *hwif, u8 err) -{ - static const char *err_master_vals[] = - { NULL, "passed", "formatter device error", - "sector buffer error", "ECC circuitry error", - "controlling MPU error" }; - - u8 err_master = err & 0x7f; - - printk(KERN_ERR "%s: reset: master: ", hwif->name); - if (err_master && err_master < 6) - printk(KERN_CONT "%s", err_master_vals[err_master]); - else - printk(KERN_CONT "error (0x%02x?)", err); - if (err & 0x80) - printk(KERN_CONT "; slave: failed"); - printk(KERN_CONT "\n"); -} - -/* - * reset_pollfunc() gets invoked to poll the interface for completion every 50ms - * during an ide reset operation. If the drives have not yet responded, - * and we have not yet hit our maximum waiting time, then the timer is restarted - * for another 50ms. - */ -static ide_startstop_t reset_pollfunc(ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_port_ops *port_ops = hwif->port_ops; - u8 tmp; - int err = 0; - - if (port_ops && port_ops->reset_poll) { - err = port_ops->reset_poll(drive); - if (err) { - printk(KERN_ERR "%s: host reset_poll failure for %s.\n", - hwif->name, drive->name); - goto out; - } - } - - tmp = hwif->tp_ops->read_status(hwif); - - if (!OK_STAT(tmp, 0, ATA_BUSY)) { - if (time_before(jiffies, hwif->poll_timeout)) { - ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); - /* continue polling */ - return ide_started; - } - printk(KERN_ERR "%s: reset timed-out, status=0x%02x\n", - hwif->name, tmp); - drive->failures++; - err = -EIO; - } else { - tmp = ide_read_error(drive); - - if (tmp == 1) { - printk(KERN_INFO "%s: reset: success\n", hwif->name); - drive->failures = 0; - } else { - ide_reset_report_error(hwif, tmp); - drive->failures++; - err = -EIO; - } - } -out: - hwif->polling = 0; /* done polling */ - ide_complete_drive_reset(drive, err); - return ide_stopped; -} - -static void ide_disk_pre_reset(ide_drive_t *drive) -{ - int legacy = (drive->id[ATA_ID_CFS_ENABLE_2] & 0x0400) ? 0 : 1; - - drive->special.all = 0; - drive->special.b.set_geometry = legacy; - drive->special.b.recalibrate = legacy; - - drive->mult_count = 0; - drive->dev_flags &= ~IDE_DFLAG_PARKED; - - if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0 && - (drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) - drive->mult_req = 0; - - if (drive->mult_req != drive->mult_count) - drive->special.b.set_multmode = 1; -} - -static void pre_reset(ide_drive_t *drive) -{ - const struct ide_port_ops *port_ops = drive->hwif->port_ops; - - if (drive->media == ide_disk) - ide_disk_pre_reset(drive); - else - drive->dev_flags |= IDE_DFLAG_POST_RESET; - - if (drive->dev_flags & IDE_DFLAG_USING_DMA) { - if (drive->crc_count) - ide_check_dma_crc(drive); - else - ide_dma_off(drive); - } - - if ((drive->dev_flags & IDE_DFLAG_KEEP_SETTINGS) == 0) { - if ((drive->dev_flags & IDE_DFLAG_USING_DMA) == 0) { - drive->dev_flags &= ~IDE_DFLAG_UNMASK; - drive->io_32bit = 0; - } - return; - } - - if (port_ops && port_ops->pre_reset) - port_ops->pre_reset(drive); - - if (drive->current_speed != 0xff) - drive->desired_speed = drive->current_speed; - drive->current_speed = 0xff; -} - -/* - * do_reset1() attempts to recover a confused drive by resetting it. - * Unfortunately, resetting a disk drive actually resets all devices on - * the same interface, so it can really be thought of as resetting the - * interface rather than resetting the drive. - * - * ATAPI devices have their own reset mechanism which allows them to be - * individually reset without clobbering other devices on the same interface. - * - * Unfortunately, the IDE interface does not generate an interrupt to let - * us know when the reset operation has finished, so we must poll for this. - * Equally poor, though, is the fact that this may a very long time to complete, - * (up to 30 seconds worstcase). So, instead of busy-waiting here for it, - * we set a timer to poll at 50ms intervals. - */ -static ide_startstop_t do_reset1(ide_drive_t *drive, int do_not_try_atapi) -{ - ide_hwif_t *hwif = drive->hwif; - struct ide_io_ports *io_ports = &hwif->io_ports; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - const struct ide_port_ops *port_ops; - ide_drive_t *tdrive; - unsigned long flags, timeout; - int i; - DEFINE_WAIT(wait); - - spin_lock_irqsave(&hwif->lock, flags); - - /* We must not reset with running handlers */ - BUG_ON(hwif->handler != NULL); - - /* For an ATAPI device, first try an ATAPI SRST. */ - if (drive->media != ide_disk && !do_not_try_atapi) { - pre_reset(drive); - SELECT_DRIVE(drive); - udelay(20); - tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); - ndelay(400); - hwif->poll_timeout = jiffies + WAIT_WORSTCASE; - hwif->polling = 1; - __ide_set_handler(drive, &atapi_reset_pollfunc, HZ/20, NULL); - spin_unlock_irqrestore(&hwif->lock, flags); - return ide_started; - } - - /* We must not disturb devices in the IDE_DFLAG_PARKED state. */ - do { - unsigned long now; - - prepare_to_wait(&ide_park_wq, &wait, TASK_UNINTERRUPTIBLE); - timeout = jiffies; - ide_port_for_each_present_dev(i, tdrive, hwif) { - if ((tdrive->dev_flags & IDE_DFLAG_PARKED) && - time_after(tdrive->sleep, timeout)) - timeout = tdrive->sleep; - } - - now = jiffies; - if (time_before_eq(timeout, now)) - break; - - spin_unlock_irqrestore(&hwif->lock, flags); - timeout = schedule_timeout_uninterruptible(timeout - now); - spin_lock_irqsave(&hwif->lock, flags); - } while (timeout); - finish_wait(&ide_park_wq, &wait); - - /* - * First, reset any device state data we were maintaining - * for any of the drives on this interface. - */ - ide_port_for_each_dev(i, tdrive, hwif) - pre_reset(tdrive); - - if (io_ports->ctl_addr == 0) { - spin_unlock_irqrestore(&hwif->lock, flags); - ide_complete_drive_reset(drive, -ENXIO); - return ide_stopped; - } - - /* - * Note that we also set nIEN while resetting the device, - * to mask unwanted interrupts from the interface during the reset. - * However, due to the design of PC hardware, this will cause an - * immediate interrupt due to the edge transition it produces. - * This single interrupt gives us a "fast poll" for drives that - * recover from reset very quickly, saving us the first 50ms wait time. - * - * TODO: add ->softreset method and stop abusing ->set_irq - */ - /* set SRST and nIEN */ - tp_ops->set_irq(hwif, 4); - /* more than enough time */ - udelay(10); - /* clear SRST, leave nIEN (unless device is on the quirk list) */ - tp_ops->set_irq(hwif, drive->quirk_list == 2); - /* more than enough time */ - udelay(10); - hwif->poll_timeout = jiffies + WAIT_WORSTCASE; - hwif->polling = 1; - __ide_set_handler(drive, &reset_pollfunc, HZ/20, NULL); - - /* - * Some weird controller like resetting themselves to a strange - * state when the disks are reset this way. At least, the Winbond - * 553 documentation says that - */ - port_ops = hwif->port_ops; - if (port_ops && port_ops->resetproc) - port_ops->resetproc(drive); - - spin_unlock_irqrestore(&hwif->lock, flags); - return ide_started; -} - -/* - * ide_do_reset() is the entry point to the drive/interface reset code. - */ - -ide_startstop_t ide_do_reset(ide_drive_t *drive) -{ - return do_reset1(drive, 0); -} -EXPORT_SYMBOL(ide_do_reset); - /* * ide_wait_not_busy() waits for the currently selected device on the hwif * to report a non-busy status, see comments in ide_probe_port(). -- cgit v1.2.3 From 213e4b0a3483b8cc99c4578923b9899e84e086e0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:48 +0100 Subject: amd74xx: use ide_pci_is_in_compatibility_mode() Fix ->init_hwif to check if IDE PCI controller is in compatibility mode instead of checking for hwif->irq == 0. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/amd74xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 77267c85996..0caecad1998 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -187,7 +187,7 @@ static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) { struct pci_dev *dev = to_pci_dev(hwif->dev); - if (hwif->irq == 0) /* 0 is bogus but will do for now */ + if (ide_pci_is_in_compatibility_mode(dev)) hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); } -- cgit v1.2.3 From 973d9e743979d4d3f06d8071c22187b2bdc0ef24 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:48 +0100 Subject: ns87415: use pci_get_legacy_ide_irq() Fix ->init_hwif to use pci_get_legacy_ide_irq() instead of __ide_default_irq(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ns87415.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 83643ed9a42..56042a36d63 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c @@ -286,7 +286,7 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) } if (!using_inta) - hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); + hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); else if (!hwif->irq && hwif->mate && hwif->mate->irq) hwif->irq = hwif->mate->irq; /* share IRQ with mate */ -- cgit v1.2.3 From 49727e3d20ba10921572e35bc99b2c2e1b8c1dba Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:49 +0100 Subject: ns87415: small ->init_hwif cleanup Core IDE PCI code takes care of assigning hwif->irq for both ports. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ns87415.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 56042a36d63..ea48a3ee806 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c @@ -287,8 +287,6 @@ static void __devinit init_hwif_ns87415 (ide_hwif_t *hwif) if (!using_inta) hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); - else if (!hwif->irq && hwif->mate && hwif->mate->irq) - hwif->irq = hwif->mate->irq; /* share IRQ with mate */ if (!hwif->dma_base) return; -- cgit v1.2.3 From 1b166ae7bb9610cdd3c4c66b960aa04004054e41 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:49 +0100 Subject: trm290: small ->init_hwif cleanup Core IDE PCI code takes care of assigning hwif->irq for both ports. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/trm290.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c index b6a1285a402..1c09e549c42 100644 --- a/drivers/ide/trm290.c +++ b/drivers/ide/trm290.c @@ -277,9 +277,6 @@ static void __devinit init_hwif_trm290(ide_hwif_t *hwif) if (reg & 0x10) /* legacy mode */ hwif->irq = hwif->channel ? 15 : 14; - else if (!hwif->irq && hwif->mate && hwif->mate->irq) - /* sharing IRQ with mate */ - hwif->irq = hwif->mate->irq; #if 1 { -- cgit v1.2.3 From 80d15a607ae95dd0514ab1ab5ea1058a3a585f2b Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:49 +0100 Subject: ide: handle IDE_HFLAG[_FORCE]_LEGACY_IRQS in ide_pci_init_{one,two}() Move handling of IDE_HFLAG[_FORCE]_LEGACY_IRQS from ide_init_port() to ide_pci_init_{one,two}(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 4 ---- drivers/ide/setup-pci.c | 12 ++++++++++++ 2 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a51ad2bd62b..80967307f2b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1183,10 +1183,6 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, if (d->init_iops) d->init_iops(hwif); - if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || - (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) - hwif->irq = port ? 15 : 14; - /* ->host_flags may be set by ->init_iops (or even earlier...) */ hwif->host_flags |= d->host_flags; hwif->pio_mask = d->pio_mask; diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index e85d1ed29c2..9482288e861 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -570,6 +570,12 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, /* fixup IRQ */ hw[1].irq = hw[0].irq = ret; + if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || + (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { + hw[0].irq = 14; + hw[1].irq = 15; + } + ret = ide_host_register(host, d, hws); if (ret) ide_host_free(host); @@ -620,6 +626,12 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, /* fixup IRQ */ hw[i*2 + 1].irq = hw[i*2].irq = ret; + + if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || + (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { + hw[i*2].irq = 14; + hw[i*2 + 1].irq = 15; + } } ret = ide_host_register(host, d, hws); -- cgit v1.2.3 From 5bae8bf4508004d46487b3a18769d0ccff01c532 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:49 +0100 Subject: ide: use pci_get_legacy_ide_irq() in ide_pci_init_{one,two}() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/setup-pci.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 9482288e861..fa645fc41b8 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -572,8 +572,8 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { - hw[0].irq = 14; - hw[1].irq = 15; + hw[0].irq = pci_get_legacy_ide_irq(dev, 0); + hw[1].irq = pci_get_legacy_ide_irq(dev, 1); } ret = ide_host_register(host, d, hws); @@ -629,8 +629,8 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { - hw[i*2].irq = 14; - hw[i*2 + 1].irq = 15; + hw[i*2].irq = pci_get_legacy_ide_irq(pdev[i], 0); + hw[i*2 + 1].irq = pci_get_legacy_ide_irq(pdev[i], 1); } } -- cgit v1.2.3 From f65dedfd7b75f19bde42bafbe84fddce18c42499 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:51 +0100 Subject: ide: use ide_pci_is_in_compatibility_mode() in ide_pci_init_{one,two}() Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/setup-pci.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index fa645fc41b8..79e3244691e 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -568,13 +568,11 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, goto out; /* fixup IRQ */ - hw[1].irq = hw[0].irq = ret; - - if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || - (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { + if (ide_pci_is_in_compatibility_mode(dev)) { hw[0].irq = pci_get_legacy_ide_irq(dev, 0); hw[1].irq = pci_get_legacy_ide_irq(dev, 1); - } + } else + hw[1].irq = hw[0].irq = ret; ret = ide_host_register(host, d, hws); if (ret) @@ -625,13 +623,11 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, goto out; /* fixup IRQ */ - hw[i*2 + 1].irq = hw[i*2].irq = ret; - - if ((ret == 0 && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || - (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) { + if (ide_pci_is_in_compatibility_mode(pdev[i])) { hw[i*2].irq = pci_get_legacy_ide_irq(pdev[i], 0); hw[i*2 + 1].irq = pci_get_legacy_ide_irq(pdev[i], 1); - } + } else + hw[i*2 + 1].irq = hw[i*2].irq = ret; } ret = ide_host_register(host, d, hws); -- cgit v1.2.3 From 2467922a560bb7e6eb4635435760ad0a2197ffcc Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:52 +0100 Subject: ide: remove no longer needed IDE_HFLAG[_FORCE]_LEGACY_IRQS There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/atiixp.c | 3 +-- drivers/ide/ide-pci-generic.c | 4 +--- drivers/ide/piix.c | 11 +---------- drivers/ide/serverworks.c | 9 ++------- drivers/ide/sis5513.c | 2 +- drivers/ide/slc90e66.c | 1 - drivers/ide/via82cxxx.c | 10 ---------- 7 files changed, 6 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c index ecd1e62ca91..923cbfe259d 100644 --- a/drivers/ide/atiixp.c +++ b/drivers/ide/atiixp.c @@ -142,7 +142,6 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = { .name = DRV_NAME, .enablebits = {{0x48,0x01,0x00}, {0x48,0x08,0x00}}, .port_ops = &atiixp_port_ops, - .host_flags = IDE_HFLAG_LEGACY_IRQS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -151,7 +150,7 @@ static const struct ide_port_info atiixp_pci_info[] __devinitdata = { .name = DRV_NAME, .enablebits = {{0x48,0x01,0x00}, {0x00,0x00,0x00}}, .port_ops = &atiixp_port_ops, - .host_flags = IDE_HFLAG_SINGLE | IDE_HFLAG_LEGACY_IRQS, + .host_flags = IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, diff --git a/drivers/ide/ide-pci-generic.c b/drivers/ide/ide-pci-generic.c index bddae2b329a..61111fd2713 100644 --- a/drivers/ide/ide-pci-generic.c +++ b/drivers/ide/ide-pci-generic.c @@ -33,8 +33,6 @@ static int ide_generic_all; /* Set to claim all devices */ module_param_named(all_generic_ide, ide_generic_all, bool, 0444); MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); -#define IDE_HFLAGS_UMC (IDE_HFLAG_NO_DMA | IDE_HFLAG_FORCE_LEGACY_IRQS) - #define DECLARE_GENERIC_PCI_DEV(extra_flags) \ { \ .name = DRV_NAME, \ @@ -61,7 +59,7 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = { /* 2: SAMURAI / HT6565 / HINT_IDE */ DECLARE_GENERIC_PCI_DEV(0), /* 3: UM8673F / UM8886A / UM8886BF */ - DECLARE_GENERIC_PCI_DEV(IDE_HFLAGS_UMC), + DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_DMA), /* 4: VIA_IDE / OPTI621V / Piccolo010{2,3,5} */ DECLARE_GENERIC_PCI_DEV(IDE_HFLAG_NO_AUTODMA), diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index f1e2e4ef0d7..42c2e3522d7 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -318,19 +318,12 @@ static const struct ide_port_ops ich_port_ops = { .cable_detect = piix_cable_detect, }; -#ifndef CONFIG_IA64 - #define IDE_HFLAGS_PIIX IDE_HFLAG_LEGACY_IRQS -#else - #define IDE_HFLAGS_PIIX 0 -#endif - #define DECLARE_PIIX_DEV(udma) \ { \ .name = DRV_NAME, \ .init_hwif = init_hwif_piix, \ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ .port_ops = &piix_port_ops, \ - .host_flags = IDE_HFLAGS_PIIX, \ .pio_mask = ATA_PIO4, \ .swdma_mask = ATA_SWDMA2_ONLY, \ .mwdma_mask = ATA_MWDMA12_ONLY, \ @@ -344,7 +337,6 @@ static const struct ide_port_ops ich_port_ops = { .init_hwif = init_hwif_piix, \ .enablebits = {{0x41,0x80,0x80}, {0x43,0x80,0x80}}, \ .port_ops = &ich_port_ops, \ - .host_flags = IDE_HFLAGS_PIIX, \ .pio_mask = ATA_PIO4, \ .swdma_mask = ATA_SWDMA2_ONLY, \ .mwdma_mask = ATA_MWDMA12_ONLY, \ @@ -360,8 +352,7 @@ static const struct ide_port_info piix_pci_info[] __devinitdata = { */ .name = DRV_NAME, .enablebits = {{0x6d,0xc0,0x80}, {0x6d,0xc0,0xc0}}, - .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA | - IDE_HFLAGS_PIIX, + .host_flags = IDE_HFLAG_ISA_PORTS | IDE_HFLAG_NO_DMA, .pio_mask = ATA_PIO4, /* This is a painful system best to let it self tune for now */ }, diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index 382102ba467..14718e73991 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c @@ -353,14 +353,11 @@ static const struct ide_port_ops svwks_port_ops = { .cable_detect = svwks_cable_detect, }; -#define IDE_HFLAGS_SVWKS IDE_HFLAG_LEGACY_IRQS - static const struct ide_port_info serverworks_chipsets[] __devinitdata = { { /* 0: OSB4 */ .name = DRV_NAME, .init_chipset = init_chipset_svwks, .port_ops = &osb4_port_ops, - .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = 0x00, /* UDMA is problematic on OSB4 */ @@ -369,7 +366,6 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_svwks, .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -378,7 +374,6 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_svwks, .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -387,7 +382,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_svwks, .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, + .host_flags = IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, @@ -396,7 +391,7 @@ static const struct ide_port_info serverworks_chipsets[] __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_svwks, .port_ops = &svwks_port_ops, - .host_flags = IDE_HFLAGS_SVWKS | IDE_HFLAG_SINGLE, + .host_flags = IDE_HFLAG_SINGLE, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index 9ec1a4a4432..d2d54aaea13 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -563,7 +563,7 @@ static const struct ide_port_info sis5513_chipset __devinitdata = { .name = DRV_NAME, .init_chipset = init_chipset_sis5513, .enablebits = { {0x4a, 0x02, 0x02}, {0x4a, 0x04, 0x04} }, - .host_flags = IDE_HFLAG_LEGACY_IRQS | IDE_HFLAG_NO_AUTODMA, + .host_flags = IDE_HFLAG_NO_AUTODMA, .pio_mask = ATA_PIO4, .mwdma_mask = ATA_MWDMA2, }; diff --git a/drivers/ide/slc90e66.c b/drivers/ide/slc90e66.c index 40b4b94a428..f55d7d6313e 100644 --- a/drivers/ide/slc90e66.c +++ b/drivers/ide/slc90e66.c @@ -136,7 +136,6 @@ static const struct ide_port_info slc90e66_chipset __devinitdata = { .name = DRV_NAME, .enablebits = { {0x41, 0x80, 0x80}, {0x43, 0x80, 0x80} }, .port_ops = &slc90e66_port_ops, - .host_flags = IDE_HFLAG_LEGACY_IRQS, .pio_mask = ATA_PIO4, .swdma_mask = ATA_SWDMA2_ONLY, .mwdma_mask = ATA_MWDMA12_ONLY, diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index 6092fe3f409..a41eab5cb5d 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -443,16 +443,6 @@ static int __devinit via_init_one(struct pci_dev *dev, const struct pci_device_i if ((via_config->flags & VIA_NO_UNMASK) == 0) d.host_flags |= IDE_HFLAG_UNMASK_IRQS; -#ifdef CONFIG_PPC_CHRP - if (machine_is(chrp) && _chrp_type == _CHRP_Pegasos) - d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; -#endif - -#ifdef CONFIG_AMIGAONE - if (machine_is(amigaone)) - d.host_flags |= IDE_HFLAG_FORCE_LEGACY_IRQS; -#endif - d.udma_mask = via_config->udma_mask; vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); -- cgit v1.2.3 From bd0c08470fcded75d3904734ee22ae5b363737db Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:52 +0100 Subject: amd74xx: remove no longer needed ->init_hwif method This is now handled by core IDE PCI code. There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/amd74xx.c | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 0caecad1998..0b51921e63e 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -183,14 +183,6 @@ static u8 amd_cable_detect(ide_hwif_t *hwif) return ATA_CBL_PATA40; } -static void __devinit init_hwif_amd74xx(ide_hwif_t *hwif) -{ - struct pci_dev *dev = to_pci_dev(hwif->dev); - - if (ide_pci_is_in_compatibility_mode(dev)) - hwif->irq = pci_get_legacy_ide_irq(dev, hwif->channel); -} - static const struct ide_port_ops amd_port_ops = { .set_pio_mode = amd_set_pio_mode, .set_dma_mode = amd_set_drive, @@ -207,7 +199,6 @@ static const struct ide_port_ops amd_port_ops = { { \ .name = DRV_NAME, \ .init_chipset = init_chipset_amd74xx, \ - .init_hwif = init_hwif_amd74xx, \ .enablebits = {{0x40,0x02,0x02}, {0x40,0x01,0x01}}, \ .port_ops = &amd_port_ops, \ .host_flags = IDE_HFLAGS_AMD, \ @@ -221,7 +212,6 @@ static const struct ide_port_ops amd_port_ops = { { \ .name = DRV_NAME, \ .init_chipset = init_chipset_amd74xx, \ - .init_hwif = init_hwif_amd74xx, \ .enablebits = {{0x50,0x02,0x02}, {0x50,0x01,0x01}}, \ .port_ops = &amd_port_ops, \ .host_flags = IDE_HFLAGS_AMD, \ -- cgit v1.2.3 From 8b07ed26f8eb73d4f55a9d852712cd588c45ff51 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:52 +0100 Subject: ide: remove no longer needed IRQ fallback code from hwif_init() Then remove no longer used __ide_default_irq(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 30 ++++-------------------------- 1 file changed, 4 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 80967307f2b..ebc328c2e7e 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1070,14 +1070,9 @@ static void drive_release_dev (struct device *dev) static int hwif_init(ide_hwif_t *hwif) { - int old_irq; - if (!hwif->irq) { - hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); - if (!hwif->irq) { - printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name); - return 0; - } + printk(KERN_ERR "%s: disabled, no IRQ\n", hwif->name); + return 0; } if (register_blkdev(hwif->major, hwif->name)) @@ -1095,29 +1090,12 @@ static int hwif_init(ide_hwif_t *hwif) sg_init_table(hwif->sg_table, hwif->sg_max_nents); - if (init_irq(hwif) == 0) - goto done; - - old_irq = hwif->irq; - /* - * It failed to initialise. Find the default IRQ for - * this port and try that. - */ - hwif->irq = __ide_default_irq(hwif->io_ports.data_addr); - if (!hwif->irq) { - printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n", - hwif->name, old_irq); - goto out; - } if (init_irq(hwif)) { - printk(KERN_ERR "%s: probed IRQ %d and default IRQ %d failed\n", - hwif->name, old_irq, hwif->irq); + printk(KERN_ERR "%s: disabled, unable to get IRQ %d\n", + hwif->name, hwif->irq); goto out; } - printk(KERN_WARNING "%s: probed IRQ %d failed, using default\n", - hwif->name, hwif->irq); -done: blk_register_region(MKDEV(hwif->major, 0), MAX_DRIVES << PARTN_BITS, THIS_MODULE, ata_probe, ata_lock, hwif); return 1; -- cgit v1.2.3 From f77e03c68f11f54509cd660ddb5a0badfdfc61cb Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:53 +0100 Subject: ide: remove no longer needed IRQ auto-probing from try_to_identify() (v2) v2: Update actual_try_to_identify() documentation. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 50 +++++++------------------------------------------ 1 file changed, 7 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index ebc328c2e7e..c63c0780758 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -255,9 +255,7 @@ err_misc: * @cmd: command to use * * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive - * and waits for a response. It also monitors irqs while this is - * happening, in hope of automatically determining which one is - * being used by the interface. + * and waits for a response. * * Returns: 0 device was identified * 1 device timed-out (no response to identify request) @@ -334,56 +332,22 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) * @drive: drive to probe * @cmd: command to use * - * Issue the identify command and then do IRQ probing to - * complete the identification when needed by finding the - * IRQ the drive is attached to + * Issue the identify command. */ static int try_to_identify (ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; - int retval; - int autoprobe = 0; - unsigned long cookie = 0; /* - * Disable device irq unless we need to - * probe for it. Otherwise we'll get spurious - * interrupts during the identify-phase that - * the irq handler isn't expecting. + * Disable device IRQ. Otherwise we'll get spurious interrupts + * during the identify phase that the IRQ handler isn't expecting. */ - if (hwif->io_ports.ctl_addr) { - if (!hwif->irq) { - autoprobe = 1; - cookie = probe_irq_on(); - } - tp_ops->set_irq(hwif, autoprobe); - } - - retval = actual_try_to_identify(drive, cmd); - - if (autoprobe) { - int irq; - + if (hwif->io_ports.ctl_addr) tp_ops->set_irq(hwif, 0); - /* clear drive IRQ */ - (void)tp_ops->read_status(hwif); - udelay(5); - irq = probe_irq_off(cookie); - if (!hwif->irq) { - if (irq > 0) { - hwif->irq = irq; - } else { - /* Mmmm.. multiple IRQs.. - * don't know which was ours - */ - printk(KERN_ERR "%s: IRQ probe failed (0x%lx)\n", - drive->name, cookie); - } - } - } - return retval; + + return actual_try_to_identify(drive, cmd); } int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus) -- cgit v1.2.3 From a182807a89946bd531122bb2da60fa9ceee90343 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:53 +0100 Subject: ide: remove try_to_identify() wrapper There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index c63c0780758..5e0c3fb3b43 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -250,7 +250,7 @@ err_misc: } /** - * actual_try_to_identify - send ata/atapi identify + * try_to_identify - send ATA/ATAPI identify * @drive: drive to identify * @cmd: command to use * @@ -262,7 +262,7 @@ err_misc: * 2 device aborted the command (refused to identify itself) */ -static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) +static int try_to_identify(ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = drive->hwif; struct ide_io_ports *io_ports = &hwif->io_ports; @@ -271,6 +271,13 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) unsigned long timeout; u8 s = 0, a = 0; + /* + * Disable device IRQ. Otherwise we'll get spurious interrupts + * during the identify phase that the IRQ handler isn't expecting. + */ + if (io_ports->ctl_addr) + tp_ops->set_irq(hwif, 0); + /* take a deep breath */ msleep(50); @@ -327,29 +334,6 @@ static int actual_try_to_identify (ide_drive_t *drive, u8 cmd) return rc; } -/** - * try_to_identify - try to identify a drive - * @drive: drive to probe - * @cmd: command to use - * - * Issue the identify command. - */ - -static int try_to_identify (ide_drive_t *drive, u8 cmd) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - - /* - * Disable device IRQ. Otherwise we'll get spurious interrupts - * during the identify phase that the IRQ handler isn't expecting. - */ - if (hwif->io_ports.ctl_addr) - tp_ops->set_irq(hwif, 0); - - return actual_try_to_identify(drive, cmd); -} - int ide_busy_sleep(ide_hwif_t *hwif, unsigned long timeout, int altstatus) { u8 stat; -- cgit v1.2.3 From 2ed0ef543ae3f3ea4f8bd0433fb1fed22625a309 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:53 +0100 Subject: ide: fix ->init_chipset method to return 'int' value * Return 0 instead of dev->irq in ->init_chipset implementations. * Fix ->init_chipset method to return 'int' value instead of 'unsigned int' one. This fixes ->init_chipset handling for host drivers (cs5530, hpt366 and pdc202xx_new) for which it is possible for this method to fail. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/aec62xx.c | 4 ++-- drivers/ide/alim15x3.c | 2 +- drivers/ide/amd74xx.c | 4 ++-- drivers/ide/cmd64x.c | 2 +- drivers/ide/cs5530.c | 2 +- drivers/ide/delkin_cb.c | 2 +- drivers/ide/hpt366.c | 4 ++-- drivers/ide/it821x.c | 2 +- drivers/ide/pdc202xx_new.c | 4 ++-- drivers/ide/pdc202xx_old.c | 4 ++-- drivers/ide/piix.c | 2 +- drivers/ide/serverworks.c | 4 ++-- drivers/ide/setup-pci.c | 2 +- drivers/ide/siimage.c | 2 +- drivers/ide/sis5513.c | 2 +- drivers/ide/sl82c105.c | 4 ++-- drivers/ide/via82cxxx.c | 2 +- 17 files changed, 24 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c index 4485b9c6f0e..878f8ec6dbe 100644 --- a/drivers/ide/aec62xx.c +++ b/drivers/ide/aec62xx.c @@ -139,7 +139,7 @@ static void aec_set_pio_mode(ide_drive_t *drive, const u8 pio) drive->hwif->port_ops->set_dma_mode(drive, pio + XFER_PIO_0); } -static unsigned int init_chipset_aec62xx(struct pci_dev *dev) +static int init_chipset_aec62xx(struct pci_dev *dev) { /* These are necessary to get AEC6280 Macintosh cards to work */ if ((dev->device == PCI_DEVICE_ID_ARTOP_ATP865) || @@ -156,7 +156,7 @@ static unsigned int init_chipset_aec62xx(struct pci_dev *dev) pci_write_config_byte(dev, 0x4a, reg4ah | 0x80); } - return dev->irq; + return 0; } static u8 atp86x_cable_detect(ide_hwif_t *hwif) diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index 66f43083408..d3513b6b853 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -212,7 +212,7 @@ static int ali15x3_dma_setup(ide_drive_t *drive) * appropriate also sets up the 1533 southbridge. */ -static unsigned int init_chipset_ali15x3(struct pci_dev *dev) +static int init_chipset_ali15x3(struct pci_dev *dev) { unsigned long flags; u8 tmpbyte; diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 0b51921e63e..628cd2e5fed 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -140,7 +140,7 @@ static void amd7411_cable_detect(struct pci_dev *dev) * The initialization callback. Initialize drive independent registers. */ -static unsigned int init_chipset_amd74xx(struct pci_dev *dev) +static int init_chipset_amd74xx(struct pci_dev *dev) { u8 t = 0, offset = amd_offset(dev); @@ -172,7 +172,7 @@ static unsigned int init_chipset_amd74xx(struct pci_dev *dev) t |= 0xf0; pci_write_config_byte(dev, AMD_IDE_CONFIG + offset, t); - return dev->irq; + return 0; } static u8 amd_cable_detect(ide_hwif_t *hwif) diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index 2f9688d87ec..aeee036b150 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c @@ -333,7 +333,7 @@ static int cmd646_1_dma_end(ide_drive_t *drive) return (dma_stat & 7) != 4; } -static unsigned int init_chipset_cmd64x(struct pci_dev *dev) +static int init_chipset_cmd64x(struct pci_dev *dev) { u8 mrdmode = 0; diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c index d8ede85fe17..8e8b35a8990 100644 --- a/drivers/ide/cs5530.c +++ b/drivers/ide/cs5530.c @@ -135,7 +135,7 @@ static void cs5530_set_dma_mode(ide_drive_t *drive, const u8 mode) * Initialize the cs5530 bridge for reliable IDE DMA operation. */ -static unsigned int init_chipset_cs5530(struct pci_dev *dev) +static int init_chipset_cs5530(struct pci_dev *dev) { struct pci_dev *master_0 = NULL, *cs5530_0 = NULL; diff --git a/drivers/ide/delkin_cb.c b/drivers/ide/delkin_cb.c index 8f1b2d9f051..bacb1194c9c 100644 --- a/drivers/ide/delkin_cb.c +++ b/drivers/ide/delkin_cb.c @@ -46,7 +46,7 @@ static const struct ide_port_ops delkin_cb_port_ops = { .quirkproc = ide_undecoded_slave, }; -static unsigned int delkin_cb_init_chipset(struct pci_dev *dev) +static int delkin_cb_init_chipset(struct pci_dev *dev) { unsigned long base = pci_resource_start(dev, 0); int i; diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index 3eb9b5c63a0..d3b3e824f44 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -995,7 +995,7 @@ static void hpt3xx_disable_fast_irq(struct pci_dev *dev, u8 mcr_addr) pci_write_config_byte(dev, mcr_addr + 1, new_mcr); } -static unsigned int init_chipset_hpt366(struct pci_dev *dev) +static int init_chipset_hpt366(struct pci_dev *dev) { unsigned long io_base = pci_resource_start(dev, 4); struct hpt_info *info = hpt3xx_get_info(&dev->dev); @@ -1237,7 +1237,7 @@ static unsigned int init_chipset_hpt366(struct pci_dev *dev) hpt3xx_disable_fast_irq(dev, 0x50); hpt3xx_disable_fast_irq(dev, 0x54); - return dev->irq; + return 0; } static u8 hpt3xx_cable_detect(ide_hwif_t *hwif) diff --git a/drivers/ide/it821x.c b/drivers/ide/it821x.c index 13b8153112e..6b9fc950b4a 100644 --- a/drivers/ide/it821x.c +++ b/drivers/ide/it821x.c @@ -603,7 +603,7 @@ static void it8212_disable_raid(struct pci_dev *dev) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0x20); } -static unsigned int init_chipset_it821x(struct pci_dev *dev) +static int init_chipset_it821x(struct pci_dev *dev) { u8 conf; static char *mode[2] = { "pass through", "smart" }; diff --git a/drivers/ide/pdc202xx_new.c b/drivers/ide/pdc202xx_new.c index f21290c4b44..b68906c3c17 100644 --- a/drivers/ide/pdc202xx_new.c +++ b/drivers/ide/pdc202xx_new.c @@ -325,7 +325,7 @@ static void apple_kiwi_init(struct pci_dev *pdev) } #endif /* CONFIG_PPC_PMAC */ -static unsigned int init_chipset_pdcnew(struct pci_dev *dev) +static int init_chipset_pdcnew(struct pci_dev *dev) { const char *name = DRV_NAME; unsigned long dma_base = pci_resource_start(dev, 4); @@ -444,7 +444,7 @@ static unsigned int init_chipset_pdcnew(struct pci_dev *dev) #endif out: - return dev->irq; + return 0; } static struct pci_dev * __devinit pdc20270_get_dev2(struct pci_dev *dev) diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c index 97193323aeb..cba66ebce4e 100644 --- a/drivers/ide/pdc202xx_old.c +++ b/drivers/ide/pdc202xx_old.c @@ -264,7 +264,7 @@ static void pdc202xx_dma_timeout(ide_drive_t *drive) ide_dma_timeout(drive); } -static unsigned int init_chipset_pdc202xx(struct pci_dev *dev) +static int init_chipset_pdc202xx(struct pci_dev *dev) { unsigned long dmabase = pci_resource_start(dev, 4); u8 udma_speed_flag = 0, primary_mode = 0, secondary_mode = 0; @@ -290,7 +290,7 @@ static unsigned int init_chipset_pdc202xx(struct pci_dev *dev) printk("%sACTIVE\n", (inb(dmabase | 0x1f) & 1) ? "" : "IN"); } out: - return dev->irq; + return 0; } static void __devinit pdc202ata4_fixup_irq(struct pci_dev *dev, diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index 42c2e3522d7..2aa69993306 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -204,7 +204,7 @@ static void piix_set_dma_mode(ide_drive_t *drive, const u8 speed) * out to be nice and simple. */ -static unsigned int init_chipset_ich(struct pci_dev *dev) +static int init_chipset_ich(struct pci_dev *dev) { u32 extra = 0; diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index 14718e73991..b6554ef9271 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c @@ -175,7 +175,7 @@ static void svwks_set_dma_mode(ide_drive_t *drive, const u8 speed) pci_write_config_byte(dev, 0x54, ultra_enable); } -static unsigned int init_chipset_svwks(struct pci_dev *dev) +static int init_chipset_svwks(struct pci_dev *dev) { unsigned int reg; u8 btr; @@ -270,7 +270,7 @@ static unsigned int init_chipset_svwks(struct pci_dev *dev) pci_write_config_byte(dev, 0x5A, btr); } - return dev->irq; + return 0; } static u8 ata66_svwks_svwks(ide_hwif_t *hwif) diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 79e3244691e..75e3beca86f 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -524,7 +524,7 @@ static int do_ide_setup_pci_device(struct pci_dev *dev, if (noisy) printk(KERN_INFO "%s %s: not 100%% native mode: will " "probe irqs later\n", d->name, pci_name(dev)); - pciirq = ret; + pciirq = 0; } else if (!pciirq && noisy) { printk(KERN_WARNING "%s %s: bad irq (%d): will probe later\n", d->name, pci_name(dev), pciirq); diff --git a/drivers/ide/siimage.c b/drivers/ide/siimage.c index cb2b352b876..1811ae9cd84 100644 --- a/drivers/ide/siimage.c +++ b/drivers/ide/siimage.c @@ -464,7 +464,7 @@ static void sil_sata_pre_reset(ide_drive_t *drive) * to 133 MHz clocking if the system isn't already set up to do it. */ -static unsigned int init_chipset_siimage(struct pci_dev *dev) +static int init_chipset_siimage(struct pci_dev *dev) { struct ide_host *host = pci_get_drvdata(dev); void __iomem *ioaddr = host->host_priv; diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index d2d54aaea13..afca22beaad 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -447,7 +447,7 @@ static int __devinit sis_find_family(struct pci_dev *dev) return chipset_family; } -static unsigned int init_chipset_sis5513(struct pci_dev *dev) +static int init_chipset_sis5513(struct pci_dev *dev) { /* Make general config ops here 1/ tell IDE channels to operate in Compatibility mode only diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index 6297956507c..dba213c51ba 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c @@ -271,7 +271,7 @@ static u8 sl82c105_bridge_revision(struct pci_dev *dev) * channel 0 here at least, but channel 1 has to be enabled by * firmware or arch code. We still set both to 16 bits mode. */ -static unsigned int init_chipset_sl82c105(struct pci_dev *dev) +static int init_chipset_sl82c105(struct pci_dev *dev) { u32 val; @@ -281,7 +281,7 @@ static unsigned int init_chipset_sl82c105(struct pci_dev *dev) val |= CTRL_P0EN | CTRL_P0F16 | CTRL_P1F16; pci_write_config_dword(dev, 0x40, val); - return dev->irq; + return 0; } static const struct ide_port_ops sl82c105_port_ops = { diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index a41eab5cb5d..3ff7231e485 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -267,7 +267,7 @@ static void via_cable_detect(struct via82cxxx_dev *vdev, u32 u) * and initialize its drive independent registers. */ -static unsigned int init_chipset_via82cxxx(struct pci_dev *dev) +static int init_chipset_via82cxxx(struct pci_dev *dev) { struct ide_host *host = pci_get_drvdata(dev); struct via82cxxx_dev *vdev = host->host_priv; -- cgit v1.2.3 From 86ccf37c6acd74cf7e4b7751ee045de19943c5a0 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:53 +0100 Subject: ide: remove pciirq argument from ide_pci_setup_ports() * Set ->irq explicitly in cs5520.c. * Remove irq argument from ide_hw_configure(). * Remove pciirq argument from ide_pci_setup_ports(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/cs5520.c | 3 ++- drivers/ide/setup-pci.c | 13 +++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/cs5520.c b/drivers/ide/cs5520.c index d003bec56ff..58fb90e5b76 100644 --- a/drivers/ide/cs5520.c +++ b/drivers/ide/cs5520.c @@ -133,7 +133,8 @@ static int __devinit cs5520_init_one(struct pci_dev *dev, const struct pci_devic * do all the device setup for us */ - ide_pci_setup_ports(dev, d, 14, &hw[0], &hws[0]); + ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); + hw[0].irq = 14; return ide_host_add(d, hws, NULL); } diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 75e3beca86f..24bc884826f 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -305,7 +305,6 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * * @dev: PCI device holding interface * @d: IDE port info * @port: port number - * @irq: PCI IRQ * @hw: hw_regs_t instance corresponding to this port * * Perform the initial set up for the hardware interface structure. This @@ -316,7 +315,7 @@ static int ide_pci_check_iomem(struct pci_dev *dev, const struct ide_port_info * */ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, - unsigned int port, int irq, hw_regs_t *hw) + unsigned int port, hw_regs_t *hw) { unsigned long ctl = 0, base = 0; @@ -344,7 +343,6 @@ static int ide_hw_configure(struct pci_dev *dev, const struct ide_port_info *d, } memset(hw, 0, sizeof(*hw)); - hw->irq = irq; hw->dev = &dev->dev; hw->chipset = d->chipset ? d->chipset : ide_pci; ide_std_init_ports(hw, base, ctl | 2); @@ -448,7 +446,6 @@ out: * ide_pci_setup_ports - configure ports/devices on PCI IDE * @dev: PCI device * @d: IDE port info - * @pciirq: IRQ line * @hw: hw_regs_t instances corresponding to this PCI IDE device * @hws: hw_regs_t pointers table to update * @@ -462,7 +459,7 @@ out: */ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, - int pciirq, hw_regs_t *hw, hw_regs_t **hws) + hw_regs_t *hw, hw_regs_t **hws) { int channels = (d->host_flags & IDE_HFLAG_SINGLE) ? 1 : 2, port; u8 tmp; @@ -481,7 +478,7 @@ void ide_pci_setup_ports(struct pci_dev *dev, const struct ide_port_info *d, continue; /* port not enabled */ } - if (ide_hw_configure(dev, d, port, pciirq, hw + port)) + if (ide_hw_configure(dev, d, port, hw + port)) continue; *(hws + port) = hw + port; @@ -549,7 +546,7 @@ int ide_pci_init_one(struct pci_dev *dev, const struct ide_port_info *d, if (ret < 0) goto out; - ide_pci_setup_ports(dev, d, 0, &hw[0], &hws[0]); + ide_pci_setup_ports(dev, d, &hw[0], &hws[0]); host = ide_host_alloc(d, hws); if (host == NULL) { @@ -595,7 +592,7 @@ int ide_pci_init_two(struct pci_dev *dev1, struct pci_dev *dev2, if (ret < 0) goto out; - ide_pci_setup_ports(pdev[i], d, 0, &hw[i*2], &hws[i*2]); + ide_pci_setup_ports(pdev[i], d, &hw[i*2], &hws[i*2]); } host = ide_host_alloc(d, hws); -- cgit v1.2.3 From 2f40c9b0b65b5635e2e13dfa068bd56fe7a8ff98 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:54 +0100 Subject: ide: fix kmalloc() failure handling in ide_driveid_update() * Doing kmalloc() in the middle of command execution is not only ugly but leaves drive waiting to send data on kmalloc() failure. Fix it. While at it: * Unify error code paths. * Fixup error message to be more useful and add missing KERN_ERR level. * Rename 'stat' variable to 's'. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index e0cfa2d2acc..a955483d240 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -293,7 +293,12 @@ int ide_driveid_update(ide_drive_t *drive) const struct ide_tp_ops *tp_ops = hwif->tp_ops; u16 *id; unsigned long flags; - u8 stat; + int rc; + u8 uninitialized_var(s); + + id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); + if (id == NULL) + return 0; /* * Re-read drive->id for possible DMA mode @@ -306,25 +311,21 @@ int ide_driveid_update(ide_drive_t *drive) tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) { - SELECT_MASK(drive, 0); - return 0; + rc = 1; + goto out_err; } msleep(50); /* wait for IRQ and ATA_DRQ */ - stat = tp_ops->read_status(hwif); - if (!OK_STAT(stat, ATA_DRQ, BAD_R_STAT)) { - SELECT_MASK(drive, 0); - printk("%s: CHECK for good STATUS\n", drive->name); - return 0; + s = tp_ops->read_status(hwif); + + if (!OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { + rc = 2; + goto out_err; } + local_irq_save(flags); SELECT_MASK(drive, 0); - id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); - if (!id) { - local_irq_restore(flags); - return 0; - } tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); (void)tp_ops->read_status(hwif); /* clear drive IRQ */ local_irq_enable(); @@ -342,6 +343,12 @@ int ide_driveid_update(ide_drive_t *drive) ide_dma_off(drive); return 1; +out_err: + SELECT_MASK(drive, 0); + if (rc == 2) + printk(KERN_ERR "%s: %s: bad status\n", drive->name, __func__); + kfree(id); + return 0; } int ide_config_drive_speed(ide_drive_t *drive, u8 speed) -- cgit v1.2.3 From 62bd0441a60b0499db339b3dc1be039f8ed9fd35 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:55 +0100 Subject: ide: propagate AltStatus workarounds to ide_driveid_update() Propagate AltStatus workarounds from try_to_identify() to ide_driveid_update(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index a955483d240..944cd857c90 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -293,8 +293,8 @@ int ide_driveid_update(ide_drive_t *drive) const struct ide_tp_ops *tp_ops = hwif->tp_ops; u16 *id; unsigned long flags; - int rc; - u8 uninitialized_var(s); + int use_altstatus = 0, rc; + u8 a, uninitialized_var(s); id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); if (id == NULL) @@ -308,9 +308,24 @@ int ide_driveid_update(ide_drive_t *drive) SELECT_MASK(drive, 1); tp_ops->set_irq(hwif, 0); msleep(50); + + if (hwif->io_ports.ctl_addr && + (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) { + a = tp_ops->read_altstatus(hwif); + s = tp_ops->read_status(hwif); + if ((a ^ s) & ~ATA_IDX) + /* ancient Seagate drives, broken interfaces */ + printk(KERN_INFO "%s: probing with STATUS(0x%02x) " + "instead of ALTSTATUS(0x%02x)\n", + drive->name, s, a); + else + /* use non-intrusive polling */ + use_altstatus = 1; + } + tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); - if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 1)) { + if (ide_busy_sleep(hwif, WAIT_WORSTCASE, use_altstatus)) { rc = 1; goto out_err; } -- cgit v1.2.3 From 4cda15a0995f2da5727514f84ec26d8b7420e1f9 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:57 +0100 Subject: ide: shorten timeout value in ide_driveid_update() Shorten timeout value in ide_driveid_update() (30s -> 15s) to match try_to_identify(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 944cd857c90..59c02184ba8 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -325,7 +325,7 @@ int ide_driveid_update(ide_drive_t *drive) tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); - if (ide_busy_sleep(hwif, WAIT_WORSTCASE, use_altstatus)) { + if (ide_busy_sleep(hwif, WAIT_WORSTCASE / 2, use_altstatus)) { rc = 1; goto out_err; } -- cgit v1.2.3 From 552d3a99bdce8a0d7f9abe3766fb3655ef5757dc Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:58 +0100 Subject: ide: remove broken EXABYTENEST support do_identify() marks EXABYTENEST device as non-present and frees drive->id so enable_nest() has absolutely no chance of working. The code was like this since at least 2.6.12-rc2 and nobody has noticed so just remove broken EXABYTENEST support. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 37 ------------------------------------- 1 file changed, 37 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 5e0c3fb3b43..29649d09dbb 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -465,37 +465,6 @@ static int do_probe (ide_drive_t *drive, u8 cmd) return rc; } -/* - * - */ -static void enable_nest (ide_drive_t *drive) -{ - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; - u8 stat; - - printk(KERN_INFO "%s: enabling %s -- ", - hwif->name, (char *)&drive->id[ATA_ID_PROD]); - - SELECT_DRIVE(drive); - msleep(50); - tp_ops->exec_command(hwif, ATA_EXABYTE_ENABLE_NEST); - - if (ide_busy_sleep(hwif, WAIT_WORSTCASE, 0)) { - printk(KERN_CONT "failed (timeout)\n"); - return; - } - - msleep(50); - - stat = tp_ops->read_status(hwif); - - if (!OK_STAT(stat, 0, BAD_STAT)) - printk(KERN_CONT "failed (status = 0x%02x)\n", stat); - else - printk(KERN_CONT "success\n"); -} - /** * probe_for_drives - upper level drive probe * @drive: drive to probe for @@ -534,7 +503,6 @@ static u8 probe_for_drive(ide_drive_t *drive) /* skip probing? */ if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) { -retry: /* if !(success||timed-out) */ if (do_probe(drive, ATA_CMD_ID_ATA) >= 2) /* look for ATAPI device */ @@ -544,11 +512,6 @@ retry: /* drive not found */ return 0; - if (strstr(m, "E X A B Y T E N E S T")) { - enable_nest(drive); - goto retry; - } - /* identification failed? */ if ((drive->dev_flags & IDE_DFLAG_ID_READ) == 0) { if (drive->media == ide_disk) { -- cgit v1.2.3 From 1bd4c1f4fe6607a0253d1318847b618a2a598612 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:58 +0100 Subject: ide: classify device type in do_probe() Defer classifying device type from do_identify() to do_probe(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-probe.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 29649d09dbb..3f9faef5e50 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -233,16 +233,6 @@ static void do_identify(ide_drive_t *drive, u8 cmd) drive->dev_flags |= IDE_DFLAG_PRESENT; drive->dev_flags &= ~IDE_DFLAG_DEAD; - /* - * Check for an ATAPI device - */ - if (cmd == ATA_CMD_ID_ATAPI) - ide_classify_atapi_dev(drive); - else - /* - * Not an ATAPI device: looks like a "regular" hard disk - */ - ide_classify_ata_dev(drive); return; err_misc: kfree(id); @@ -480,6 +470,8 @@ static int do_probe (ide_drive_t *drive, u8 cmd) static u8 probe_for_drive(ide_drive_t *drive) { char *m; + int rc; + u8 cmd; /* * In order to keep things simple we have an id @@ -504,9 +496,13 @@ static u8 probe_for_drive(ide_drive_t *drive) /* skip probing? */ if ((drive->dev_flags & IDE_DFLAG_NOPROBE) == 0) { /* if !(success||timed-out) */ - if (do_probe(drive, ATA_CMD_ID_ATA) >= 2) + cmd = ATA_CMD_ID_ATA; + rc = do_probe(drive, cmd); + if (rc >= 2) { /* look for ATAPI device */ - (void)do_probe(drive, ATA_CMD_ID_ATAPI); + cmd = ATA_CMD_ID_ATAPI; + rc = do_probe(drive, cmd); + } if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) /* drive not found */ @@ -525,8 +521,12 @@ static u8 probe_for_drive(ide_drive_t *drive) printk(KERN_WARNING "%s: Unknown device on bus refused identification. Ignoring.\n", drive->name); drive->dev_flags &= ~IDE_DFLAG_PRESENT; } + } else { + if (cmd == ATA_CMD_ID_ATAPI) + ide_classify_atapi_dev(drive); + else + ide_classify_ata_dev(drive); } - /* drive was found */ } if ((drive->dev_flags & IDE_DFLAG_PRESENT) == 0) -- cgit v1.2.3 From f323b80dceaca858f8e240ca098681fcfe7fd3c4 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:58 +0100 Subject: ide: sanitize SELECT_MASK() usage in ide_driveid_update() Call SELECT_MASK() after ide_fix_driveid(). Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index 59c02184ba8..f92c63f564d 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -340,13 +340,15 @@ int ide_driveid_update(ide_drive_t *drive) } local_irq_save(flags); - SELECT_MASK(drive, 0); tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); (void)tp_ops->read_status(hwif); /* clear drive IRQ */ local_irq_enable(); local_irq_restore(flags); + ide_fix_driveid(id); + SELECT_MASK(drive, 0); + drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES]; drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES]; drive->id[ATA_ID_SWDMA_MODES] = id[ATA_ID_SWDMA_MODES]; -- cgit v1.2.3 From ff18b89bef76d291db594af3e27b6c91e6600b57 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:58 +0100 Subject: ide: clear drive IRQ after re-enabling local IRQs in ide_driveid_update() Clear drive IRQ after re-enabling local IRQs in ide_driveid_update() to match try_to_identify(). Also remove superfluous local_irq_enable() call while at it. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index f92c63f564d..affbc603987 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -341,10 +341,10 @@ int ide_driveid_update(ide_drive_t *drive) local_irq_save(flags); tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); - (void)tp_ops->read_status(hwif); /* clear drive IRQ */ - local_irq_enable(); local_irq_restore(flags); + (void)tp_ops->read_status(hwif); /* clear drive IRQ */ + ide_fix_driveid(id); SELECT_MASK(drive, 0); -- cgit v1.2.3 From 2ebe1d9efed5f232afc8d00901d0959c9814bce3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Tue, 24 Mar 2009 23:22:59 +0100 Subject: ide: use try_to_identify() in ide_driveid_update() * Pass pointer to buffer for IDENTIFY data to do_identify() and try_to_identify(). * Un-static try_to_identify() and use it in ide_driveid_update(). * Rename try_to_identify() to ide_dev_read_id(). There should be no functional changes caused by this patch. Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-iops.c | 54 ++++--------------------------------------------- drivers/ide/ide-probe.c | 24 +++++++++++----------- 2 files changed, 16 insertions(+), 62 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-iops.c b/drivers/ide/ide-iops.c index affbc603987..317c5dadd7c 100644 --- a/drivers/ide/ide-iops.c +++ b/drivers/ide/ide-iops.c @@ -289,65 +289,19 @@ no_80w: int ide_driveid_update(ide_drive_t *drive) { - ide_hwif_t *hwif = drive->hwif; - const struct ide_tp_ops *tp_ops = hwif->tp_ops; u16 *id; - unsigned long flags; - int use_altstatus = 0, rc; - u8 a, uninitialized_var(s); + int rc; id = kmalloc(SECTOR_SIZE, GFP_ATOMIC); if (id == NULL) return 0; - /* - * Re-read drive->id for possible DMA mode - * change (copied from ide-probe.c) - */ - SELECT_MASK(drive, 1); - tp_ops->set_irq(hwif, 0); - msleep(50); - - if (hwif->io_ports.ctl_addr && - (hwif->host_flags & IDE_HFLAG_BROKEN_ALTSTATUS) == 0) { - a = tp_ops->read_altstatus(hwif); - s = tp_ops->read_status(hwif); - if ((a ^ s) & ~ATA_IDX) - /* ancient Seagate drives, broken interfaces */ - printk(KERN_INFO "%s: probing with STATUS(0x%02x) " - "instead of ALTSTATUS(0x%02x)\n", - drive->name, s, a); - else - /* use non-intrusive polling */ - use_altstatus = 1; - } - - tp_ops->exec_command(hwif, ATA_CMD_ID_ATA); - - if (ide_busy_sleep(hwif, WAIT_WORSTCASE / 2, use_altstatus)) { - rc = 1; - goto out_err; - } - - msleep(50); /* wait for IRQ and ATA_DRQ */ - - s = tp_ops->read_status(hwif); + rc = ide_dev_read_id(drive, ATA_CMD_ID_ATA, id); + SELECT_MASK(drive, 0); - if (!OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { - rc = 2; + if (rc) goto out_err; - } - - local_irq_save(flags); - tp_ops->input_data(drive, NULL, id, SECTOR_SIZE); - local_irq_restore(flags); - - (void)tp_ops->read_status(hwif); /* clear drive IRQ */ - - ide_fix_driveid(id); - - SELECT_MASK(drive, 0); drive->id[ATA_ID_UDMA_MODES] = id[ATA_ID_UDMA_MODES]; drive->id[ATA_ID_MWDMA_MODES] = id[ATA_ID_MWDMA_MODES]; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 3f9faef5e50..974067043fb 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -181,16 +181,16 @@ static void ide_classify_atapi_dev(ide_drive_t *drive) * do_identify - identify a drive * @drive: drive to identify * @cmd: command used + * @id: buffer for IDENTIFY data * * Called when we have issued a drive identify command to * read and parse the results. This function is run with * interrupts disabled. */ -static void do_identify(ide_drive_t *drive, u8 cmd) +static void do_identify(ide_drive_t *drive, u8 cmd, u16 *id) { ide_hwif_t *hwif = drive->hwif; - u16 *id = drive->id; char *m = (char *)&id[ATA_ID_PROD]; unsigned long flags; int bswap = 1; @@ -240,19 +240,19 @@ err_misc: } /** - * try_to_identify - send ATA/ATAPI identify + * ide_dev_read_id - send ATA/ATAPI IDENTIFY command * @drive: drive to identify * @cmd: command to use + * @id: buffer for IDENTIFY data * - * try_to_identify() sends an ATA(PI) IDENTIFY request to a drive - * and waits for a response. + * Sends an ATA(PI) IDENTIFY request to a drive and waits for a response. * * Returns: 0 device was identified * 1 device timed-out (no response to identify request) * 2 device aborted the command (refused to identify itself) */ -static int try_to_identify(ide_drive_t *drive, u8 cmd) +int ide_dev_read_id(ide_drive_t *drive, u8 cmd, u16 *id) { ide_hwif_t *hwif = drive->hwif; struct ide_io_ports *io_ports = &hwif->io_ports; @@ -312,7 +312,7 @@ static int try_to_identify(ide_drive_t *drive, u8 cmd) if (OK_STAT(s, ATA_DRQ, BAD_R_STAT)) { /* drive returned ID */ - do_identify(drive, cmd); + do_identify(drive, cmd, id); /* drive responded with ID */ rc = 0; /* clear drive IRQ */ @@ -378,6 +378,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) { ide_hwif_t *hwif = drive->hwif; const struct ide_tp_ops *tp_ops = hwif->tp_ops; + u16 *id = drive->id; int rc; u8 present = !!(drive->dev_flags & IDE_DFLAG_PRESENT), stat; @@ -413,11 +414,10 @@ static int do_probe (ide_drive_t *drive, u8 cmd) if (OK_STAT(stat, ATA_DRDY, ATA_BUSY) || present || cmd == ATA_CMD_ID_ATAPI) { - /* send cmd and wait */ - if ((rc = try_to_identify(drive, cmd))) { + rc = ide_dev_read_id(drive, cmd, id); + if (rc) /* failed: try again */ - rc = try_to_identify(drive,cmd); - } + rc = ide_dev_read_id(drive, cmd, id); stat = tp_ops->read_status(hwif); @@ -432,7 +432,7 @@ static int do_probe (ide_drive_t *drive, u8 cmd) msleep(50); tp_ops->exec_command(hwif, ATA_CMD_DEV_RESET); (void)ide_busy_sleep(hwif, WAIT_WORSTCASE, 0); - rc = try_to_identify(drive, cmd); + rc = ide_dev_read_id(drive, cmd, id); } /* ensure drive IRQ is clear */ -- cgit v1.2.3 From 1662e3a7f076e51e3073faf9ce77157b529c475b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 18 Mar 2009 14:28:53 -0400 Subject: USB: add quirk to avoid config and interface strings Apparently the Configuration and Interface strings aren't used as often as the Vendor, Product, and Serial strings. In at least one device (a Saitek Cyborg Gold 3D joystick), attempts to read the Configuration string cause the device to stop responding to Control requests. This patch (as1226) adds a quirks flag, telling the kernel not to read a device's Configuration or Interface strings, together with a new quirk for the offending joystick. Reported-by: Melchior FRANZ Tested-by: Melchior FRANZ Signed-off-by: Alan Stern Cc: stable [2.6.28 and 2.6.29, nothing earlier] Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 3 ++- drivers/usb/core/quirks.c | 4 ++++ drivers/usb/core/sysfs.c | 4 +++- 3 files changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 49e7f56e0d7..3922fa915ed 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -1719,7 +1719,8 @@ free_interfaces: } kfree(new_interfaces); - if (cp->string == NULL) + if (cp->string == NULL && + !(dev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) cp->string = usb_cache_string(dev, cp->desc.iConfiguration); /* Now that all the interfaces are set up, register them diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index c070b34b669..ab93918d920 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -54,6 +54,10 @@ static const struct usb_device_id usb_quirk_list[] = { { USB_DEVICE(0x0638, 0x0a13), .driver_info = USB_QUIRK_STRING_FETCH_255 }, + /* Saitek Cyborg Gold Joystick */ + { USB_DEVICE(0x06a3, 0x0006), .driver_info = + USB_QUIRK_CONFIG_INTF_STRINGS }, + /* M-Systems Flash Disk Pioneers */ { USB_DEVICE(0x08ec, 0x1000), .driver_info = USB_QUIRK_RESET_RESUME }, diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index 4cc2456ef3b..c6678919792 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -13,6 +13,7 @@ #include #include #include +#include #include "usb.h" /* Active configuration fields */ @@ -813,7 +814,8 @@ int usb_create_sysfs_intf_files(struct usb_interface *intf) if (intf->sysfs_files_created || intf->unregistering) return 0; - if (alt->string == NULL) + if (alt->string == NULL && + !(udev->quirks & USB_QUIRK_CONFIG_INTF_STRINGS)) alt->string = usb_cache_string(udev, alt->desc.iInterface); if (alt->string) retval = device_create_file(&intf->dev, &dev_attr_interface); -- cgit v1.2.3 From 090b90118207e786d2990310d063fda5d52cce6e Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 20 Mar 2009 01:08:20 -0700 Subject: USB: gadget: fix rndis regression Restore some code that was wrongly dropped from the RNDIS driver, and caused interop problems observed with OpenMoko. The issue is with hardware which needs help conforming to part of the USB 2.0 spec (section 8.5.3.2); some can automagically send a ZLP in response to an unexpected IN, but not all chips will do that. We don't need to check the packet length ourselves the way earlier code did, since the UDC must already check it. But we do need to tell the UDC when it must force a short packet termination of the data stage. (Based on a patch from Aric D. Blumer ) Signed-off-by: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_rndis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 3a8bb53fc47..fd7b356f902 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -437,7 +437,7 @@ invalid: DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n", ctrl->bRequestType, ctrl->bRequest, w_value, w_index, w_length); - req->zero = 0; + req->zero = (value < w_length); req->length = value; value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); if (value < 0) -- cgit v1.2.3 From 5c16034d73da2c1b663aa25dedadbc533b3d811c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 23 Mar 2009 09:51:02 -0400 Subject: USB: usb-storage: increase max_sectors for tape drives This patch (as1203) increases the max_sector limit for USB tape drives. By default usb-storage sets max_sectors to 240 (i.e., 120 KB) for all devices. But tape drives need a higher limit, since tapes can and do have very large block sizes. Without the ability to transfer an entire large block in a single command, such tapes can't be used. This fixes Bugzilla #12207. Signed-off-by: Alan Stern Reported-and-tested-by: Phil Mitchell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/scsiglue.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 727c506417c..ed710bcdaab 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -135,6 +135,12 @@ static int slave_configure(struct scsi_device *sdev) if (sdev->request_queue->max_sectors > max_sectors) blk_queue_max_sectors(sdev->request_queue, max_sectors); + } else if (sdev->type == TYPE_TAPE) { + /* Tapes need much higher max_sector limits, so just + * raise it to the maximum possible (4 GB / 512) and + * let the queue segment size sort out the real limit. + */ + blk_queue_max_sectors(sdev->request_queue, 0x7FFFFF); } /* Some USB host controllers can't do DMA; they have to use PIO. -- cgit v1.2.3 From dd44be6b17ac52238aa6c7f46b906d9fb76e7052 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Tue, 6 Jan 2009 17:20:42 -0700 Subject: usblp: continuously poll for status MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The usblp in 2.6.18 polled for status regardless if we actually needed it. At some point I dropped it, to save the batteries if nothing else. As it turned out, printers exist (e.g. Canon BJC-3000) that need prodding this way or else they stop. This patch restores the old behaviour. If you want to save battery, don't leave jobs in the print queue. I tested this on my printers by printing and examining usbmon traces to make sure status is being requested and printers continue to print. Tuomas Jäntti verified the fix on BJC-3000. Signed-off-by: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/usblp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/class/usblp.c b/drivers/usb/class/usblp.c index 3f3ee135193..d2747a49b97 100644 --- a/drivers/usb/class/usblp.c +++ b/drivers/usb/class/usblp.c @@ -880,16 +880,19 @@ static int usblp_wwait(struct usblp *usblp, int nonblock) if (rc <= 0) break; - if (usblp->flags & LP_ABORT) { - if (schedule_timeout(msecs_to_jiffies(5000)) == 0) { + if (schedule_timeout(msecs_to_jiffies(1500)) == 0) { + if (usblp->flags & LP_ABORT) { err = usblp_check_status(usblp, err); if (err == 1) { /* Paper out */ rc = -ENOSPC; break; } + } else { + /* Prod the printer, Gentoo#251237. */ + mutex_lock(&usblp->mut); + usblp_read_status(usblp, usblp->statusbuf); + mutex_unlock(&usblp->mut); } - } else { - schedule(); } } set_current_state(TASK_RUNNING); -- cgit v1.2.3 From c2344f13b59e007d782a3e591ebc551bc583a8b7 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:54:31 -0800 Subject: USB: gpio_vbus: add delayed vbus_session calls Call usb_gadget_vbus_connect() and ...disconnect() from a workqueue rather than from an irq handler, allowing msleep() calls in vbus_session. Update kerneldoc to match. [ dbrownell@users.sourceforge.net: more kerneldoc updates ] Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/gpio_vbus.c | 42 +++++++++++++++++++++++++++++++----------- 1 file changed, 31 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/otg/gpio_vbus.c b/drivers/usb/otg/gpio_vbus.c index 63a6036f04b..1c26c94513e 100644 --- a/drivers/usb/otg/gpio_vbus.c +++ b/drivers/usb/otg/gpio_vbus.c @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -34,6 +35,7 @@ struct gpio_vbus_data { struct regulator *vbus_draw; int vbus_draw_enabled; unsigned mA; + struct work_struct work; }; @@ -76,24 +78,26 @@ static void set_vbus_draw(struct gpio_vbus_data *gpio_vbus, unsigned mA) gpio_vbus->mA = mA; } -/* VBUS change IRQ handler */ -static irqreturn_t gpio_vbus_irq(int irq, void *data) +static int is_vbus_powered(struct gpio_vbus_mach_info *pdata) { - struct platform_device *pdev = data; - struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; - struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); - int gpio, vbus; + int vbus; vbus = gpio_get_value(pdata->gpio_vbus); if (pdata->gpio_vbus_inverted) vbus = !vbus; - dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", - vbus ? "supplied" : "inactive", - gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); + return vbus; +} + +static void gpio_vbus_work(struct work_struct *work) +{ + struct gpio_vbus_data *gpio_vbus = + container_of(work, struct gpio_vbus_data, work); + struct gpio_vbus_mach_info *pdata = gpio_vbus->dev->platform_data; + int gpio; if (!gpio_vbus->otg.gadget) - return IRQ_HANDLED; + return; /* Peripheral controllers which manage the pullup themselves won't have * gpio_pullup configured here. If it's configured here, we'll do what @@ -101,7 +105,7 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) * that may complicate usb_gadget_{,dis}connect() support. */ gpio = pdata->gpio_pullup; - if (vbus) { + if (is_vbus_powered(pdata)) { gpio_vbus->otg.state = OTG_STATE_B_PERIPHERAL; usb_gadget_vbus_connect(gpio_vbus->otg.gadget); @@ -121,6 +125,21 @@ static irqreturn_t gpio_vbus_irq(int irq, void *data) usb_gadget_vbus_disconnect(gpio_vbus->otg.gadget); gpio_vbus->otg.state = OTG_STATE_B_IDLE; } +} + +/* VBUS change IRQ handler */ +static irqreturn_t gpio_vbus_irq(int irq, void *data) +{ + struct platform_device *pdev = data; + struct gpio_vbus_mach_info *pdata = pdev->dev.platform_data; + struct gpio_vbus_data *gpio_vbus = platform_get_drvdata(pdev); + + dev_dbg(&pdev->dev, "VBUS %s (gadget: %s)\n", + is_vbus_powered(pdata) ? "supplied" : "inactive", + gpio_vbus->otg.gadget ? gpio_vbus->otg.gadget->name : "none"); + + if (gpio_vbus->otg.gadget) + schedule_work(&gpio_vbus->work); return IRQ_HANDLED; } @@ -257,6 +276,7 @@ static int __init gpio_vbus_probe(struct platform_device *pdev) irq, err); goto err_irq; } + INIT_WORK(&gpio_vbus->work, gpio_vbus_work); /* only active when a gadget is registered */ err = otg_set_transceiver(&gpio_vbus->otg); -- cgit v1.2.3 From eb50702539f9be3765127d927d3e9ccfeb65f26e Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:55:34 -0800 Subject: USB: pxa27x_udc: factor pullup code to prepare otg transceiver Prepare pxa27x_udc to handle usb D+ pullup properly : it should connect the pullup resistor and disconnect it only if no external transceiver is handling it. [ dbrownell@users.sourceforge.net: kerneldoc and gpio fixes ] Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 140 +++++++++++++++++++++++++++++++++++++--- drivers/usb/gadget/pxa27x_udc.h | 6 ++ 2 files changed, 138 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 990f40f988d..f8145590944 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -1471,6 +1472,32 @@ static struct usb_ep_ops pxa_ep_ops = { .fifo_flush = pxa_ep_fifo_flush, }; +/** + * dplus_pullup - Connect or disconnect pullup resistor to D+ pin + * @udc: udc device + * @on: 0 if disconnect pullup resistor, 1 otherwise + * Context: any + * + * Handle D+ pullup resistor, make the device visible to the usb bus, and + * declare it as a full speed usb device + */ +static void dplus_pullup(struct pxa_udc *udc, int on) +{ + if (on) { + if (gpio_is_valid(udc->mach->gpio_pullup)) + gpio_set_value(udc->mach->gpio_pullup, + !udc->mach->gpio_pullup_inverted); + if (udc->mach->udc_command) + udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); + } else { + if (gpio_is_valid(udc->mach->gpio_pullup)) + gpio_set_value(udc->mach->gpio_pullup, + udc->mach->gpio_pullup_inverted); + if (udc->mach->udc_command) + udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); + } + udc->pullup_on = on; +} /** * pxa_udc_get_frame - Returns usb frame number @@ -1500,21 +1527,91 @@ static int pxa_udc_wakeup(struct usb_gadget *_gadget) return 0; } +static void udc_enable(struct pxa_udc *udc); +static void udc_disable(struct pxa_udc *udc); + +/** + * should_enable_udc - Tells if UDC should be enabled + * @udc: udc device + * Context: any + * + * The UDC should be enabled if : + * - the pullup resistor is connected + * - and a gadget driver is bound + * + * Returns 1 if UDC should be enabled, 0 otherwise + */ +static int should_enable_udc(struct pxa_udc *udc) +{ + int put_on; + + put_on = ((udc->pullup_on) && (udc->driver)); + return put_on; +} + +/** + * should_disable_udc - Tells if UDC should be disabled + * @udc: udc device + * Context: any + * + * The UDC should be disabled if : + * - the pullup resistor is not connected + * - or no gadget driver is bound + * + * Returns 1 if UDC should be disabled + */ +static int should_disable_udc(struct pxa_udc *udc) +{ + int put_off; + + put_off = ((!udc->pullup_on) || (!udc->driver)); + return put_off; +} + +/** + * pxa_udc_pullup - Offer manual D+ pullup control + * @_gadget: usb gadget using the control + * @is_active: 0 if disconnect, else connect D+ pullup resistor + * Context: !in_interrupt() + * + * Returns 0 if OK, -EOPNOTSUPP if udc driver doesn't handle D+ pullup + */ +static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active) +{ + struct pxa_udc *udc = to_gadget_udc(_gadget); + + if (!gpio_is_valid(udc->mach->gpio_pullup) && !udc->mach->udc_command) + return -EOPNOTSUPP; + + dplus_pullup(udc, is_active); + + if (should_enable_udc(udc)) + udc_enable(udc); + if (should_disable_udc(udc)) + udc_disable(udc); + return 0; +} + static const struct usb_gadget_ops pxa_udc_ops = { .get_frame = pxa_udc_get_frame, .wakeup = pxa_udc_wakeup, + .pullup = pxa_udc_pullup, /* current versions must always be self-powered */ }; /** * udc_disable - disable udc device controller * @udc: udc device + * Context: any * * Disables the udc device : disables clocks, udc interrupts, control endpoint * interrupts. */ static void udc_disable(struct pxa_udc *udc) { + if (!udc->enabled) + return; + udc_writel(udc, UDCICR0, 0); udc_writel(udc, UDCICR1, 0); @@ -1523,8 +1620,8 @@ static void udc_disable(struct pxa_udc *udc) ep0_idle(udc); udc->gadget.speed = USB_SPEED_UNKNOWN; - if (udc->mach->udc_command) - udc->mach->udc_command(PXA2XX_UDC_CMD_DISCONNECT); + + udc->enabled = 0; } /** @@ -1570,6 +1667,9 @@ static __init void udc_init_data(struct pxa_udc *dev) */ static void udc_enable(struct pxa_udc *udc) { + if (udc->enabled) + return; + udc_writel(udc, UDCICR0, 0); udc_writel(udc, UDCICR1, 0); udc_clear_mask_UDCCR(udc, UDCCR_UDE); @@ -1598,9 +1698,7 @@ static void udc_enable(struct pxa_udc *udc) /* enable ep0 irqs */ pio_irq_enable(&udc->pxa_ep[0]); - dev_info(udc->dev, "UDC connecting\n"); - if (udc->mach->udc_command) - udc->mach->udc_command(PXA2XX_UDC_CMD_CONNECT); + udc->enabled = 1; } /** @@ -1612,6 +1710,9 @@ static void udc_enable(struct pxa_udc *udc) * usb traffic follows until a disconnect is reported. Then a host may connect * again, or the driver might get unbound. * + * Note that the udc is not automatically enabled. Check function + * should_enable_udc(). + * * Returns 0 if no error, -EINVAL, -ENODEV, -EBUSY otherwise */ int usb_gadget_register_driver(struct usb_gadget_driver *driver) @@ -1630,6 +1731,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) /* first hook up the driver ... */ udc->driver = driver; udc->gadget.dev.driver = &driver->driver; + dplus_pullup(udc, 1); retval = device_add(&udc->gadget.dev); if (retval) { @@ -1645,7 +1747,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dev_dbg(udc->dev, "registered gadget driver '%s'\n", driver->driver.name); - udc_enable(udc); + if (should_enable_udc(udc)) + udc_enable(udc); return 0; bind_fail: @@ -1699,6 +1802,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) stop_activity(udc, driver); udc_disable(udc); + dplus_pullup(udc, 0); driver->unbind(&udc->gadget); udc->driver = NULL; @@ -2212,7 +2316,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) { struct resource *regs; struct pxa_udc *udc = &memory; - int retval; + int retval = 0, gpio; regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!regs) @@ -2224,6 +2328,19 @@ static int __init pxa_udc_probe(struct platform_device *pdev) udc->dev = &pdev->dev; udc->mach = pdev->dev.platform_data; + gpio = udc->mach->gpio_pullup; + if (gpio_is_valid(gpio)) { + retval = gpio_request(gpio, "USB D+ pullup"); + if (retval == 0) + gpio_direction_output(gpio, + udc->mach->gpio_pullup_inverted); + } + if (retval) { + dev_err(&pdev->dev, "Couldn't request gpio %d : %d\n", + gpio, retval); + return retval; + } + udc->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(udc->clk)) { retval = PTR_ERR(udc->clk); @@ -2273,10 +2390,13 @@ err_clk: static int __exit pxa_udc_remove(struct platform_device *_dev) { struct pxa_udc *udc = platform_get_drvdata(_dev); + int gpio = udc->mach->gpio_pullup; usb_gadget_unregister_driver(udc->driver); free_irq(udc->irq, udc); pxa_cleanup_debugfs(udc); + if (gpio_is_valid(gpio)) + gpio_free(gpio); platform_set_drvdata(_dev, NULL); the_controller = NULL; @@ -2319,6 +2439,8 @@ static int pxa_udc_suspend(struct platform_device *_dev, pm_message_t state) } udc_disable(udc); + udc->pullup_resume = udc->pullup_on; + dplus_pullup(udc, 0); return 0; } @@ -2346,7 +2468,9 @@ static int pxa_udc_resume(struct platform_device *_dev) ep->udccsr_value, ep->udccr_value); } - udc_enable(udc); + dplus_pullup(udc, udc->pullup_resume); + if (should_enable_udc(udc)) + udc_enable(udc); /* * We do not handle OTG yet. * diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 1d1b7936ee1..6f5234dff8a 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -425,6 +425,9 @@ struct udc_stats { * @stats: statistics on udc usage * @udc_usb_ep: array of usb endpoints offered by the gadget * @pxa_ep: array of pxa available endpoints + * @enabled: UDC was enabled by a previous udc_enable() + * @pullup_on: if pullup resistor connected to D+ pin + * @pullup_resume: if pullup resistor should be connected to D+ pin on resume * @config: UDC active configuration * @last_interface: UDC interface of the last SET_INTERFACE host request * @last_alternate: UDC altsetting of the last SET_INTERFACE host request @@ -450,6 +453,9 @@ struct pxa_udc { struct udc_usb_ep udc_usb_ep[NR_USB_ENDPOINTS]; struct pxa_ep pxa_ep[NR_PXA_ENDPOINTS]; + unsigned enabled:1; + unsigned pullup_on:1; + unsigned pullup_resume:1; unsigned config:2; unsigned last_interface:3; unsigned last_alternate:3; -- cgit v1.2.3 From b799a7eb68082af620b7e37b6f41c98802e831f6 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:56:42 -0800 Subject: USB: pxa27x_udc: add vbus session handling On vbus_session() call, optionally activate D+ pullup resistor and enable the udc, or deactivate D+ pullup resistor and disable the udc. It is intentional to not handle any VBus sense related irq. An external transceiver driver (like gpio_vbus) should catch VBus sense signal, and call usb_gadget_vbus_connect() or usb_gadget_vbus_disconnect(). Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 33 +++++++++++++++++++++++++++++++++ drivers/usb/gadget/pxa27x_udc.h | 1 + 2 files changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index f8145590944..0c9307118b5 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1536,8 +1536,10 @@ static void udc_disable(struct pxa_udc *udc); * Context: any * * The UDC should be enabled if : + * - the pullup resistor is connected * - and a gadget driver is bound + * - and vbus is sensed (or no vbus sense is available) * * Returns 1 if UDC should be enabled, 0 otherwise */ @@ -1546,6 +1548,7 @@ static int should_enable_udc(struct pxa_udc *udc) int put_on; put_on = ((udc->pullup_on) && (udc->driver)); + put_on &= ((udc->vbus_sensed) || (!udc->transceiver)); return put_on; } @@ -1557,6 +1560,7 @@ static int should_enable_udc(struct pxa_udc *udc) * The UDC should be disabled if : * - the pullup resistor is not connected * - or no gadget driver is bound + * - or no vbus is sensed (when vbus sesing is available) * * Returns 1 if UDC should be disabled */ @@ -1565,6 +1569,7 @@ static int should_disable_udc(struct pxa_udc *udc) int put_off; put_off = ((!udc->pullup_on) || (!udc->driver)); + put_off |= ((!udc->vbus_sensed) && (udc->transceiver)); return put_off; } @@ -1592,10 +1597,37 @@ static int pxa_udc_pullup(struct usb_gadget *_gadget, int is_active) return 0; } +static void udc_enable(struct pxa_udc *udc); +static void udc_disable(struct pxa_udc *udc); + +/** + * pxa_udc_vbus_session - Called by external transceiver to enable/disable udc + * @_gadget: usb gadget + * @is_active: 0 if should disable the udc, 1 if should enable + * + * Enables the udc, and optionnaly activates D+ pullup resistor. Or disables the + * udc, and deactivates D+ pullup resistor. + * + * Returns 0 + */ +static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active) +{ + struct pxa_udc *udc = to_gadget_udc(_gadget); + + udc->vbus_sensed = is_active; + if (should_enable_udc(udc)) + udc_enable(udc); + if (should_disable_udc(udc)) + udc_disable(udc); + + return 0; +} + static const struct usb_gadget_ops pxa_udc_ops = { .get_frame = pxa_udc_get_frame, .wakeup = pxa_udc_wakeup, .pullup = pxa_udc_pullup, + .vbus_session = pxa_udc_vbus_session, /* current versions must always be self-powered */ }; @@ -2357,6 +2389,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) device_initialize(&udc->gadget.dev); udc->gadget.dev.parent = &pdev->dev; udc->gadget.dev.dma_mask = NULL; + udc->vbus_sensed = 0; the_controller = udc; platform_set_drvdata(pdev, udc); diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 6f5234dff8a..64741e19920 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -456,6 +456,7 @@ struct pxa_udc { unsigned enabled:1; unsigned pullup_on:1; unsigned pullup_resume:1; + unsigned vbus_sensed:1; unsigned config:2; unsigned last_interface:3; unsigned last_alternate:3; -- cgit v1.2.3 From 7fec3c25b773883bd50c4078bcccdd23d3dadeac Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:57:30 -0800 Subject: USB: pxa27x_udc: add otg transceiver support When a transceiver driver is used, no automatic udc enable is done. The transceiver (OTG or not) should : - take care of VBus sensing - call usb_gadget_vbus_connect() - call usb_gadget_vbus_disconnect() The pullup should remain within this driver's management, either by gpio_pullup of udc_command() fields. Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/Kconfig | 1 + drivers/usb/gadget/pxa27x_udc.c | 19 ++++++++++++++++++- drivers/usb/gadget/pxa27x_udc.h | 3 +++ 3 files changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index e55fef52a5d..770b3eaa918 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig @@ -254,6 +254,7 @@ config USB_PXA25X_SMALL config USB_GADGET_PXA27X boolean "PXA 27x" depends on ARCH_PXA && PXA27x + select USB_OTG_UTILS help Intel's PXA 27x series XScale ARM v5TE processors include an integrated full speed USB 1.1 device controller. diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 0c9307118b5..11510472ee0 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1779,10 +1779,21 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) dev_dbg(udc->dev, "registered gadget driver '%s'\n", driver->driver.name); + if (udc->transceiver) { + retval = otg_set_peripheral(udc->transceiver, &udc->gadget); + if (retval) { + dev_err(udc->dev, "can't bind to transceiver\n"); + goto transceiver_fail; + } + } + if (should_enable_udc(udc)) udc_enable(udc); return 0; +transceiver_fail: + if (driver->unbind) + driver->unbind(&udc->gadget); bind_fail: device_del(&udc->gadget.dev); add_fail: @@ -1840,9 +1851,11 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc->driver = NULL; device_del(&udc->gadget.dev); - dev_info(udc->dev, "unregistered gadget driver '%s'\n", driver->driver.name); + + if (udc->transceiver) + return otg_set_peripheral(udc->transceiver, NULL); return 0; } EXPORT_SYMBOL(usb_gadget_unregister_driver); @@ -2359,6 +2372,7 @@ static int __init pxa_udc_probe(struct platform_device *pdev) udc->dev = &pdev->dev; udc->mach = pdev->dev.platform_data; + udc->transceiver = otg_get_transceiver(); gpio = udc->mach->gpio_pullup; if (gpio_is_valid(gpio)) { @@ -2431,6 +2445,9 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) if (gpio_is_valid(gpio)) gpio_free(gpio); + otg_put_transceiver(udc->transceiver); + + udc->transceiver = NULL; platform_set_drvdata(_dev, NULL); the_controller = NULL; clk_put(udc->clk); diff --git a/drivers/usb/gadget/pxa27x_udc.h b/drivers/usb/gadget/pxa27x_udc.h index 64741e19920..db58125331d 100644 --- a/drivers/usb/gadget/pxa27x_udc.h +++ b/drivers/usb/gadget/pxa27x_udc.h @@ -26,6 +26,7 @@ #include #include #include +#include /* * Register definitions @@ -421,6 +422,7 @@ struct udc_stats { * @driver: bound gadget (zero, g_ether, g_file_storage, ...) * @dev: device * @mach: machine info, used to activate specific GPIO + * @transceiver: external transceiver to handle vbus sense and D+ pullup * @ep0state: control endpoint state machine state * @stats: statistics on udc usage * @udc_usb_ep: array of usb endpoints offered by the gadget @@ -446,6 +448,7 @@ struct pxa_udc { struct usb_gadget_driver *driver; struct device *dev; struct pxa2xx_udc_mach_info *mach; + struct otg_transceiver *transceiver; enum ep0_state ep0state; struct udc_stats stats; -- cgit v1.2.3 From ee069fb1185895e725ad942c7a529f947e25166d Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 24 Jan 2009 23:59:38 -0800 Subject: USB: pxa27x_udc: add vbus_draw callback Add the vbus_draw() callback to inform the transceiver, if it exists, how much current may be drawn. The decision is taken on gadget driver side using the configuration chosen by the host and its bMaxPower field. Some systems can use the host's VBUS supply to augment or recharge a battery. (There's also a default of 100 mA for unconfigured devices, or 8 mA if they're OTG devices.) Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 11510472ee0..e50419d0899 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1623,12 +1623,34 @@ static int pxa_udc_vbus_session(struct usb_gadget *_gadget, int is_active) return 0; } +/** + * pxa_udc_vbus_draw - Called by gadget driver after SET_CONFIGURATION completed + * @_gadget: usb gadget + * @mA: current drawn + * + * Context: !in_interrupt() + * + * Called after a configuration was chosen by a USB host, to inform how much + * current can be drawn by the device from VBus line. + * + * Returns 0 or -EOPNOTSUPP if no transceiver is handling the udc + */ +static int pxa_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) +{ + struct pxa_udc *udc; + + udc = to_gadget_udc(_gadget); + if (udc->transceiver) + return otg_set_power(udc->transceiver, mA); + return -EOPNOTSUPP; +} + static const struct usb_gadget_ops pxa_udc_ops = { .get_frame = pxa_udc_get_frame, .wakeup = pxa_udc_wakeup, .pullup = pxa_udc_pullup, .vbus_session = pxa_udc_vbus_session, - /* current versions must always be self-powered */ + .vbus_draw = pxa_udc_vbus_draw, }; /** -- cgit v1.2.3 From db5e6df172309c382982790aafa8cd87dc0b6292 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 29 Dec 2008 11:19:10 +0100 Subject: USB: ub: use USB API functions rather than constants This set of patches introduces calls to the following set of functions: usb_endpoint_dir_in(epd) usb_endpoint_dir_out(epd) usb_endpoint_is_bulk_in(epd) usb_endpoint_is_bulk_out(epd) usb_endpoint_is_int_in(epd) usb_endpoint_is_int_out(epd) usb_endpoint_num(epd) usb_endpoint_type(epd) usb_endpoint_xfer_bulk(epd) usb_endpoint_xfer_control(epd) usb_endpoint_xfer_int(epd) usb_endpoint_xfer_isoc(epd) In some cases, introducing one of these functions is not possible, and it just replaces an explicit integer value by one of the following constants: USB_ENDPOINT_XFER_BULK USB_ENDPOINT_XFER_CONTROL USB_ENDPOINT_XFER_INT USB_ENDPOINT_XFER_ISOC An extract of the semantic patch that makes these changes is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r1@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bmAttributes & \(USB_ENDPOINT_XFERTYPE_MASK\|3\)) == - \(USB_ENDPOINT_XFER_CONTROL\|0\)) + usb_endpoint_xfer_control(epd) @r5@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bEndpointAddress & \(USB_ENDPOINT_DIR_MASK\|0x80\)) == - \(USB_DIR_IN\|0x80\)) + usb_endpoint_dir_in(epd) @inc@ @@ #include @depends on !inc && (r1||r5)@ @@ + #include #include // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 12fb816db7b..b36b84fbe39 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -2146,10 +2146,9 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, ep = &altsetting->endpoint[i].desc; /* Is it a BULK endpoint? */ - if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) - == USB_ENDPOINT_XFER_BULK) { + if (usb_endpoint_xfer_bulk(ep)) { /* BULK in or out? */ - if (ep->bEndpointAddress & USB_DIR_IN) { + if (usb_endpoint_dir_in(ep)) { if (ep_in == NULL) ep_in = ep; } else { @@ -2168,9 +2167,9 @@ static int ub_get_pipes(struct ub_dev *sc, struct usb_device *dev, sc->send_ctrl_pipe = usb_sndctrlpipe(dev, 0); sc->recv_ctrl_pipe = usb_rcvctrlpipe(dev, 0); sc->send_bulk_pipe = usb_sndbulkpipe(dev, - ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_out)); sc->recv_bulk_pipe = usb_rcvbulkpipe(dev, - ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_in)); return 0; } -- cgit v1.2.3 From 00185a60c37549531b9eee562d3eba19020875d5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sun, 21 Dec 2008 16:41:36 +0100 Subject: USB: Remove redundant test in pxa27x_udc and ftdi_sio priv is checked not to be NULL near the beginning of the function and not changed subsequently, making the test redundant. A simplified version of the semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r exists@ local idexpression x; expression E; position p1,p2; @@ if (x@p1 == NULL || ...) { ... when forall return ...; } ... when != \(x=E\|x--\|x++\|--x\|++x\|x-=E\|x+=E\|x|=E\|x&=E\|&x\) ( x@p2 == NULL | x@p2 != NULL ) // another path to the test that is not through p1? @s exists@ local idexpression r.x; position r.p1,r.p2; @@ ... when != x@p1 ( x@p2 == NULL | x@p2 != NULL ) @fix depends on !s@ position r.p1,r.p2; expression x,E; statement S1,S2; @@ ( - if ((x@p2 != NULL) || ...) S1 | - if ((x@p2 == NULL) && ...) S1 | - BUG_ON(x@p2 == NULL); ) // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 2 +- drivers/usb/serial/ftdi_sio.c | 16 +++++++--------- 2 files changed, 8 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index e50419d0899..91ba1e93947 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -279,7 +279,7 @@ static void pxa_init_debugfs(struct pxa_udc *udc) goto err_queues; eps = debugfs_create_file("epstate", 0400, root, udc, &eps_dbg_fops); - if (!queues) + if (!eps) goto err_eps; udc->debugfs_root = root; diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index ae84c326a54..d889216bcb3 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1938,15 +1938,13 @@ static void ftdi_process_read(struct work_struct *work) /* Compare new line status to the old one, signal if different/ N.B. packet may be processed more than once, but differences are only processed once. */ - if (priv != NULL) { - char new_status = data[packet_offset + 0] & - FTDI_STATUS_B0_MASK; - if (new_status != priv->prev_status) { - priv->diff_status |= - new_status ^ priv->prev_status; - wake_up_interruptible(&priv->delta_msr_wait); - priv->prev_status = new_status; - } + char new_status = data[packet_offset + 0] & + FTDI_STATUS_B0_MASK; + if (new_status != priv->prev_status) { + priv->diff_status |= + new_status ^ priv->prev_status; + wake_up_interruptible(&priv->delta_msr_wait); + priv->prev_status = new_status; } length = min(PKTSZ, urb->actual_length-packet_offset)-2; -- cgit v1.2.3 From 2e0fe709687470637a0709b930ccc9e993d2dad5 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Mon, 29 Dec 2008 11:22:14 +0100 Subject: USB: drivers: use USB API functions rather than constants This set of patches introduces calls to the following set of functions: usb_endpoint_dir_in(epd) usb_endpoint_dir_out(epd) usb_endpoint_is_bulk_in(epd) usb_endpoint_is_bulk_out(epd) usb_endpoint_is_int_in(epd) usb_endpoint_is_int_out(epd) usb_endpoint_num(epd) usb_endpoint_type(epd) usb_endpoint_xfer_bulk(epd) usb_endpoint_xfer_control(epd) usb_endpoint_xfer_int(epd) usb_endpoint_xfer_isoc(epd) In some cases, introducing one of these functions is not possible, and it just replaces an explicit integer value by one of the following constants: USB_ENDPOINT_XFER_BULK USB_ENDPOINT_XFER_CONTROL USB_ENDPOINT_XFER_INT USB_ENDPOINT_XFER_ISOC An extract of the semantic patch that makes these changes is as follows: (http://www.emn.fr/x-info/coccinelle/) // @r1@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bmAttributes & \(USB_ENDPOINT_XFERTYPE_MASK\|3\)) == - \(USB_ENDPOINT_XFER_CONTROL\|0\)) + usb_endpoint_xfer_control(epd) @r5@ struct usb_endpoint_descriptor *epd; @@ - ((epd->bEndpointAddress & \(USB_ENDPOINT_DIR_MASK\|0x80\)) == - \(USB_DIR_IN\|0x80\)) + usb_endpoint_dir_in(epd) @inc@ @@ #include @depends on !inc && (r1||r5)@ @@ + #include #include // Signed-off-by: Julia Lawall Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devices.c | 2 +- drivers/usb/core/endpoint.c | 9 ++++----- drivers/usb/host/r8a66597-hcd.c | 15 +++++++-------- drivers/usb/serial/keyspan.c | 2 +- drivers/usb/storage/usb.c | 6 +++--- 5 files changed, 16 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c index 6ec38175a81..73c108d117b 100644 --- a/drivers/usb/core/devices.c +++ b/drivers/usb/core/devices.c @@ -187,7 +187,7 @@ static char *usb_dump_endpoint_descriptor(int speed, char *start, char *end, } /* this isn't checking for illegal values */ - switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(desc)) { case USB_ENDPOINT_XFER_CONTROL: type = "Ctrl"; if (speed == USB_SPEED_HIGH) /* uframes per NAK */ diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c index e1710f260b4..40dee2ac013 100644 --- a/drivers/usb/core/endpoint.c +++ b/drivers/usb/core/endpoint.c @@ -66,7 +66,7 @@ static ssize_t show_ep_type(struct device *dev, struct device_attribute *attr, struct ep_device *ep = to_ep_device(dev); char *type = "unknown"; - switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(ep->desc)) { case USB_ENDPOINT_XFER_CONTROL: type = "Control"; break; @@ -94,7 +94,7 @@ static ssize_t show_ep_interval(struct device *dev, in = (ep->desc->bEndpointAddress & USB_DIR_IN); - switch (ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(ep->desc)) { case USB_ENDPOINT_XFER_CONTROL: if (ep->udev->speed == USB_SPEED_HIGH) /* uframes per NAK */ interval = ep->desc->bInterval; @@ -131,10 +131,9 @@ static ssize_t show_ep_direction(struct device *dev, struct ep_device *ep = to_ep_device(dev); char *direction; - if ((ep->desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == - USB_ENDPOINT_XFER_CONTROL) + if (usb_endpoint_xfer_control(ep->desc)) direction = "both"; - else if (ep->desc->bEndpointAddress & USB_DIR_IN) + else if (usb_endpoint_dir_in(ep->desc)) direction = "in"; else direction = "out"; diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 319041205b5..5e942d94aeb 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -660,9 +660,9 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, u16 array[R8A66597_MAX_NUM_PIPE], i = 0, min; memset(array, 0, sizeof(array)); - switch (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { + switch (usb_endpoint_type(ep)) { case USB_ENDPOINT_XFER_BULK: - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + if (usb_endpoint_dir_in(ep)) array[i++] = 4; else { array[i++] = 3; @@ -670,7 +670,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, } break; case USB_ENDPOINT_XFER_INT: - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) { + if (usb_endpoint_dir_in(ep)) { array[i++] = 6; array[i++] = 7; array[i++] = 8; @@ -678,7 +678,7 @@ static u16 get_empty_pipenum(struct r8a66597 *r8a66597, array[i++] = 9; break; case USB_ENDPOINT_XFER_ISOC: - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + if (usb_endpoint_dir_in(ep)) array[i++] = 2; else array[i++] = 1; @@ -928,10 +928,9 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, info.pipenum = get_empty_pipenum(r8a66597, ep); info.address = get_urb_to_r8a66597_addr(r8a66597, urb); - info.epnum = ep->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK; + info.epnum = usb_endpoint_num(ep); info.maxpacket = le16_to_cpu(ep->wMaxPacketSize); - info.type = get_r8a66597_type(ep->bmAttributes - & USB_ENDPOINT_XFERTYPE_MASK); + info.type = get_r8a66597_type(usb_endpoint_type(ep)); info.bufnum = get_bufnum(info.pipenum); info.buf_bsize = get_buf_bsize(info.pipenum); if (info.type == R8A66597_BULK) { @@ -941,7 +940,7 @@ static void init_pipe_info(struct r8a66597 *r8a66597, struct urb *urb, info.interval = get_interval(urb, ep->bInterval); info.timer_interval = get_timer_interval(urb, ep->bInterval); } - if (ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) + if (usb_endpoint_dir_in(ep)) info.dir_in = 1; else info.dir_in = 0; diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 9878c0fb385..00daa8f7759 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c @@ -1507,7 +1507,7 @@ static struct urb *keyspan_setup_urb(struct usb_serial *serial, int endpoint, } else { dev_warn(&serial->interface->dev, "unsupported endpoint type %x\n", - ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); + usb_endpoint_type(ep_desc)); usb_free_urb(urb); return NULL; } diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 4becf495ca2..b01dade63cb 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -846,12 +846,12 @@ static int get_pipes(struct us_data *us) us->send_ctrl_pipe = usb_sndctrlpipe(us->pusb_dev, 0); us->recv_ctrl_pipe = usb_rcvctrlpipe(us->pusb_dev, 0); us->send_bulk_pipe = usb_sndbulkpipe(us->pusb_dev, - ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_out)); us->recv_bulk_pipe = usb_rcvbulkpipe(us->pusb_dev, - ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_in)); if (ep_int) { us->recv_intr_pipe = usb_rcvintpipe(us->pusb_dev, - ep_int->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); + usb_endpoint_num(ep_int)); us->ep_bInterval = ep_int->bInterval; } return 0; -- cgit v1.2.3 From bcbbbfc169e837f0bf54dd4a6ef0a6494fb14925 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 11 Jan 2009 17:25:13 +0800 Subject: USB: gadget: remove duplicated #include Removed duplicated #include in drivers/usb/gadget/ci13xxx_udc.c Signed-off-by: Huang Weiyi Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/ci13xxx_udc.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index bebf911c7e5..0e310b9aa7a 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -56,7 +56,6 @@ #include #include #include -#include #include #include #include -- cgit v1.2.3 From 664d5df92e88b6ef091048a802b3750f4e989180 Mon Sep 17 00:00:00 2001 From: Werner Cornelius Date: Fri, 16 Jan 2009 21:02:41 +0100 Subject: USB: usb-serial ch341: support for DTR/RTS/CTS Fixup of Werner Cornelius patch to the ch341 USB-serial driver, which adds: - support all baudrates, not just a hard-coded set - support for controlling DTR, RTS and CTS Features still missing: - character length other than 8 bits - parity settings - break control I adapted his patch for the new usb_serial API introduced in 2.6.25-git8 by Alan Cox on 22 July 2008. Non-compliance to the new API was a reason for refusing a similar patch from Tollef Fog Heen. Usage example by Tollef Fog Heen : TEMPer USB thermometer Signed-off-by: Werner Cornelius Signed-off-by: Boris Hajduk Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 374 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 302 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index f61e3ca6430..d5ea679e169 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -1,5 +1,7 @@ /* * Copyright 2007, Frank A Kingswood + * Copyright 2007, Werner Cornelius + * Copyright 2009, Boris Hajduk * * ch341.c implements a serial port driver for the Winchiphead CH341. * @@ -21,9 +23,39 @@ #include #include -#define DEFAULT_BAUD_RATE 2400 +#define DEFAULT_BAUD_RATE 9600 #define DEFAULT_TIMEOUT 1000 +/* flags for IO-Bits */ +#define CH341_BIT_RTS (1 << 6) +#define CH341_BIT_DTR (1 << 5) + +/******************************/ +/* interrupt pipe definitions */ +/******************************/ +/* always 4 interrupt bytes */ +/* first irq byte normally 0x08 */ +/* second irq byte base 0x7d + below */ +/* third irq byte base 0x94 + below */ +/* fourth irq byte normally 0xee */ + +/* second interrupt byte */ +#define CH341_MULT_STAT 0x04 /* multiple status since last interrupt event */ + +/* status returned in third interrupt answer byte, inverted in data + from irq */ +#define CH341_BIT_CTS 0x01 +#define CH341_BIT_DSR 0x02 +#define CH341_BIT_RI 0x04 +#define CH341_BIT_DCD 0x08 +#define CH341_BITS_MODEM_STAT 0x0f /* all bits */ + +/*******************************/ +/* baudrate calculation factor */ +/*******************************/ +#define CH341_BAUDBASE_FACTOR 1532620800 +#define CH341_BAUDBASE_DIVMAX 3 + static int debug; static struct usb_device_id id_table [] = { @@ -34,9 +66,12 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE(usb, id_table); struct ch341_private { - unsigned baud_rate; - u8 dtr; - u8 rts; + spinlock_t lock; /* access lock */ + wait_queue_head_t delta_msr_wait; /* wait queue for modem status */ + unsigned baud_rate; /* set baud rate */ + u8 line_control; /* set line control value RTS/DTR */ + u8 line_status; /* active status of modem control inputs */ + u8 multi_status_change; /* status changed multiple since last call */ }; static int ch341_control_out(struct usb_device *dev, u8 request, @@ -72,37 +107,28 @@ static int ch341_set_baudrate(struct usb_device *dev, { short a, b; int r; + unsigned long factor; + short divisor; dbg("ch341_set_baudrate(%d)", priv->baud_rate); - switch (priv->baud_rate) { - case 2400: - a = 0xd901; - b = 0x0038; - break; - case 4800: - a = 0x6402; - b = 0x001f; - break; - case 9600: - a = 0xb202; - b = 0x0013; - break; - case 19200: - a = 0xd902; - b = 0x000d; - break; - case 38400: - a = 0x6403; - b = 0x000a; - break; - case 115200: - a = 0xcc03; - b = 0x0008; - break; - default: + + if (!priv->baud_rate) return -EINVAL; + factor = (CH341_BAUDBASE_FACTOR / priv->baud_rate); + divisor = CH341_BAUDBASE_DIVMAX; + + while ((factor > 0xfff0) && divisor) { + factor >>= 3; + divisor--; } + if (factor > 0xfff0) + return -EINVAL; + + factor = 0x10000 - factor; + a = (factor & 0xff00) | divisor; + b = factor & 0xff; + r = ch341_control_out(dev, 0x9a, 0x1312, a); if (!r) r = ch341_control_out(dev, 0x9a, 0x0f2c, b); @@ -110,19 +136,18 @@ static int ch341_set_baudrate(struct usb_device *dev, return r; } -static int ch341_set_handshake(struct usb_device *dev, - struct ch341_private *priv) +static int ch341_set_handshake(struct usb_device *dev, u8 control) { - dbg("ch341_set_handshake(%d,%d)", priv->dtr, priv->rts); - return ch341_control_out(dev, 0xa4, - ~((priv->dtr?1<<5:0)|(priv->rts?1<<6:0)), 0); + dbg("ch341_set_handshake(0x%02x)", control); + return ch341_control_out(dev, 0xa4, ~control, 0); } -static int ch341_get_status(struct usb_device *dev) +static int ch341_get_status(struct usb_device *dev, struct ch341_private *priv) { char *buffer; int r; const unsigned size = 8; + unsigned long flags; dbg("ch341_get_status()"); @@ -134,10 +159,15 @@ static int ch341_get_status(struct usb_device *dev) if (r < 0) goto out; - /* Not having the datasheet for the CH341, we ignore the bytes returned - * from the device. Return error if the device did not respond in time. - */ - r = 0; + /* setup the private status if available */ + if (r == 2) { + r = 0; + spin_lock_irqsave(&priv->lock, flags); + priv->line_status = (~(*buffer)) & CH341_BITS_MODEM_STAT; + priv->multi_status_change = 0; + spin_unlock_irqrestore(&priv->lock, flags); + } else + r = -EPROTO; out: kfree(buffer); return r; @@ -180,7 +210,7 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) goto out; /* expect 0xff 0xee */ - r = ch341_get_status(dev); + r = ch341_get_status(dev, priv); if (r < 0) goto out; @@ -192,12 +222,12 @@ static int ch341_configure(struct usb_device *dev, struct ch341_private *priv) if (r < 0) goto out; - r = ch341_set_handshake(dev, priv); + r = ch341_set_handshake(dev, priv->line_control); if (r < 0) goto out; /* expect 0x9f 0xee */ - r = ch341_get_status(dev); + r = ch341_get_status(dev, priv); out: kfree(buffer); return r; @@ -216,9 +246,10 @@ static int ch341_attach(struct usb_serial *serial) if (!priv) return -ENOMEM; + spin_lock_init(&priv->lock); + init_waitqueue_head(&priv->delta_msr_wait); priv->baud_rate = DEFAULT_BAUD_RATE; - priv->dtr = 1; - priv->rts = 1; + priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; r = ch341_configure(serial->dev, priv); if (r < 0) @@ -231,6 +262,35 @@ error: kfree(priv); return r; } +static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + unsigned int c_cflag; + + dbg("%s - port %d", __func__, port->number); + + /* shutdown our urbs */ + dbg("%s - shutting down urbs", __func__); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); + usb_kill_urb(port->interrupt_in_urb); + + if (tty) { + c_cflag = tty->termios->c_cflag; + if (c_cflag & HUPCL) { + /* drop DTR and RTS */ + spin_lock_irqsave(&priv->lock, flags); + priv->line_control = 0; + spin_unlock_irqrestore(&priv->lock, flags); + ch341_set_handshake(port->serial->dev, 0); + } + } + wake_up_interruptible(&priv->delta_msr_wait); +} + + /* open this device, set default parameters */ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) @@ -242,14 +302,13 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, dbg("ch341_open()"); priv->baud_rate = DEFAULT_BAUD_RATE; - priv->dtr = 1; - priv->rts = 1; + priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; r = ch341_configure(serial->dev, priv); if (r) goto out; - r = ch341_set_handshake(serial->dev, priv); + r = ch341_set_handshake(serial->dev, priv->line_control); if (r) goto out; @@ -257,6 +316,16 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, if (r) goto out; + dbg("%s - submitting interrupt urb", __func__); + port->interrupt_in_urb->dev = serial->dev; + r = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (r) { + dev_err(&port->dev, "%s - failed submitting interrupt urb," + " error %d\n", __func__, r); + ch341_close(tty, port, NULL); + return -EPROTO; + } + r = usb_serial_generic_open(tty, port, filp); out: return r; @@ -270,38 +339,194 @@ static void ch341_set_termios(struct tty_struct *tty, { struct ch341_private *priv = usb_get_serial_port_data(port); unsigned baud_rate; + unsigned long flags; dbg("ch341_set_termios()"); + if (!tty || !tty->termios) + return; + baud_rate = tty_get_baud_rate(tty); - switch (baud_rate) { - case 2400: - case 4800: - case 9600: - case 19200: - case 38400: - case 115200: - priv->baud_rate = baud_rate; - break; - default: - dbg("Rate %d not supported, using %d", - baud_rate, DEFAULT_BAUD_RATE); - priv->baud_rate = DEFAULT_BAUD_RATE; + priv->baud_rate = baud_rate; + + if (baud_rate) { + spin_lock_irqsave(&priv->lock, flags); + priv->line_control |= (CH341_BIT_DTR | CH341_BIT_RTS); + spin_unlock_irqrestore(&priv->lock, flags); + ch341_set_baudrate(port->serial->dev, priv); + } else { + spin_lock_irqsave(&priv->lock, flags); + priv->line_control &= ~(CH341_BIT_DTR | CH341_BIT_RTS); + spin_unlock_irqrestore(&priv->lock, flags); } - ch341_set_baudrate(port->serial->dev, priv); + ch341_set_handshake(port->serial->dev, priv->line_control); /* Unimplemented: * (cflag & CSIZE) : data bits [5, 8] * (cflag & PARENB) : parity {NONE, EVEN, ODD} * (cflag & CSTOPB) : stop bits [1, 2] */ +} + +static int ch341_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 control; + + spin_lock_irqsave(&priv->lock, flags); + if (set & TIOCM_RTS) + priv->line_control |= CH341_BIT_RTS; + if (set & TIOCM_DTR) + priv->line_control |= CH341_BIT_DTR; + if (clear & TIOCM_RTS) + priv->line_control &= ~CH341_BIT_RTS; + if (clear & TIOCM_DTR) + priv->line_control &= ~CH341_BIT_DTR; + control = priv->line_control; + spin_unlock_irqrestore(&priv->lock, flags); + + return ch341_set_handshake(port->serial->dev, control); +} + +static void ch341_read_int_callback(struct urb *urb) +{ + struct usb_serial_port *port = (struct usb_serial_port *) urb->context; + unsigned char *data = urb->transfer_buffer; + unsigned int actual_length = urb->actual_length; + int status; + + dbg("%s (%d)", __func__, port->number); + + switch (urb->status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", __func__, + urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", __func__, + urb->status); + goto exit; + } + + usb_serial_debug_data(debug, &port->dev, __func__, + urb->actual_length, urb->transfer_buffer); + + if (actual_length >= 4) { + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + + spin_lock_irqsave(&priv->lock, flags); + priv->line_status = (~(data[2])) & CH341_BITS_MODEM_STAT; + if ((data[1] & CH341_MULT_STAT)) + priv->multi_status_change = 1; + spin_unlock_irqrestore(&priv->lock, flags); + wake_up_interruptible(&priv->delta_msr_wait); + } + +exit: + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) + dev_err(&urb->dev->dev, + "%s - usb_submit_urb failed with result %d\n", + __func__, status); +} + +static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) +{ + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 prevstatus; + u8 status; + u8 changed; + u8 multi_change = 0; + + spin_lock_irqsave(&priv->lock, flags); + prevstatus = priv->line_status; + priv->multi_status_change = 0; + spin_unlock_irqrestore(&priv->lock, flags); + + while (!multi_change) { + interruptible_sleep_on(&priv->delta_msr_wait); + /* see if a signal did it */ + if (signal_pending(current)) + return -ERESTARTSYS; + + spin_lock_irqsave(&priv->lock, flags); + status = priv->line_status; + multi_change = priv->multi_status_change; + spin_unlock_irqrestore(&priv->lock, flags); + + changed = prevstatus ^ status; + + if (((arg & TIOCM_RNG) && (changed & CH341_BIT_RI)) || + ((arg & TIOCM_DSR) && (changed & CH341_BIT_DSR)) || + ((arg & TIOCM_CD) && (changed & CH341_BIT_DCD)) || + ((arg & TIOCM_CTS) && (changed & CH341_BIT_CTS))) { + return 0; + } + prevstatus = status; + } + + return 0; +} + +/*static int ch341_ioctl(struct usb_serial_port *port, struct file *file,*/ +static int ch341_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + dbg("%s (%d) cmd = 0x%04x", __func__, port->number, cmd); + + switch (cmd) { + case TIOCMIWAIT: + dbg("%s (%d) TIOCMIWAIT", __func__, port->number); + return wait_modem_info(port, arg); + + default: + dbg("%s not supported = 0x%04x", __func__, cmd); + break; + } + + return -ENOIOCTLCMD; +} + +static int ch341_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + struct ch341_private *priv = usb_get_serial_port_data(port); + unsigned long flags; + u8 mcr; + u8 status; + unsigned int result; + + dbg("%s (%d)", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + mcr = priv->line_control; + status = priv->line_status; + spin_unlock_irqrestore(&priv->lock, flags); + + result = ((mcr & CH341_BIT_DTR) ? TIOCM_DTR : 0) + | ((mcr & CH341_BIT_RTS) ? TIOCM_RTS : 0) + | ((status & CH341_BIT_CTS) ? TIOCM_CTS : 0) + | ((status & CH341_BIT_DSR) ? TIOCM_DSR : 0) + | ((status & CH341_BIT_RI) ? TIOCM_RI : 0) + | ((status & CH341_BIT_DCD) ? TIOCM_CD : 0); + + dbg("%s - result = %x", __func__, result); - /* Copy back the old hardware settings */ - tty_termios_copy_hw(tty->termios, old_termios); - /* And re-encode with the new baud */ - tty_encode_baud_rate(tty, baud_rate, baud_rate); + return result; } static struct usb_driver ch341_driver = { @@ -317,12 +542,17 @@ static struct usb_serial_driver ch341_device = { .owner = THIS_MODULE, .name = "ch341-uart", }, - .id_table = id_table, - .usb_driver = &ch341_driver, - .num_ports = 1, - .open = ch341_open, - .set_termios = ch341_set_termios, - .attach = ch341_attach, + .id_table = id_table, + .usb_driver = &ch341_driver, + .num_ports = 1, + .open = ch341_open, + .close = ch341_close, + .ioctl = ch341_ioctl, + .set_termios = ch341_set_termios, + .tiocmget = ch341_tiocmget, + .tiocmset = ch341_tiocmset, + .read_int_callback = ch341_read_int_callback, + .attach = ch341_attach, }; static int __init ch341_init(void) -- cgit v1.2.3 From 8f182e5ddc84a30d7014a753ae359d85b1238e7f Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:17:25 +0200 Subject: USB: imx_udc: Fix IMX UDC gadget bugs Fix small bugs and add some omptimization in IMX UDC Gadget. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 33 +++++++++++++++++++-------------- drivers/usb/gadget/imx_udc.h | 2 +- 2 files changed, 20 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 77c5d0a8a06..9e3fe306301 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -283,7 +283,7 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) imx_flush(imx_ep); /* Special care for ep0 */ - if (EP_NO(imx_ep)) { + if (!EP_NO(imx_ep)) { temp = __raw_readl(imx_usb->base + USB_CTRL); __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL); do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER); @@ -301,7 +301,7 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) break; udelay(20); } - if (i == 50) + if (i == 100) D_ERR(imx_usb->dev, "<%s> Non finished stall on %s\n", __func__, imx_ep->ep.name); } @@ -539,10 +539,9 @@ static int handle_ep0(struct imx_ep_struct *imx_ep) struct imx_request *req = NULL; int ret = 0; - if (!list_empty(&imx_ep->queue)) + if (!list_empty(&imx_ep->queue)) { req = list_entry(imx_ep->queue.next, struct imx_request, queue); - if (req) { switch (imx_ep->imx_usb->ep0state) { case EP0_IN_DATA_PHASE: /* GET_DESCRIPTOR */ @@ -561,6 +560,10 @@ static int handle_ep0(struct imx_ep_struct *imx_ep) } } + else + D_ERR(imx_ep->imx_usb->dev, "<%s> no request on %s\n", + __func__, imx_ep->ep.name); + return ret; } @@ -759,7 +762,7 @@ static int imx_ep_queue */ if (imx_usb->set_config && !EP_NO(imx_ep)) { imx_usb->set_config = 0; - D_EPX(imx_usb->dev, + D_ERR(imx_usb->dev, "<%s> gadget reply set config\n", __func__); return 0; } @@ -779,8 +782,6 @@ static int imx_ep_queue return -ESHUTDOWN; } - local_irq_save(flags); - /* Debug */ D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n", __func__, EP_NO(imx_ep), @@ -790,17 +791,18 @@ static int imx_ep_queue if (imx_ep->stopped) { usb_req->status = -ESHUTDOWN; - ret = -ESHUTDOWN; - goto out; + return -ESHUTDOWN; } if (req->in_use) { D_ERR(imx_usb->dev, "<%s> refusing to queue req %p (already queued)\n", __func__, req); - goto out; + return 0; } + local_irq_save(flags); + usb_req->status = -EINPROGRESS; usb_req->actual = 0; @@ -810,7 +812,7 @@ static int imx_ep_queue ret = handle_ep0(imx_ep); else ret = handle_ep(imx_ep); -out: + local_irq_restore(flags); return ret; } @@ -1010,10 +1012,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) dump_usb_stat(__func__, imx_usb); } - if (!imx_usb->driver) { - /*imx_udc_disable(imx_usb);*/ + if (!imx_usb->driver) goto end_irq; - } if (intr & INTR_WAKEUP) { if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN @@ -1095,6 +1095,11 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) } if (intr & INTR_SOF) { + /* Copy from Freescale BSP. + We must enable SOF intr and set CMDOVER. + Datasheet don't specifiy this action, but it + is done in Freescale BSP, so just copy it. + */ if (imx_usb->ep0state == EP0_IDLE) { temp = __raw_readl(imx_usb->base + USB_CTRL); __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL); diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h index 850076937d8..d1dfb2d2fa8 100644 --- a/drivers/usb/gadget/imx_udc.h +++ b/drivers/usb/gadget/imx_udc.h @@ -170,7 +170,7 @@ struct imx_udc_struct { /* #define DEBUG_IRQ */ /* #define DEBUG_EPIRQ */ /* #define DEBUG_DUMP */ -#define DEBUG_ERR +/* #define DEBUG_ERR */ #ifdef DEBUG_REQ #define D_REQ(dev, args...) dev_dbg(dev, ## args) -- cgit v1.2.3 From 593bef6c75e11d2edb5396bd9775cf49a4cda659 Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:17:55 +0200 Subject: USB: imx_udc: Fix IMX UDC gadget code style Fix code style errors in IMX UDC Gadget. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 59 +++++++++++++++++++++++++++++--------------- drivers/usb/gadget/imx_udc.h | 46 ++++++++++++++++++++++------------ 2 files changed, 69 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 9e3fe306301..3ee5bd8bea7 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1,7 +1,7 @@ /* * driver/usb/gadget/imx_udc.c * - * Copyright (C) 2005 Mike Lee(eemike@gmail.com) + * Copyright (C) 2005 Mike Lee * Copyright (C) 2008 Darius Augulis * * This program is free software; you can redistribute it and/or modify @@ -51,7 +51,8 @@ void ep0_chg_stat(const char *label, struct imx_udc_struct *imx_usb, void imx_udc_enable(struct imx_udc_struct *imx_usb) { int temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, imx_usb->base + USB_CTRL); + __raw_writel(temp | CTRL_FE_ENA | CTRL_AFE_ENA, + imx_usb->base + USB_CTRL); imx_usb->gadget.speed = USB_SPEED_FULL; } @@ -126,7 +127,8 @@ void imx_udc_config(struct imx_udc_struct *imx_usb) for (j = 0; j < 5; j++) { __raw_writeb(ep_conf[j], imx_usb->base + USB_DDAT); - do {} while (__raw_readl(imx_usb->base + USB_DADR) + do {} while (__raw_readl(imx_usb->base + + USB_DADR) & DADR_BSY); } } @@ -183,7 +185,8 @@ void imx_udc_init_ep(struct imx_udc_struct *imx_usb) temp = (EP_DIR(imx_ep) << 7) | (max << 5) | (imx_ep->bmAttributes << 3); __raw_writel(temp, imx_usb->base + USB_EP_STAT(i)); - __raw_writel(temp | EPSTAT_FLUSH, imx_usb->base + USB_EP_STAT(i)); + __raw_writel(temp | EPSTAT_FLUSH, + imx_usb->base + USB_EP_STAT(i)); D_INI(imx_usb->dev, "<%s> ep%d_stat %08x\n", __func__, i, __raw_readl(imx_usb->base + USB_EP_STAT(i))); } @@ -278,15 +281,18 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) struct imx_udc_struct *imx_usb = imx_ep->imx_usb; int temp, i; - D_ERR(imx_usb->dev, "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name); + D_ERR(imx_usb->dev, + "<%s> Forced stall on %s\n", __func__, imx_ep->ep.name); imx_flush(imx_ep); /* Special care for ep0 */ if (!EP_NO(imx_ep)) { temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, imx_usb->base + USB_CTRL); - do { } while (__raw_readl(imx_usb->base + USB_CTRL) & CTRL_CMDOVER); + __raw_writel(temp | CTRL_CMDOVER | CTRL_CMDERROR, + imx_usb->base + USB_CTRL); + do { } while (__raw_readl(imx_usb->base + USB_CTRL) + & CTRL_CMDOVER); temp = __raw_readl(imx_usb->base + USB_CTRL); __raw_writel(temp & ~CTRL_CMDERROR, imx_usb->base + USB_CTRL); } @@ -296,7 +302,8 @@ void imx_ep_stall(struct imx_ep_struct *imx_ep) imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); for (i = 0; i < 100; i ++) { - temp = __raw_readl(imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); + temp = __raw_readl(imx_usb->base + + USB_EP_STAT(EP_NO(imx_ep))); if (!(temp & EPSTAT_STALL)) break; udelay(20); @@ -325,7 +332,8 @@ static int imx_udc_wakeup(struct usb_gadget *_gadget) ******************************************************************************* */ -static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req) +static void ep_add_request(struct imx_ep_struct *imx_ep, + struct imx_request *req) { if (unlikely(!req)) return; @@ -334,7 +342,8 @@ static void ep_add_request(struct imx_ep_struct *imx_ep, struct imx_request *req list_add_tail(&req->queue, &imx_ep->queue); } -static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req) +static void ep_del_request(struct imx_ep_struct *imx_ep, + struct imx_request *req) { if (unlikely(!req)) return; @@ -343,7 +352,8 @@ static void ep_del_request(struct imx_ep_struct *imx_ep, struct imx_request *req req->in_use = 0; } -static void done(struct imx_ep_struct *imx_ep, struct imx_request *req, int status) +static void done(struct imx_ep_struct *imx_ep, + struct imx_request *req, int status) { ep_del_request(imx_ep, req); @@ -494,7 +504,8 @@ static int write_fifo(struct imx_ep_struct *imx_ep, struct imx_request *req) __func__, imx_ep->ep.name, req, completed ? "completed" : "not completed"); if (!EP_NO(imx_ep)) - ep0_chg_stat(__func__, imx_ep->imx_usb, EP0_IDLE); + ep0_chg_stat(__func__, + imx_ep->imx_usb, EP0_IDLE); } } @@ -586,7 +597,8 @@ static void handle_ep0_devreq(struct imx_udc_struct *imx_usb) "<%s> no setup packet received\n", __func__); goto stall; } - u.word[i] = __raw_readl(imx_usb->base + USB_EP_FDAT(EP_NO(imx_ep))); + u.word[i] = __raw_readl(imx_usb->base + + USB_EP_FDAT(EP_NO(imx_ep))); } temp = imx_ep_empty(imx_ep); @@ -785,8 +797,10 @@ static int imx_ep_queue /* Debug */ D_REQ(imx_usb->dev, "<%s> ep%d %s request for [%d] bytes\n", __func__, EP_NO(imx_ep), - ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) - || (EP_NO(imx_ep) && EP_DIR(imx_ep))) ? "IN" : "OUT", usb_req->length); + ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state + == EP0_IN_DATA_PHASE) + || (EP_NO(imx_ep) && EP_DIR(imx_ep))) + ? "IN" : "OUT", usb_req->length); dump_req(__func__, imx_ep, usb_req); if (imx_ep->stopped) { @@ -1061,7 +1075,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) /* Config setup */ if (imx_usb->cfg != cfg) { - D_REQ(imx_usb->dev, "<%s> Change config start\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change config start\n", __func__); u.bRequest = USB_REQ_SET_CONFIGURATION; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1073,11 +1088,13 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); imx_usb->set_config = 0; - D_REQ(imx_usb->dev, "<%s> Change config done\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change config done\n", __func__); } if (imx_usb->intf != intf || imx_usb->alt != alt) { - D_REQ(imx_usb->dev, "<%s> Change interface start\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change interface start\n", __func__); u.bRequest = USB_REQ_SET_INTERFACE; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1090,7 +1107,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); imx_usb->set_config = 0; - D_REQ(imx_usb->dev, "<%s> Change interface done\n",__func__); + D_REQ(imx_usb->dev, + "<%s> Change interface done\n", __func__); } } @@ -1102,7 +1120,8 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) */ if (imx_usb->ep0state == EP0_IDLE) { temp = __raw_readl(imx_usb->base + USB_CTRL); - __raw_writel(temp | CTRL_CMDOVER, imx_usb->base + USB_CTRL); + __raw_writel(temp | CTRL_CMDOVER, + imx_usb->base + USB_CTRL); } } diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h index d1dfb2d2fa8..6b0b1e3d6fc 100644 --- a/drivers/usb/gadget/imx_udc.h +++ b/drivers/usb/gadget/imx_udc.h @@ -23,7 +23,8 @@ /* Helper macros */ #define EP_NO(ep) ((ep->bEndpointAddress) & ~USB_DIR_IN) /* IN:1, OUT:0 */ #define EP_DIR(ep) ((ep->bEndpointAddress) & USB_DIR_IN ? 1 : 0) -#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/ +#define irq_to_ep(irq) (((irq) >= USBD_INT0) || ((irq) <= USBD_INT6) \ + ? ((irq) - USBD_INT0) : (USBD_INT6)) /*should not happen*/ #define ep_to_irq(ep) (EP_NO((ep)) + USBD_INT0) #define IMX_USB_NB_EP 6 @@ -88,8 +89,8 @@ struct imx_udc_struct { #define USB_EP_FDAT3(x) (0x3F + (x*0x30)) /* USB FIFO data */ #define USB_EP_FSTAT(x) (0x40 + (x*0x30)) /* USB FIFO status */ #define USB_EP_FCTRL(x) (0x44 + (x*0x30)) /* USB FIFO control */ -#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last read frame pointer */ -#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last write frame pointer */ +#define USB_EP_LRFP(x) (0x48 + (x*0x30)) /* USB last rd f. pointer */ +#define USB_EP_LWFP(x) (0x4C + (x*0x30)) /* USB last wr f. pointer */ #define USB_EP_FALRM(x) (0x50 + (x*0x30)) /* USB FIFO alarm */ #define USB_EP_FRDP(x) (0x54 + (x*0x30)) /* USB FIFO read pointer */ #define USB_EP_FWRP(x) (0x58 + (x*0x30)) /* USB FIFO write pointer */ @@ -228,7 +229,8 @@ struct imx_udc_struct { #endif /* DEBUG_IRQ */ #ifdef DEBUG_EPIRQ - static void dump_ep_intr(const char *label, int nr, int irqreg, struct device *dev) + static void dump_ep_intr(const char *label, int nr, int irqreg, + struct device *dev) { dev_dbg(dev, "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, nr, (irqreg & EPINTR_FIFO_FULL) ? " full" : "", @@ -246,7 +248,8 @@ struct imx_udc_struct { #endif /* DEBUG_IRQ */ #ifdef DEBUG_DUMP - static void dump_usb_stat(const char *label, struct imx_udc_struct *imx_usb) + static void dump_usb_stat(const char *label, + struct imx_udc_struct *imx_usb) { int temp = __raw_readl(imx_usb->base + USB_STAT); @@ -259,12 +262,15 @@ struct imx_udc_struct { (temp & STAT_ALTSET)); } - static void dump_ep_stat(const char *label, struct imx_ep_struct *imx_ep) + static void dump_ep_stat(const char *label, + struct imx_ep_struct *imx_ep) { - int temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_INTR(EP_NO(imx_ep))); + int temp = __raw_readl(imx_ep->imx_usb->base + + USB_EP_INTR(EP_NO(imx_ep))); dev_dbg(imx_ep->imx_usb->dev, - "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), + "<%s> EP%d_INTR=[%s%s%s%s%s%s%s%s%s]\n", + label, EP_NO(imx_ep), (temp & EPINTR_FIFO_FULL) ? " full" : "", (temp & EPINTR_FIFO_EMPTY) ? " fempty" : "", (temp & EPINTR_FIFO_ERROR) ? " ferr" : "", @@ -275,18 +281,22 @@ struct imx_udc_struct { (temp & EPINTR_DEVREQ) ? " devreq" : "", (temp & EPINTR_EOT) ? " eot" : ""); - temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_STAT(EP_NO(imx_ep))); + temp = __raw_readl(imx_ep->imx_usb->base + + USB_EP_STAT(EP_NO(imx_ep))); dev_dbg(imx_ep->imx_usb->dev, - "<%s> EP%d_STAT=[%s%s bcount=%d]\n", label, EP_NO(imx_ep), + "<%s> EP%d_STAT=[%s%s bcount=%d]\n", + label, EP_NO(imx_ep), (temp & EPSTAT_SIP) ? " sip" : "", (temp & EPSTAT_STALL) ? " stall" : "", (temp & EPSTAT_BCOUNT) >> 16); - temp = __raw_readl(imx_ep->imx_usb->base + USB_EP_FSTAT(EP_NO(imx_ep))); + temp = __raw_readl(imx_ep->imx_usb->base + + USB_EP_FSTAT(EP_NO(imx_ep))); dev_dbg(imx_ep->imx_usb->dev, - "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", label, EP_NO(imx_ep), + "<%s> EP%d_FSTAT=[%s%s%s%s%s%s%s]\n", + label, EP_NO(imx_ep), (temp & FSTAT_ERR) ? " ferr" : "", (temp & FSTAT_UF) ? " funder" : "", (temp & FSTAT_OF) ? " fover" : "", @@ -296,19 +306,23 @@ struct imx_udc_struct { (temp & FSTAT_EMPTY) ? " fempty" : ""); } - static void dump_req(const char *label, struct imx_ep_struct *imx_ep, struct usb_request *req) + static void dump_req(const char *label, struct imx_ep_struct *imx_ep, + struct usb_request *req) { int i; if (!req || !req->buf) { - dev_dbg(imx_ep->imx_usb->dev, "<%s> req or req buf is free\n", label); + dev_dbg(imx_ep->imx_usb->dev, + "<%s> req or req buf is free\n", label); return; } - if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state == EP0_IN_DATA_PHASE) + if ((!EP_NO(imx_ep) && imx_ep->imx_usb->ep0state + == EP0_IN_DATA_PHASE) || (EP_NO(imx_ep) && EP_DIR(imx_ep))) { - dev_dbg(imx_ep->imx_usb->dev, "<%s> request dump <", label); + dev_dbg(imx_ep->imx_usb->dev, + "<%s> request dump <", label); for (i = 0; i < req->length; i++) printk("%02x-", *((u8 *)req->buf + i)); printk(">\n"); -- cgit v1.2.3 From d24921a36df31332c32e1bb539671284d9e36bfa Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:18:33 +0200 Subject: USB: imx_udc: Fix IMX UDC gadget ep0 irq handling Fix ep0 interrupt handling in IMX UDC Gadget. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 3ee5bd8bea7..e590464c3a5 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1133,6 +1133,7 @@ end_irq: static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) { struct imx_udc_struct *imx_usb = dev; + struct imx_ep_struct *imx_ep = &imx_usb->imx_ep[0]; int intr = __raw_readl(imx_usb->base + USB_EP_INTR(0)); dump_ep_intr(__func__, 0, intr, imx_usb->dev); @@ -1142,16 +1143,15 @@ static irqreturn_t imx_udc_ctrl_irq(int irq, void *dev) return IRQ_HANDLED; } - /* DEVREQ IRQ has highest priority */ + /* DEVREQ has highest priority */ if (intr & (EPINTR_DEVREQ | EPINTR_MDEVREQ)) handle_ep0_devreq(imx_usb); /* Seem i.MX is missing EOF interrupt sometimes. - * Therefore we monitor both EOF and FIFO_EMPTY interrups - * when transmiting, and both EOF and FIFO_FULL when - * receiving data. + * Therefore we don't monitor EOF. + * We call handle_ep0() only if a request is queued for ep0. */ - else if (intr & (EPINTR_EOF | EPINTR_FIFO_EMPTY | EPINTR_FIFO_FULL)) - handle_ep0(&imx_usb->imx_ep[0]); + else if (!list_empty(&imx_ep->queue)) + handle_ep0(imx_ep); __raw_writel(intr, imx_usb->base + USB_EP_INTR(0)); -- cgit v1.2.3 From b633d28e2c5fbe1c8d163892644f57df04aa1421 Mon Sep 17 00:00:00 2001 From: Darius Augulis Date: Wed, 21 Jan 2009 15:19:19 +0200 Subject: USB: imx_udc: Fix IMX UDC gadget general irq handling Workaround of hw bug in IMX UDC. This bug causes wrong handling of CFG_CHG interrupt. Workaround is documented inline source code. Signed-off-by: Darius Augulis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/imx_udc.c | 158 +++++++++++++++++++++++++------------------ drivers/usb/gadget/imx_udc.h | 1 + 2 files changed, 94 insertions(+), 65 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index e590464c3a5..8d3c6a96098 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -1013,70 +1014,32 @@ static void udc_stop_activity(struct imx_udc_struct *imx_usb, ******************************************************************************* */ -static irqreturn_t imx_udc_irq(int irq, void *dev) +/* + * Called when timer expires. + * Timer is started when CFG_CHG is received. + */ +static void handle_config(unsigned long data) { - struct imx_udc_struct *imx_usb = dev; + struct imx_udc_struct *imx_usb = (void *)data; struct usb_ctrlrequest u; int temp, cfg, intf, alt; - int intr = __raw_readl(imx_usb->base + USB_INTR); - - if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START - | INTR_RESET_STOP | INTR_CFG_CHG)) { - dump_intr(__func__, intr, imx_usb->dev); - dump_usb_stat(__func__, imx_usb); - } - - if (!imx_usb->driver) - goto end_irq; - - if (intr & INTR_WAKEUP) { - if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN - && imx_usb->driver && imx_usb->driver->resume) - imx_usb->driver->resume(&imx_usb->gadget); - imx_usb->set_config = 0; - imx_usb->gadget.speed = USB_SPEED_FULL; - } - - if (intr & INTR_SUSPEND) { - if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN - && imx_usb->driver && imx_usb->driver->suspend) - imx_usb->driver->suspend(&imx_usb->gadget); - imx_usb->set_config = 0; - imx_usb->gadget.speed = USB_SPEED_UNKNOWN; - } - if (intr & INTR_RESET_START) { - __raw_writel(intr, imx_usb->base + USB_INTR); - udc_stop_activity(imx_usb, imx_usb->driver); - imx_usb->set_config = 0; - imx_usb->gadget.speed = USB_SPEED_UNKNOWN; - } - - if (intr & INTR_RESET_STOP) - imx_usb->gadget.speed = USB_SPEED_FULL; + local_irq_disable(); - if (intr & INTR_CFG_CHG) { - __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR); - temp = __raw_readl(imx_usb->base + USB_STAT); - cfg = (temp & STAT_CFG) >> 5; - intf = (temp & STAT_INTF) >> 3; - alt = temp & STAT_ALTSET; + temp = __raw_readl(imx_usb->base + USB_STAT); + cfg = (temp & STAT_CFG) >> 5; + intf = (temp & STAT_INTF) >> 3; + alt = temp & STAT_ALTSET; - D_REQ(imx_usb->dev, - "<%s> orig config C=%d, I=%d, A=%d / " - "req config C=%d, I=%d, A=%d\n", - __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt, - cfg, intf, alt); + D_REQ(imx_usb->dev, + "<%s> orig config C=%d, I=%d, A=%d / " + "req config C=%d, I=%d, A=%d\n", + __func__, imx_usb->cfg, imx_usb->intf, imx_usb->alt, + cfg, intf, alt); - if (cfg != 1 && cfg != 2) - goto end_irq; + if (cfg == 1 || cfg == 2) { - imx_usb->set_config = 0; - - /* Config setup */ if (imx_usb->cfg != cfg) { - D_REQ(imx_usb->dev, - "<%s> Change config start\n", __func__); u.bRequest = USB_REQ_SET_CONFIGURATION; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1085,16 +1048,10 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) u.wIndex = 0; u.wLength = 0; imx_usb->cfg = cfg; - imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); - imx_usb->set_config = 0; - D_REQ(imx_usb->dev, - "<%s> Change config done\n", __func__); } if (imx_usb->intf != intf || imx_usb->alt != alt) { - D_REQ(imx_usb->dev, - "<%s> Change interface start\n", __func__); u.bRequest = USB_REQ_SET_INTERFACE; u.bRequestType = USB_DIR_OUT | USB_TYPE_STANDARD | @@ -1104,14 +1061,30 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) u.wLength = 0; imx_usb->intf = intf; imx_usb->alt = alt; - imx_usb->set_config = 1; imx_usb->driver->setup(&imx_usb->gadget, &u); - imx_usb->set_config = 0; - D_REQ(imx_usb->dev, - "<%s> Change interface done\n", __func__); } } + imx_usb->set_config = 0; + + local_irq_enable(); +} + +static irqreturn_t imx_udc_irq(int irq, void *dev) +{ + struct imx_udc_struct *imx_usb = dev; + int intr = __raw_readl(imx_usb->base + USB_INTR); + int temp; + + if (intr & (INTR_WAKEUP | INTR_SUSPEND | INTR_RESUME | INTR_RESET_START + | INTR_RESET_STOP | INTR_CFG_CHG)) { + dump_intr(__func__, intr, imx_usb->dev); + dump_usb_stat(__func__, imx_usb); + } + + if (!imx_usb->driver) + goto end_irq; + if (intr & INTR_SOF) { /* Copy from Freescale BSP. We must enable SOF intr and set CMDOVER. @@ -1125,6 +1098,55 @@ static irqreturn_t imx_udc_irq(int irq, void *dev) } } + if (intr & INTR_CFG_CHG) { + /* A workaround of serious IMX UDC bug. + Handling of CFG_CHG should be delayed for some time, because + IMX does not NACK the host when CFG_CHG interrupt is pending. + There is no time to handle current CFG_CHG + if next CFG_CHG or SETUP packed is send immediately. + We have to clear CFG_CHG, start the timer and + NACK the host by setting CTRL_CMDOVER + if it sends any SETUP packet. + When timer expires, handler is called to handle configuration + changes. While CFG_CHG is not handled (set_config=1), + we must NACK the host to every SETUP packed. + This delay prevents from going out of sync with host. + */ + __raw_writel(INTR_CFG_CHG, imx_usb->base + USB_INTR); + imx_usb->set_config = 1; + mod_timer(&imx_usb->timer, jiffies + 5); + goto end_irq; + } + + if (intr & INTR_WAKEUP) { + if (imx_usb->gadget.speed == USB_SPEED_UNKNOWN + && imx_usb->driver && imx_usb->driver->resume) + imx_usb->driver->resume(&imx_usb->gadget); + imx_usb->set_config = 0; + del_timer(&imx_usb->timer); + imx_usb->gadget.speed = USB_SPEED_FULL; + } + + if (intr & INTR_SUSPEND) { + if (imx_usb->gadget.speed != USB_SPEED_UNKNOWN + && imx_usb->driver && imx_usb->driver->suspend) + imx_usb->driver->suspend(&imx_usb->gadget); + imx_usb->set_config = 0; + del_timer(&imx_usb->timer); + imx_usb->gadget.speed = USB_SPEED_UNKNOWN; + } + + if (intr & INTR_RESET_START) { + __raw_writel(intr, imx_usb->base + USB_INTR); + udc_stop_activity(imx_usb, imx_usb->driver); + imx_usb->set_config = 0; + del_timer(&imx_usb->timer); + imx_usb->gadget.speed = USB_SPEED_UNKNOWN; + } + + if (intr & INTR_RESET_STOP) + imx_usb->gadget.speed = USB_SPEED_FULL; + end_irq: __raw_writel(intr, imx_usb->base + USB_INTR); return IRQ_HANDLED; @@ -1342,6 +1364,7 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc_stop_activity(imx_usb, driver); imx_udc_disable(imx_usb); + del_timer(&imx_usb->timer); driver->unbind(&imx_usb->gadget); imx_usb->gadget.dev.driver = NULL; @@ -1459,6 +1482,10 @@ static int __init imx_udc_probe(struct platform_device *pdev) usb_init_data(imx_usb); imx_udc_init(imx_usb); + init_timer(&imx_usb->timer); + imx_usb->timer.function = handle_config; + imx_usb->timer.data = (unsigned long)imx_usb; + return 0; fail3: @@ -1481,6 +1508,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev) int i; imx_udc_disable(imx_usb); + del_timer(&imx_usb->timer); for (i = 0; i < IMX_USB_NB_EP + 1; i++) free_irq(imx_usb->usbd_int[i], imx_usb); diff --git a/drivers/usb/gadget/imx_udc.h b/drivers/usb/gadget/imx_udc.h index 6b0b1e3d6fc..b48ad59603d 100644 --- a/drivers/usb/gadget/imx_udc.h +++ b/drivers/usb/gadget/imx_udc.h @@ -59,6 +59,7 @@ struct imx_udc_struct { struct device *dev; struct imx_ep_struct imx_ep[IMX_USB_NB_EP]; struct clk *clk; + struct timer_list timer; enum ep0_state ep0state; struct resource *res; void __iomem *base; -- cgit v1.2.3 From 4901b2c34ecb6fc45909228ad269c8126efe4401 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Tue, 27 Jan 2009 17:21:40 +0100 Subject: USB: suspend/resume support for option driver This patch implements suspend and resume methods for the option driver. With my hardware I can even suspend the system and keep up a connection for a short time. Signed-off-by: Oliver Neukum Signed-Off-By: Matthias Urlichs Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/option.c | 86 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 80 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 61ebddc4849..d560c0b54e6 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -62,6 +62,8 @@ static int option_tiocmget(struct tty_struct *tty, struct file *file); static int option_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear); static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port); +static int option_suspend(struct usb_serial *serial, pm_message_t message); +static int option_resume(struct usb_serial *serial); /* Vendor and product IDs */ #define OPTION_VENDOR_ID 0x0AF0 @@ -523,6 +525,8 @@ static struct usb_driver option_driver = { .name = "option", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, .id_table = option_ids, .no_dynamic_id = 1, }; @@ -551,6 +555,8 @@ static struct usb_serial_driver option_1port_device = { .attach = option_startup, .shutdown = option_shutdown, .read_int_callback = option_instat_callback, + .suspend = option_suspend, + .resume = option_resume, }; static int debug; @@ -821,10 +827,10 @@ static void option_instat_callback(struct urb *urb) req_pkt->bRequestType, req_pkt->bRequest); } } else - dbg("%s: error %d", __func__, status); + err("%s: error %d", __func__, status); /* Resubmit urb so we continue receiving IRQ data */ - if (status != -ESHUTDOWN) { + if (status != -ESHUTDOWN && status != -ENOENT) { urb->dev = serial->dev; err = usb_submit_urb(urb, GFP_ATOMIC); if (err) @@ -843,7 +849,6 @@ static int option_write_room(struct tty_struct *tty) portdata = usb_get_serial_port_data(port); - for (i = 0; i < N_OUT_URB; i++) { this_urb = portdata->out_urbs[i]; if (this_urb && !test_bit(i, &portdata->out_busy)) @@ -1105,14 +1110,12 @@ bail_out_error: return 1; } -static void option_shutdown(struct usb_serial *serial) +static void stop_read_write_urbs(struct usb_serial *serial) { int i, j; struct usb_serial_port *port; struct option_port_private *portdata; - dbg("%s", __func__); - /* Stop reading/writing urbs */ for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; @@ -1122,6 +1125,17 @@ static void option_shutdown(struct usb_serial *serial) for (j = 0; j < N_OUT_URB; j++) usb_kill_urb(portdata->out_urbs[j]); } +} + +static void option_shutdown(struct usb_serial *serial) +{ + int i, j; + struct usb_serial_port *port; + struct option_port_private *portdata; + + dbg("%s", __func__); + + stop_read_write_urbs(serial); /* Now free them */ for (i = 0; i < serial->num_ports; ++i) { @@ -1152,6 +1166,66 @@ static void option_shutdown(struct usb_serial *serial) } } +static int option_suspend(struct usb_serial *serial, pm_message_t message) +{ + dbg("%s entered", __func__); + stop_read_write_urbs(serial); + + return 0; +} + +static int option_resume(struct usb_serial *serial) +{ + int err, i, j; + struct usb_serial_port *port; + struct urb *urb; + struct option_port_private *portdata; + + dbg("%s entered", __func__); + /* get the interrupt URBs resubmitted unconditionally */ + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + if (!port->interrupt_in_urb) { + dbg("%s: No interrupt URB for port %d\n", __func__, i); + continue; + } + port->interrupt_in_urb->dev = serial->dev; + err = usb_submit_urb(port->interrupt_in_urb, GFP_NOIO); + dbg("Submitted interrupt URB for port %d (result %d)", i, err); + if (err < 0) { + err("%s: Error %d for interrupt URB of port%d", + __func__, err, i); + return err; + } + } + + for (i = 0; i < serial->num_ports; i++) { + /* walk all ports */ + port = serial->port[i]; + portdata = usb_get_serial_port_data(port); + mutex_lock(&port->mutex); + + /* skip closed ports */ + if (!port->port.count) { + mutex_unlock(&port->mutex); + continue; + } + + for (j = 0; j < N_IN_URB; j++) { + urb = portdata->in_urbs[j]; + err = usb_submit_urb(urb, GFP_NOIO); + if (err < 0) { + mutex_unlock(&port->mutex); + err("%s: Error %d for bulk URB %d", + __func__, err, i); + return err; + } + } + mutex_unlock(&port->mutex); + } + return 0; +} + MODULE_AUTHOR(DRIVER_AUTHOR); MODULE_DESCRIPTION(DRIVER_DESC); MODULE_VERSION(DRIVER_VERSION); -- cgit v1.2.3 From d1c0713daea5d1d881ecc8707458ca6746031376 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 14 Jan 2009 18:34:06 +0100 Subject: USB: suspend/resume for opticon driver this does the standard support for suspend/resume for the opticon driver. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index cea326f1f10..00d5c60aded 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -306,11 +306,37 @@ static void opticon_shutdown(struct usb_serial *serial) usb_set_serial_data(serial, NULL); } +static int opticon_suspend(struct usb_interface *intf, pm_message_t message) +{ + struct usb_serial *serial = usb_get_intfdata(intf); + struct opticon_private *priv = usb_get_serial_data(serial); + + usb_kill_urb(priv->bulk_read_urb); + return 0; +} + +static int opticon_resume(struct usb_interface *intf) +{ + struct usb_serial *serial = usb_get_intfdata(intf); + struct opticon_private *priv = usb_get_serial_data(serial); + struct usb_serial_port *port = serial->port[0]; + int result; + + mutex_lock(&port->mutex); + if (port->port.count) + result = usb_submit_urb(priv->bulk_read_urb, GFP_NOIO); + else + result = 0; + mutex_unlock(&port->mutex); + return result; +} static struct usb_driver opticon_driver = { .name = "opticon", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = opticon_suspend, + .resume = opticon_resume, .id_table = id_table, .no_dynamic_id = 1, }; -- cgit v1.2.3 From 6e14bda1b18b2e3c16258427fc43ceb43e1bc1d5 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Sat, 31 Jan 2009 12:37:04 +0100 Subject: USB: count reaches -1, tested 0 With a postfix decrement count will reach -1 rather than 0, so the warning will not be issued. Signed-off-by: Roel Kluin Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/pci-quirks.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index 75b69847918..033c2846ce5 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c @@ -234,7 +234,7 @@ static void __devinit quirk_usb_disable_ehci(struct pci_dev *pdev) */ hcc_params = readl(base + EHCI_HCC_PARAMS); offset = (hcc_params >> 8) & 0xff; - while (offset && count--) { + while (offset && --count) { u32 cap; int msec; -- cgit v1.2.3 From f8bece8d91f9ed9cff3c98920802f1b3046b7560 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 5 Feb 2009 16:54:25 +0100 Subject: USB: serial: introduce a flag into the usb serial layer to tell drivers that their URBs are killed due to suspension This patch introduces a flag into the usb serial layer to tell drivers that their URBs are killed due to suspension. That is necessary to let drivers know whether they should report an error back. Signed-off-by: Oliver Neukum Hi Greg, this is for 2.6.30. Patches to use this in drivers are under development. Regards Oliver --- drivers/usb/serial/usb-serial.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index cfcfd5ab06c..c6aaa6dc756 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1067,6 +1067,8 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) struct usb_serial_port *port; int i, r = 0; + serial->suspending = 1; + for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; if (port) @@ -1084,8 +1086,10 @@ int usb_serial_resume(struct usb_interface *intf) { struct usb_serial *serial = usb_get_intfdata(intf); + serial->suspending = 0; if (serial->type->resume) return serial->type->resume(serial); + return 0; } EXPORT_SYMBOL(usb_serial_resume); -- cgit v1.2.3 From d55c0ae6b243bb8e247259089b3a2e47ebfabdf6 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Feb 2009 15:01:54 +0100 Subject: USB: serial generic resume function fix This removes an unnecessary check for autoresume from the generic resume method. The check has been obsoleted by the now delayed increase of the usage counter which makes the error this check prevented impossible. This change allows drivers which only use the bulk read URB the use of the generic method even if they support autosuspend. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 814909f1ee6..c4a47abfee6 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -177,14 +177,6 @@ int usb_serial_generic_resume(struct usb_serial *serial) struct usb_serial_port *port; int i, c = 0, r; -#ifdef CONFIG_PM - /* - * If this is an autoresume, don't submit URBs. - * They will be submitted in the open function instead. - */ - if (serial->dev->auto_pm) - return 0; -#endif for (i = 0; i < serial->num_ports; i++) { port = serial->port[i]; if (port->port.count && port->read_urb) { -- cgit v1.2.3 From 81d043c2f30b157b96cb8ef2b570d12c112e395d Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Feb 2009 15:37:14 +0100 Subject: USB: serial: export symbol of usb_serial_generic_resume This exports a symbol for usb_serial_generic_resume, so that modules can use it. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/generic.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index c4a47abfee6..9d57cace373 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c @@ -188,6 +188,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) return c ? -EIO : 0; } +EXPORT_SYMBOL_GPL(usb_serial_generic_resume); void usb_serial_generic_close(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) -- cgit v1.2.3 From c49cfa9170256295f4a0fd1668a2411fc05d6b33 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Fri, 6 Feb 2009 18:06:43 +0100 Subject: USB: serial: use generic method if no alternative is provided in usb serial layer This patch makes use of the generic method if a serial driver provides no implementation. This simplifies implementing suspend/resume support in serial drivers. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index c6aaa6dc756..18f94084731 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1085,12 +1085,15 @@ EXPORT_SYMBOL(usb_serial_suspend); int usb_serial_resume(struct usb_interface *intf) { struct usb_serial *serial = usb_get_intfdata(intf); + int rv; serial->suspending = 0; if (serial->type->resume) - return serial->type->resume(serial); + rv = serial->type->resume(serial); + else + rv = usb_serial_generic_resume(serial); - return 0; + return rv; } EXPORT_SYMBOL(usb_serial_resume); -- cgit v1.2.3 From 6f8aa65b52037123beab573432e371c0f70b7b9a Mon Sep 17 00:00:00 2001 From: Frank Seidel Date: Thu, 5 Feb 2009 16:16:24 +0100 Subject: USB: add missing KERN_* constants to printks According to kerneljanitors todo list all printk calls (beginning a new line) should have an according KERN_* constant. Those are the missing peaces here for the usb subsystem. Signed-off-by: Frank Seidel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/fsl_usb2_udc.c | 8 +++++--- drivers/usb/gadget/lh7a40x_udc.c | 16 +++++++++------- drivers/usb/host/isp116x.h | 8 ++++---- drivers/usb/storage/alauda.c | 25 ++++++++++++++++--------- drivers/usb/storage/sddr09.c | 37 ++++++++++++++++++++++--------------- drivers/usb/storage/sddr55.c | 4 +++- 6 files changed, 59 insertions(+), 39 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/fsl_usb2_udc.c b/drivers/usb/gadget/fsl_usb2_udc.c index d8d9a52a44b..9d7b95d4e3d 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.c +++ b/drivers/usb/gadget/fsl_usb2_udc.c @@ -1802,7 +1802,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) out: if (retval) - printk("gadget driver register failed %d\n", retval); + printk(KERN_WARNING "gadget driver register failed %d\n", + retval); return retval; } EXPORT_SYMBOL(usb_gadget_register_driver); @@ -1847,7 +1848,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) udc_controller->gadget.dev.driver = NULL; udc_controller->driver = NULL; - printk("unregistered gadget driver '%s'\n", driver->driver.name); + printk(KERN_WARNING "unregistered gadget driver '%s'\n", + driver->driver.name); return 0; } EXPORT_SYMBOL(usb_gadget_unregister_driver); @@ -2455,7 +2457,7 @@ module_init(udc_init); static void __exit udc_exit(void) { platform_driver_unregister(&udc_driver); - printk("%s unregistered\n", driver_desc); + printk(KERN_WARNING "%s unregistered\n", driver_desc); } module_exit(udc_exit); diff --git a/drivers/usb/gadget/lh7a40x_udc.c b/drivers/usb/gadget/lh7a40x_udc.c index d554b089560..6cd3d54f564 100644 --- a/drivers/usb/gadget/lh7a40x_udc.c +++ b/drivers/usb/gadget/lh7a40x_udc.c @@ -432,8 +432,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) device_add(&dev->gadget.dev); retval = driver->bind(&dev->gadget); if (retval) { - printk("%s: bind to driver %s --> error %d\n", dev->gadget.name, - driver->driver.name, retval); + printk(KERN_WARNING "%s: bind to driver %s --> error %d\n", + dev->gadget.name, driver->driver.name, retval); device_del(&dev->gadget.dev); dev->driver = 0; @@ -445,8 +445,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) * for set_configuration as well as eventual disconnect. * NOTE: this shouldn't power up until later. */ - printk("%s: registered gadget driver '%s'\n", dev->gadget.name, - driver->driver.name); + printk(KERN_WARNING "%s: registered gadget driver '%s'\n", + dev->gadget.name, driver->driver.name); udc_enable(dev); @@ -581,7 +581,8 @@ static int read_fifo(struct lh7a40x_ep *ep, struct lh7a40x_request *req) * discard the extra data. */ if (req->req.status != -EOVERFLOW) - printk("%s overflow %d\n", ep->ep.name, count); + printk(KERN_WARNING "%s overflow %d\n", + ep->ep.name, count); req->req.status = -EOVERFLOW; } else { *buf++ = byte; @@ -831,7 +832,8 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr) queue); if (!req) { - printk("%s: NULL REQ %d\n", + printk(KERN_WARNING + "%s: NULL REQ %d\n", __func__, ep_idx); flush(ep); break; @@ -844,7 +846,7 @@ static void lh7a40x_out_epn(struct lh7a40x_udc *dev, u32 ep_idx, u32 intr) } else { /* Throw packet away.. */ - printk("%s: No descriptor?!?\n", __func__); + printk(KERN_WARNING "%s: No descriptor?!?\n", __func__); flush(ep); } } diff --git a/drivers/usb/host/isp116x.h b/drivers/usb/host/isp116x.h index aa211bafcff..12db961acdf 100644 --- a/drivers/usb/host/isp116x.h +++ b/drivers/usb/host/isp116x.h @@ -563,7 +563,7 @@ static void urb_dbg(struct urb *urb, char *msg) */ static inline void dump_ptd(struct ptd *ptd) { - printk("td: %x %d%c%d %d,%d,%d %x %x%x%x\n", + printk(KERN_WARNING "td: %x %d%c%d %d,%d,%d %x %x%x%x\n", PTD_GET_CC(ptd), PTD_GET_FA(ptd), PTD_DIR_STR(ptd), PTD_GET_EP(ptd), PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), @@ -576,7 +576,7 @@ static inline void dump_ptd_out_data(struct ptd *ptd, u8 * buf) int k; if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) { - printk("-> "); + printk(KERN_WARNING "-> "); for (k = 0; k < PTD_GET_LEN(ptd); ++k) printk("%02x ", ((u8 *) buf)[k]); printk("\n"); @@ -588,13 +588,13 @@ static inline void dump_ptd_in_data(struct ptd *ptd, u8 * buf) int k; if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) { - printk("<- "); + printk(KERN_WARNING "<- "); for (k = 0; k < PTD_GET_COUNT(ptd); ++k) printk("%02x ", ((u8 *) buf)[k]); printk("\n"); } if (PTD_GET_LAST(ptd)) - printk("-\n"); + printk(KERN_WARNING "-\n"); } #else diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 8d3711a7ff0..5407411e30e 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -307,7 +307,8 @@ static int alauda_init_media(struct us_data *us) data[0], data[1], data[2], data[3]); media_info = alauda_card_find_id(data[1]); if (media_info == NULL) { - printk("alauda_init_media: Unrecognised media signature: " + printk(KERN_WARNING + "alauda_init_media: Unrecognised media signature: " "%02X %02X %02X %02X\n", data[0], data[1], data[2], data[3]); return USB_STOR_TRANSPORT_ERROR; @@ -518,7 +519,8 @@ static int alauda_read_map(struct us_data *us, unsigned int zone) /* check even parity */ if (parity[data[6] ^ data[7]]) { - printk("alauda_read_map: Bad parity in LBA for block %d" + printk(KERN_WARNING + "alauda_read_map: Bad parity in LBA for block %d" " (%02X %02X)\n", i, data[6], data[7]); pba_to_lba[i] = UNUSABLE; continue; @@ -538,13 +540,16 @@ static int alauda_read_map(struct us_data *us, unsigned int zone) */ if (lba_offset >= uzonesize) { - printk("alauda_read_map: Bad low LBA %d for block %d\n", + printk(KERN_WARNING + "alauda_read_map: Bad low LBA %d for block %d\n", lba_real, blocknum); continue; } if (lba_to_pba[lba_offset] != UNDEF) { - printk("alauda_read_map: LBA %d seen for PBA %d and %d\n", + printk(KERN_WARNING + "alauda_read_map: " + "LBA %d seen for PBA %d and %d\n", lba_real, lba_to_pba[lba_offset], blocknum); continue; } @@ -712,13 +717,15 @@ static int alauda_write_lba(struct us_data *us, u16 lba, if (pba == 1) { /* Maybe it is impossible to write to PBA 1. Fake success, but don't do anything. */ - printk("alauda_write_lba: avoid writing to pba 1\n"); + printk(KERN_WARNING + "alauda_write_lba: avoid writing to pba 1\n"); return USB_STOR_TRANSPORT_GOOD; } new_pba = alauda_find_unused_pba(&MEDIA_INFO(us), zone); if (!new_pba) { - printk("alauda_write_lba: Out of unused blocks\n"); + printk(KERN_WARNING + "alauda_write_lba: Out of unused blocks\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -818,7 +825,7 @@ static int alauda_read_data(struct us_data *us, unsigned long address, len = min(sectors, blocksize) * (pagesize + 64); buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("alauda_read_data: Out of memory\n"); + printk(KERN_WARNING "alauda_read_data: Out of memory\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -911,7 +918,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address, len = min(sectors, blocksize) * pagesize; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("alauda_write_data: Out of memory\n"); + printk(KERN_WARNING "alauda_write_data: Out of memory\n"); return USB_STOR_TRANSPORT_ERROR; } @@ -921,7 +928,7 @@ static int alauda_write_data(struct us_data *us, unsigned long address, */ blockbuffer = kmalloc((pagesize + 64) * blocksize, GFP_NOIO); if (blockbuffer == NULL) { - printk("alauda_write_data: Out of memory\n"); + printk(KERN_WARNING "alauda_write_data: Out of memory\n"); kfree(buffer); return USB_STOR_TRANSPORT_ERROR; } diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 531ae5c5abf..b667c7d2b83 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -723,7 +723,7 @@ sddr09_read_data(struct us_data *us, len = min(sectors, (unsigned int) info->blocksize) * info->pagesize; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("sddr09_read_data: Out of memory\n"); + printk(KERN_WARNING "sddr09_read_data: Out of memory\n"); return -ENOMEM; } @@ -838,7 +838,8 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, if (pba == UNDEF) { pba = sddr09_find_unused_pba(info, lba); if (!pba) { - printk("sddr09_write_lba: Out of unused blocks\n"); + printk(KERN_WARNING + "sddr09_write_lba: Out of unused blocks\n"); return -ENOSPC; } info->pba_to_lba[pba] = lba; @@ -849,7 +850,7 @@ sddr09_write_lba(struct us_data *us, unsigned int lba, if (pba == 1) { /* Maybe it is impossible to write to PBA 1. Fake success, but don't do anything. */ - printk("sddr09: avoid writing to pba 1\n"); + printk(KERN_WARNING "sddr09: avoid writing to pba 1\n"); return 0; } @@ -954,7 +955,7 @@ sddr09_write_data(struct us_data *us, blocklen = (pagelen << info->blockshift); blockbuffer = kmalloc(blocklen, GFP_NOIO); if (!blockbuffer) { - printk("sddr09_write_data: Out of memory\n"); + printk(KERN_WARNING "sddr09_write_data: Out of memory\n"); return -ENOMEM; } @@ -965,7 +966,7 @@ sddr09_write_data(struct us_data *us, len = min(sectors, (unsigned int) info->blocksize) * info->pagesize; buffer = kmalloc(len, GFP_NOIO); if (buffer == NULL) { - printk("sddr09_write_data: Out of memory\n"); + printk(KERN_WARNING "sddr09_write_data: Out of memory\n"); kfree(blockbuffer); return -ENOMEM; } @@ -1112,7 +1113,7 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { if (result) { US_DEBUGP("Result of read_deviceID is %d\n", result); - printk("sddr09: could not read card info\n"); + printk(KERN_WARNING "sddr09: could not read card info\n"); return NULL; } @@ -1153,7 +1154,7 @@ sddr09_get_cardinfo(struct us_data *us, unsigned char flags) { sprintf(blurbtxt + strlen(blurbtxt), ", WP"); - printk("%s\n", blurbtxt); + printk(KERN_WARNING "%s\n", blurbtxt); return cardinfo; } @@ -1184,7 +1185,7 @@ sddr09_read_map(struct us_data *us) { alloc_len = (alloc_blocks << CONTROL_SHIFT); buffer = kmalloc(alloc_len, GFP_NOIO); if (buffer == NULL) { - printk("sddr09_read_map: out of memory\n"); + printk(KERN_WARNING "sddr09_read_map: out of memory\n"); result = -1; goto done; } @@ -1198,7 +1199,7 @@ sddr09_read_map(struct us_data *us) { info->pba_to_lba = kmalloc(numblocks*sizeof(int), GFP_NOIO); if (info->lba_to_pba == NULL || info->pba_to_lba == NULL) { - printk("sddr09_read_map: out of memory\n"); + printk(KERN_WARNING "sddr09_read_map: out of memory\n"); result = -1; goto done; } @@ -1238,7 +1239,8 @@ sddr09_read_map(struct us_data *us) { if (ptr[j] != 0) goto nonz; info->pba_to_lba[i] = UNUSABLE; - printk("sddr09: PBA %d has no logical mapping\n", i); + printk(KERN_WARNING "sddr09: PBA %d has no logical mapping\n", + i); continue; nonz: @@ -1251,7 +1253,8 @@ sddr09_read_map(struct us_data *us) { nonff: /* normal PBAs start with six FFs */ if (j < 6) { - printk("sddr09: PBA %d has no logical mapping: " + printk(KERN_WARNING + "sddr09: PBA %d has no logical mapping: " "reserved area = %02X%02X%02X%02X " "data status %02X block status %02X\n", i, ptr[0], ptr[1], ptr[2], ptr[3], @@ -1261,7 +1264,8 @@ sddr09_read_map(struct us_data *us) { } if ((ptr[6] >> 4) != 0x01) { - printk("sddr09: PBA %d has invalid address field " + printk(KERN_WARNING + "sddr09: PBA %d has invalid address field " "%02X%02X/%02X%02X\n", i, ptr[6], ptr[7], ptr[11], ptr[12]); info->pba_to_lba[i] = UNUSABLE; @@ -1270,7 +1274,8 @@ sddr09_read_map(struct us_data *us) { /* check even parity */ if (parity[ptr[6] ^ ptr[7]]) { - printk("sddr09: Bad parity in LBA for block %d" + printk(KERN_WARNING + "sddr09: Bad parity in LBA for block %d" " (%02X %02X)\n", i, ptr[6], ptr[7]); info->pba_to_lba[i] = UNUSABLE; continue; @@ -1289,7 +1294,8 @@ sddr09_read_map(struct us_data *us) { */ if (lba >= 1000) { - printk("sddr09: Bad low LBA %d for block %d\n", + printk(KERN_WARNING + "sddr09: Bad low LBA %d for block %d\n", lba, i); goto possibly_erase; } @@ -1297,7 +1303,8 @@ sddr09_read_map(struct us_data *us) { lba += 1000*(i/0x400); if (info->lba_to_pba[lba] != UNDEF) { - printk("sddr09: LBA %d seen for PBA %d and %d\n", + printk(KERN_WARNING + "sddr09: LBA %d seen for PBA %d and %d\n", lba, info->lba_to_pba[lba], i); goto possibly_erase; } diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index 0d8df757789..5a0106ba256 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -703,7 +703,9 @@ static int sddr55_read_map(struct us_data *us) { if (info->lba_to_pba[lba + zone * 1000] != NOT_ALLOCATED && !info->force_read_only) { - printk("sddr55: map inconsistency at LBA %04X\n", lba + zone * 1000); + printk(KERN_WARNING + "sddr55: map inconsistency at LBA %04X\n", + lba + zone * 1000); info->force_read_only = 1; } -- cgit v1.2.3 From 5d1ca6cf7f80644b07c348d6be870ccd8e3a92ed Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 6 Feb 2009 02:39:11 -0800 Subject: USB: ftdi_sio: remove pointless syslog spew Remove some pointless messages from the FTDI serial driver; I found these filling up syslog on one system. Also remove a pointless "break" after a "return" in the same area. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d889216bcb3..adeb23fb800 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -2292,11 +2292,8 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 0, 0, buf, 1, WDR_TIMEOUT); - if (ret < 0) { - dbg("%s Could not get modem status of device - err: %d", __func__, - ret); + if (ret < 0) return ret; - } break; case FT8U232AM: case FT232BM: @@ -2311,15 +2308,11 @@ static int ftdi_tiocmget(struct tty_struct *tty, struct file *file) FTDI_SIO_GET_MODEM_STATUS_REQUEST_TYPE, 0, priv->interface, buf, 2, WDR_TIMEOUT); - if (ret < 0) { - dbg("%s Could not get modem status of device - err: %d", __func__, - ret); + if (ret < 0) return ret; - } break; default: return -EFAULT; - break; } return (buf[0] & FTDI_SIO_DSR_MASK ? TIOCM_DSR : 0) | -- cgit v1.2.3 From f6d92a05c86754d62eabc84856d2035d0de3ddc3 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Fri, 6 Feb 2009 17:32:35 +0530 Subject: USB: otg: adding nop usb transceiver NOP transceiver is used by all the usb transceiver which are mostly autonomous and doesn't require any programming or which are built into the usb ip itself.NOP transceiver only allocates the memory for struct xceiv and calls otg_set_transceiver() so function call to otg_get_transceiver() will return a valid transceiver. NOP transceiver device should be registered by calling usb_nop_xceiv_register() from platform files. Signed-off-by: Ajay Kumar Gupta Cc: Felipe Balbi Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/Kconfig | 8 ++ drivers/usb/otg/Makefile | 1 + drivers/usb/otg/nop-usb-xceiv.c | 180 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 drivers/usb/otg/nop-usb-xceiv.c (limited to 'drivers') diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index ee55b449ffd..fc1ca03ce4d 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -51,4 +51,12 @@ config TWL4030_USB This transceiver supports high and full speed devices plus, in host mode, low speed. +config NOP_USB_XCEIV + tristate "NOP USB Transceiver Driver" + select USB_OTG_UTILS + help + this driver is to be used by all the usb transceiver which are either + built-in with usb ip or which are autonomous and doesn't require any + phy programming such as ISP1x04 etc. + endif # USB || OTG diff --git a/drivers/usb/otg/Makefile b/drivers/usb/otg/Makefile index d73c7cf5e2f..20816785652 100644 --- a/drivers/usb/otg/Makefile +++ b/drivers/usb/otg/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_USB_OTG_UTILS) += otg.o obj-$(CONFIG_USB_GPIO_VBUS) += gpio_vbus.o obj-$(CONFIG_ISP1301_OMAP) += isp1301_omap.o obj-$(CONFIG_TWL4030_USB) += twl4030-usb.o +obj-$(CONFIG_NOP_USB_XCEIV) += nop-usb-xceiv.o ccflags-$(CONFIG_USB_DEBUG) += -DDEBUG ccflags-$(CONFIG_USB_GADGET_DEBUG) += -DDEBUG diff --git a/drivers/usb/otg/nop-usb-xceiv.c b/drivers/usb/otg/nop-usb-xceiv.c new file mode 100644 index 00000000000..4b933f646f2 --- /dev/null +++ b/drivers/usb/otg/nop-usb-xceiv.c @@ -0,0 +1,180 @@ +/* + * drivers/usb/otg/nop-usb-xceiv.c + * + * NOP USB transceiver for all USB transceiver which are either built-in + * into USB IP or which are mostly autonomous. + * + * Copyright (C) 2009 Texas Instruments Inc + * Author: Ajay Kumar Gupta + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Current status: + * this is to add "nop" transceiver for all those phy which is + * autonomous such as isp1504 etc. + */ + +#include +#include +#include +#include + +struct nop_usb_xceiv { + struct otg_transceiver otg; + struct device *dev; +}; + +static u64 nop_xceiv_dmamask = DMA_32BIT_MASK; + +static struct platform_device nop_xceiv_device = { + .name = "nop_usb_xceiv", + .id = -1, + .dev = { + .dma_mask = &nop_xceiv_dmamask, + .coherent_dma_mask = DMA_32BIT_MASK, + .platform_data = NULL, + }, +}; + +void usb_nop_xceiv_register(void) +{ + if (platform_device_register(&nop_xceiv_device) < 0) { + printk(KERN_ERR "Unable to register usb nop transceiver\n"); + return; + } +} + +void usb_nop_xceiv_unregister(void) +{ + platform_device_unregister(&nop_xceiv_device); +} + +static inline struct nop_usb_xceiv *xceiv_to_nop(struct otg_transceiver *x) +{ + return container_of(x, struct nop_usb_xceiv, otg); +} + +static int nop_set_suspend(struct otg_transceiver *x, int suspend) +{ + return 0; +} + +static int nop_set_peripheral(struct otg_transceiver *x, + struct usb_gadget *gadget) +{ + struct nop_usb_xceiv *nop; + + if (!x) + return -ENODEV; + + nop = xceiv_to_nop(x); + + if (!gadget) { + nop->otg.gadget = NULL; + return -ENODEV; + } + + nop->otg.gadget = gadget; + nop->otg.state = OTG_STATE_B_IDLE; + return 0; +} + +static int nop_set_host(struct otg_transceiver *x, struct usb_bus *host) +{ + struct nop_usb_xceiv *nop; + + if (!x) + return -ENODEV; + + nop = xceiv_to_nop(x); + + if (!host) { + nop->otg.host = NULL; + return -ENODEV; + } + + nop->otg.host = host; + return 0; +} + +static int __devinit nop_usb_xceiv_probe(struct platform_device *pdev) +{ + struct nop_usb_xceiv *nop; + int err; + + nop = kzalloc(sizeof *nop, GFP_KERNEL); + if (!nop) + return -ENOMEM; + + nop->dev = &pdev->dev; + nop->otg.dev = nop->dev; + nop->otg.label = "nop-xceiv"; + nop->otg.state = OTG_STATE_UNDEFINED; + nop->otg.set_host = nop_set_host; + nop->otg.set_peripheral = nop_set_peripheral; + nop->otg.set_suspend = nop_set_suspend; + + err = otg_set_transceiver(&nop->otg); + if (err) { + dev_err(&pdev->dev, "can't register transceiver, err: %d\n", + err); + goto exit; + } + + platform_set_drvdata(pdev, nop); + + return 0; +exit: + kfree(nop); + return err; +} + +static int __devexit nop_usb_xceiv_remove(struct platform_device *pdev) +{ + struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); + + otg_set_transceiver(NULL); + + platform_set_drvdata(pdev, NULL); + kfree(nop); + + return 0; +} + +static struct platform_driver nop_usb_xceiv_driver = { + .probe = nop_usb_xceiv_probe, + .remove = __devexit_p(nop_usb_xceiv_remove), + .driver = { + .name = "nop_usb_xceiv", + .owner = THIS_MODULE, + }, +}; + +static int __init nop_usb_xceiv_init(void) +{ + return platform_driver_register(&nop_usb_xceiv_driver); +} +subsys_initcall(nop_usb_xceiv_init); + +static void __exit nop_usb_xceiv_exit(void) +{ + platform_driver_unregister(&nop_usb_xceiv_driver); +} +module_exit(nop_usb_xceiv_exit); + +MODULE_ALIAS("platform:nop_usb_xceiv"); +MODULE_AUTHOR("Texas Instruments Inc"); +MODULE_DESCRIPTION("NOP USB Transceiver driver"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 648d4e16567eae4c643bd2125e91128f06c0d3ad Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 6 Feb 2009 18:30:56 -0800 Subject: USB: serial: opticon: add write support This patch allows data to be sent to the scanner. Cc: Kees Stoop Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 124 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 122 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 00d5c60aded..8c87a49ee2b 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -1,8 +1,8 @@ /* * Opticon USB barcode to serial driver * - * Copyright (C) 2008 Greg Kroah-Hartman - * Copyright (C) 2008 Novell Inc. + * Copyright (C) 2008 - 2009 Greg Kroah-Hartman + * Copyright (C) 2008 - 2009 Novell Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version @@ -40,8 +40,12 @@ struct opticon_private { bool throttled; bool actually_throttled; bool rts; + int outstanding_urbs; }; +/* max number of write urbs in flight */ +#define URB_UPPER_LIMIT 4 + static void opticon_bulk_callback(struct urb *urb) { struct opticon_private *priv = urb->context; @@ -188,6 +192,120 @@ static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port, usb_kill_urb(priv->bulk_read_urb); } +static void opticon_write_bulk_callback(struct urb *urb) +{ + struct opticon_private *priv = urb->context; + int status = urb->status; + unsigned long flags; + + /* free up the transfer buffer, as usb_free_urb() does not do this */ + kfree(urb->transfer_buffer); + + if (status) + dbg("%s - nonzero write bulk status received: %d", + __func__, status); + + spin_lock_irqsave(&priv->lock, flags); + --priv->outstanding_urbs; + spin_unlock_irqrestore(&priv->lock, flags); + + usb_serial_port_softint(priv->port); +} + +static int opticon_write(struct tty_struct *tty, struct usb_serial_port *port, + const unsigned char *buf, int count) +{ + struct opticon_private *priv = usb_get_serial_data(port->serial); + struct usb_serial *serial = port->serial; + struct urb *urb; + unsigned char *buffer; + unsigned long flags; + int status; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + if (priv->outstanding_urbs > URB_UPPER_LIMIT) { + spin_unlock_irqrestore(&priv->lock, flags); + dbg("%s - write limit hit\n", __func__); + return 0; + } + priv->outstanding_urbs++; + spin_unlock_irqrestore(&priv->lock, flags); + + buffer = kmalloc(count, GFP_ATOMIC); + if (!buffer) { + dev_err(&port->dev, "out of memory\n"); + count = -ENOMEM; + goto error_no_buffer; + } + + urb = usb_alloc_urb(0, GFP_ATOMIC); + if (!urb) { + dev_err(&port->dev, "no more free urbs\n"); + count = -ENOMEM; + goto error_no_urb; + } + + memcpy(buffer, buf, count); + + usb_serial_debug_data(debug, &port->dev, __func__, count, buffer); + + usb_fill_bulk_urb(urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + buffer, count, opticon_write_bulk_callback, priv); + + /* send it down the pipe */ + status = usb_submit_urb(urb, GFP_ATOMIC); + if (status) { + dev_err(&port->dev, + "%s - usb_submit_urb(write bulk) failed with status = %d\n", + __func__, status); + count = status; + goto error; + } + + /* we are done with this urb, so let the host driver + * really free it when it is finished with it */ + usb_free_urb(urb); + + return count; +error: + usb_free_urb(urb); +error_no_urb: + kfree(buffer); +error_no_buffer: + spin_lock_irqsave(&priv->lock, flags); + --priv->outstanding_urbs; + spin_unlock_irqrestore(&priv->lock, flags); + return count; +} + +static int opticon_write_room(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct opticon_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + + dbg("%s - port %d", __func__, port->number); + + /* + * We really can take almost anything the user throws at us + * but let's pick a nice big number to tell the tty + * layer that we have lots of free space, unless we don't. + */ + spin_lock_irqsave(&priv->lock, flags); + if (priv->outstanding_urbs > URB_UPPER_LIMIT * 2 / 3) { + spin_unlock_irqrestore(&priv->lock, flags); + dbg("%s - write limit hit\n", __func__); + return 0; + } + spin_unlock_irqrestore(&priv->lock, flags); + + return 2048; +} + static void opticon_throttle(struct tty_struct *tty) { struct usb_serial_port *port = tty->driver_data; @@ -352,6 +470,8 @@ static struct usb_serial_driver opticon_device = { .attach = opticon_startup, .open = opticon_open, .close = opticon_close, + .write = opticon_write, + .write_room = opticon_write_room, .shutdown = opticon_shutdown, .throttle = opticon_throttle, .unthrottle = opticon_unthrottle, -- cgit v1.2.3 From faac64ad9c7b1aa56a10be6b5f9b813789e81dfd Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 6 Feb 2009 18:31:46 -0800 Subject: USB: serial: opticon: add serial line ioctls This lets userspace determine what the state of the RTS line is, which is what is needed to properly handle data flow for this device (it raises RTS when there is data to be sent from it.) Cc: Kees Stoop Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/opticon.c | 65 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 8c87a49ee2b..839583dc8b6 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -110,7 +111,6 @@ static void opticon_bulk_callback(struct urb *urb) priv->rts = false; else priv->rts = true; - /* FIXME change the RTS level */ } else { dev_dbg(&priv->udev->dev, "Unknown data packet received from the device:" @@ -341,6 +341,67 @@ static void opticon_unthrottle(struct tty_struct *tty) __func__, result); } +static int opticon_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + struct opticon_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + int result = 0; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + if (priv->rts) + result = TIOCM_RTS; + spin_unlock_irqrestore(&priv->lock, flags); + + dbg("%s - %x", __func__, result); + return result; +} + +static int get_serial_info(struct opticon_private *priv, + struct serial_struct __user *serial) +{ + struct serial_struct tmp; + + if (!serial) + return -EFAULT; + + memset(&tmp, 0x00, sizeof(tmp)); + + /* fake emulate a 16550 uart to make userspace code happy */ + tmp.type = PORT_16550A; + tmp.line = priv->serial->minor; + tmp.port = 0; + tmp.irq = 0; + tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ; + tmp.xmit_fifo_size = 1024; + tmp.baud_base = 9600; + tmp.close_delay = 5*HZ; + tmp.closing_wait = 30*HZ; + + if (copy_to_user(serial, &tmp, sizeof(*serial))) + return -EFAULT; + return 0; +} + +static int opticon_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + struct opticon_private *priv = usb_get_serial_data(port->serial); + + dbg("%s - port %d, cmd = 0x%x", __func__, port->number, cmd); + + switch (cmd) { + case TIOCGSERIAL: + return get_serial_info(priv, + (struct serial_struct __user *)arg); + } + + return -ENOIOCTLCMD; +} + static int opticon_startup(struct usb_serial *serial) { struct opticon_private *priv; @@ -475,6 +536,8 @@ static struct usb_serial_driver opticon_device = { .shutdown = opticon_shutdown, .throttle = opticon_throttle, .unthrottle = opticon_unthrottle, + .ioctl = opticon_ioctl, + .tiocmget = opticon_tiocmget, }; static int __init opticon_init(void) -- cgit v1.2.3 From 0eb526b96ced3759e7d4445fc55204f314e33d8c Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sat, 7 Feb 2009 20:20:42 +0100 Subject: usb_storage: make Kconfig note visible in the console Make lines about usb_storage depending on SCSI visible when configuring the kernel in a 80x25 console Signed-off-by: Borislav Petkov Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 9df6887b91f..5c367566be8 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -2,8 +2,8 @@ # USB Storage driver configuration # -comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may also be needed;" -comment "see USB_STORAGE Help for more information" +comment "NOTE: USB_STORAGE depends on SCSI but BLK_DEV_SD may" +comment "also be needed; see USB_STORAGE Help for more info" depends on USB config USB_STORAGE -- cgit v1.2.3 From a5f5ea230d70f5dde4d787208855fa3c3cd7b31e Mon Sep 17 00:00:00 2001 From: Matt Kraai Date: Fri, 6 Feb 2009 19:38:51 -0800 Subject: USB: skeleton: Use dev_info instead of info 338b67b0c1a97ca705023a8189cf41aa0828d294 removed the info macro and replaced its uses with dev_info. This patch does so for usb-skeleton.c, which was missed. Signed-off-by: Matt Kraai Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usb-skeleton.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/usb-skeleton.c b/drivers/usb/usb-skeleton.c index be76084c8d7..60ba631e99c 100644 --- a/drivers/usb/usb-skeleton.c +++ b/drivers/usb/usb-skeleton.c @@ -410,7 +410,9 @@ static int skel_probe(struct usb_interface *interface, const struct usb_device_i } /* let the user know what node this device is now attached to */ - info("USB Skeleton device now attached to USBSkel-%d", interface->minor); + dev_info(&interface->dev, + "USB Skeleton device now attached to USBSkel-%d", + interface->minor); return 0; error: @@ -441,7 +443,7 @@ static void skel_disconnect(struct usb_interface *interface) /* decrement our usage count */ kref_put(&dev->kref, skel_delete); - info("USB Skeleton #%d now disconnected", minor); + dev_info(&interface->dev, "USB Skeleton #%d now disconnected", minor); } static void skel_draw_down(struct usb_skel *dev) -- cgit v1.2.3 From 1c27ae671e6b465e04544450276c88f4dba8de60 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 9 Feb 2009 10:03:49 +0100 Subject: USB: serial: remove recourse to generic method This removes the fallback to the generic method. It is cleaner to explicitely request it. Introducing this was my mistake. This will be solved by an explicit test and the driver being allowed to request what it needs to be done upon resumption. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 18f94084731..9a2617845df 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1229,7 +1229,6 @@ static void fixup_generic(struct usb_serial_driver *device) set_to_generic_if_null(device, read_bulk_callback); set_to_generic_if_null(device, write_bulk_callback); set_to_generic_if_null(device, shutdown); - set_to_generic_if_null(device, resume); } int usb_serial_register(struct usb_serial_driver *driver) -- cgit v1.2.3 From 331879fd6f584d60327ba802616d41bfa636b873 Mon Sep 17 00:00:00 2001 From: James Woodcock Date: Wed, 11 Feb 2009 15:06:53 +0000 Subject: USB: serial: refuse to open recently removed USB Serial devices A USB-serial converter device is plugged into a system, and a process opens it's device node. If the device is physically removed whilst the process still has its device node open, then other processes can sucessfully open the now non-existent device's node. I would expect that open() on a device that has been physically removed should return ENODEV. This is manifesting itself with getty on my system. I do the following: 1. set up inittab to spawn getty on ttyUSB0, eg: T1:23:respawn:/sbin/getty -L ttyUSB0 115200 vt100 2. Plug in USB-serial converter cable 3. Wait for a login prompt on a terminal program attached to the serial cable 4. Login 5. Pull the USB-serial converter cable from the box 6. getty doesn't realise that ttyUSB0 no longer exists as /dev/ttyUSB0 can still be opened. 7. Re-insert the USB-serial converter cable 8. You should no longer get a login prompt over the serial cable, as the the USB-serial cable now shows up as /dev/ttyUSB1, and getty is trying to talk to /dev/ttyUSB0. The attached patch will cause open("/dev/ttyUSB0", O_RDONLY) to return ENODEV after the USB-serial converter has been pulled. The patch was created against 2.6.28.1. I can supply it against something else if needs be. It is fairly simple, so should be OK. I am using a pl2303 device, although I don't think that makes any difference. From: James Woodcock Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 9a2617845df..73172898ccb 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -204,6 +204,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp) goto bailout_kref_put; } + if (port->serial->disconnected) { + retval = -ENODEV; + goto bailout_kref_put; + } + if (mutex_lock_interruptible(&port->mutex)) { retval = -ERESTARTSYS; goto bailout_kref_put; -- cgit v1.2.3 From b967c88ed1b48bc353ea83e0cacb2249a3bb1a51 Mon Sep 17 00:00:00 2001 From: Thierry Vignaud Date: Wed, 11 Feb 2009 13:31:05 -0800 Subject: usb: kill prehistorical comments about USB_EHCI_HCD Remove old comments about USB_EHCI_HCD. Cc: Alan Stern Signed-off-by: Andrew Morton Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/Kconfig | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index 2c63bfb1f8d..c1cfed7eefb 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -24,10 +24,7 @@ config USB_EHCI_HCD The Enhanced Host Controller Interface (EHCI) is standard for USB 2.0 "high speed" (480 Mbit/sec, 60 Mbyte/sec) host controller hardware. If your USB host controller supports USB 2.0, you will likely want to - configure this Host Controller Driver. At the time of this writing, - the primary implementation of EHCI is a chip from NEC, widely available - in add-on PCI cards, but implementations are in the works from other - vendors including Intel and Philips. Motherboard support is appearing. + configure this Host Controller Driver. EHCI controllers are packaged with "companion" host controllers (OHCI or UHCI) to handle USB 1.1 devices connected to root hub ports. Ports -- cgit v1.2.3 From bc29847e16cb6b571157220ec9b20a7d86e58046 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 11 Feb 2009 14:26:38 -0500 Subject: USB: EHCI: Make timer_action out-of-line This patch (as1205) moves timer_action() from ehci.h to ehci-hcd.c and makes it out-of-line. Over the years it has grown too big to be inline any more. Signed-off-by: Alan Stern Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-hcd.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 34 ---------------------------------- 2 files changed, 36 insertions(+), 34 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index e551bb38852..f2618d17710 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c @@ -110,6 +110,42 @@ MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); /*-------------------------------------------------------------------------*/ +static void +timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action) +{ + /* Don't override timeouts which shrink or (later) disable + * the async ring; just the I/O watchdog. Note that if a + * SHRINK were pending, OFF would never be requested. + */ + if (timer_pending(&ehci->watchdog) + && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) + & ehci->actions)) + return; + + if (!test_and_set_bit(action, &ehci->actions)) { + unsigned long t; + + switch (action) { + case TIMER_IO_WATCHDOG: + t = EHCI_IO_JIFFIES; + break; + case TIMER_ASYNC_OFF: + t = EHCI_ASYNC_JIFFIES; + break; + /* case TIMER_ASYNC_SHRINK: */ + default: + /* add a jiffie since we synch against the + * 8 KHz uframe counter. + */ + t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; + break; + } + mod_timer(&ehci->watchdog, t + jiffies); + } +} + +/*-------------------------------------------------------------------------*/ + /* * handshake - spin reading hc until handshake completes or fails * @ptr: address of hc register to be read diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 262b00c9b33..0042deb671d 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -190,40 +190,6 @@ timer_action_done (struct ehci_hcd *ehci, enum ehci_timer_action action) clear_bit (action, &ehci->actions); } -static inline void -timer_action (struct ehci_hcd *ehci, enum ehci_timer_action action) -{ - /* Don't override timeouts which shrink or (later) disable - * the async ring; just the I/O watchdog. Note that if a - * SHRINK were pending, OFF would never be requested. - */ - if (timer_pending(&ehci->watchdog) - && ((BIT(TIMER_ASYNC_SHRINK) | BIT(TIMER_ASYNC_OFF)) - & ehci->actions)) - return; - - if (!test_and_set_bit (action, &ehci->actions)) { - unsigned long t; - - switch (action) { - case TIMER_IO_WATCHDOG: - t = EHCI_IO_JIFFIES; - break; - case TIMER_ASYNC_OFF: - t = EHCI_ASYNC_JIFFIES; - break; - // case TIMER_ASYNC_SHRINK: - default: - /* add a jiffie since we synch against the - * 8 KHz uframe counter. - */ - t = DIV_ROUND_UP(EHCI_SHRINK_FRAMES * HZ, 1000) + 1; - break; - } - mod_timer(&ehci->watchdog, t + jiffies); - } -} - static void free_cached_itd_list(struct ehci_hcd *ehci); /*-------------------------------------------------------------------------*/ -- cgit v1.2.3 From 1f4159c1620f74377e26d8a569d10ca5907ef475 Mon Sep 17 00:00:00 2001 From: Boaz Harrosh Date: Wed, 11 Feb 2009 09:54:31 +0200 Subject: USB: fix USB_STORAGE_CYPRESS_ATACB commit 64a87b24: [SCSI] Let scsi_cmnd->cmnd use request->cmd buffer changed the scsi_eh_prep_cmnd logic by making it clear the ->cmnd buffer. But the sat to cypress atacb translation supposed the ->cmnd buffer wasn't modified. This patch makes it set the ->cmnd buffer after scsi_eh_prep_cmnd call. The problem and a fix was reported by Matthieu CASTET It also removes all the hackery fiddling of scsi_cmnd and scsi_eh_save by requesting from scsi_eh_prep_cmnd to prepare a read into ->sense_buffer, which is much more suitable a buffer for HW transfers, then after the command execution the regs read is copied into regs buffer before actual preparation of sense_buffer. Also fix an alien comment character to my utf-8 editor. Signed-off-by: Boaz Harrosh Signed-off-by: Matthieu CASTET Cc: stable Cc: James Bottomley Cc: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/cypress_atacb.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 898e67d30e5..9466a99baab 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -133,19 +133,18 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) /* build the command for * reading the ATA registers */ - scsi_eh_prep_cmnd(srb, &ses, NULL, 0, 0); - srb->sdb.length = sizeof(regs); - sg_init_one(&ses.sense_sgl, regs, srb->sdb.length); - srb->sdb.table.sgl = &ses.sense_sgl; - srb->sc_data_direction = DMA_FROM_DEVICE; - srb->sdb.table.nents = 1; + scsi_eh_prep_cmnd(srb, &ses, NULL, 0, sizeof(regs)); + /* we use the same command as before, but we set * the read taskfile bit, for not executing atacb command, * but reading register selected in srb->cmnd[4] */ + srb->cmd_len = 16; + srb->cmnd = ses.cmnd; srb->cmnd[2] = 1; usb_stor_transparent_scsi_command(srb, us); + memcpy(regs, srb->sense_buffer, sizeof(regs)); tmp_result = srb->result; scsi_eh_restore_cmnd(srb, &ses); /* we fail to get registers, report invalid command */ @@ -162,8 +161,8 @@ void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) /* XXX we should generate sk, asc, ascq from status and error * regs - * (see 11.1 Error translation ­ ATA device error to SCSI error map) - * and ata_to_sense_error from libata. + * (see 11.1 Error translation ATA device error to SCSI error + * map, and ata_to_sense_error from libata.) */ /* Sense data is current and format is descriptor. */ -- cgit v1.2.3 From a2c2706e1043c17139c2dafd171c4a5cf008ef7e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 10 Feb 2009 10:16:58 -0500 Subject: USB: EHCI: add software retry for transaction errors This patch (as1204) adds a software retry mechanism to ehci-hcd. It gets invoked when the driver encounters transaction errors on an asynchronous endpoint. On many systems, hardware deficiencies cause such errors to occur if one device is unplugged while the host is communicating with another device. With the patch, the failed transactions are retried and generally succeed the second or third time through. This is based on code originally written by Koichiro Saito. Signed-off-by: Alan Stern Tested by: Koichiro Saito CC: David Brownell Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 32 ++++++++++++++++++++++++++++++++ drivers/usb/host/ehci.h | 3 +++ 2 files changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index ecc9b66c03c..01132ac74eb 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -333,12 +333,40 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) token = hc32_to_cpu(ehci, qtd->hw_token); /* always clean up qtds the hc de-activated */ + retry_xacterr: if ((token & QTD_STS_ACTIVE) == 0) { /* on STALL, error, and short reads this urb must * complete and all its qtds must be recycled. */ if ((token & QTD_STS_HALT) != 0) { + + /* retry transaction errors until we + * reach the software xacterr limit + */ + if ((token & QTD_STS_XACT) && + QTD_CERR(token) == 0 && + --qh->xacterrs > 0 && + !urb->unlinked) { + ehci_dbg(ehci, + "detected XactErr len %d/%d retry %d\n", + qtd->length - QTD_LENGTH(token), qtd->length, + QH_XACTERR_MAX - qh->xacterrs); + + /* reset the token in the qtd and the + * qh overlay (which still contains + * the qtd) so that we pick up from + * where we left off + */ + token &= ~QTD_STS_HALT; + token |= QTD_STS_ACTIVE | + (EHCI_TUNE_CERR << 10); + qtd->hw_token = cpu_to_hc32(ehci, + token); + wmb(); + qh->hw_token = cpu_to_hc32(ehci, token); + goto retry_xacterr; + } stopped = 1; /* magic dummy for some short reads; qh won't advance. @@ -421,6 +449,9 @@ halt: /* remove qtd; it's recycled after possible urb completion */ list_del (&qtd->qtd_list); last = qtd; + + /* reinit the xacterr counter for the next qtd */ + qh->xacterrs = QH_XACTERR_MAX; } /* last urb's completion might still need calling */ @@ -862,6 +893,7 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) head->qh_next.qh = qh; head->hw_next = dma; + qh->xacterrs = QH_XACTERR_MAX; qh->qh_state = QH_STATE_LINKED; /* qtd completions reported later by interrupt */ } diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 0042deb671d..9aba560fd56 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -342,6 +342,9 @@ struct ehci_qh { #define QH_STATE_UNLINK_WAIT 4 /* LINKED and on reclaim q */ #define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ + u8 xacterrs; /* XactErr retry counter */ +#define QH_XACTERR_MAX 32 /* XactErr retry limit */ + /* periodic schedule info */ u8 usecs; /* intr bandwidth */ u8 gap_uf; /* uframes split/csplit gap */ -- cgit v1.2.3 From f9031f2c4237abfe75d9ad33f5c0f0dde96f7d09 Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 10 Feb 2009 16:55:45 +0000 Subject: USB: Make the isp1760_register function prototype more generic The patch changes the prototype of the isp1760_register() function to use predefined types like phys_addr_t and resource_size_t rather than u64 Signed-off-by: Catalin Marinas Cc: Sebastian Siewior Cc: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 7 ++++--- drivers/usb/host/isp1760-hcd.h | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index b899f1a59c2..8ee2f415984 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -2235,9 +2235,10 @@ void deinit_kmem_cache(void) kmem_cache_destroy(qh_cachep); } -struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, - u64 irqflags, struct device *dev, const char *busname, - unsigned int devflags) +struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, + int irq, unsigned long irqflags, + struct device *dev, const char *busname, + unsigned int devflags) { struct usb_hcd *hcd; struct isp1760_hcd *priv; diff --git a/drivers/usb/host/isp1760-hcd.h b/drivers/usb/host/isp1760-hcd.h index a9daea58796..462f4943cb1 100644 --- a/drivers/usb/host/isp1760-hcd.h +++ b/drivers/usb/host/isp1760-hcd.h @@ -2,9 +2,10 @@ #define _ISP1760_HCD_H_ /* exports for if */ -struct usb_hcd *isp1760_register(u64 res_start, u64 res_len, int irq, - u64 irqflags, struct device *dev, const char *busname, - unsigned int devflags); +struct usb_hcd *isp1760_register(phys_addr_t res_start, resource_size_t res_len, + int irq, unsigned long irqflags, + struct device *dev, const char *busname, + unsigned int devflags); int init_kmem_once(void); void deinit_kmem_cache(void); -- cgit v1.2.3 From f7e7aa5850839faa5eb7c7c177da5fd6bca8949b Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Tue, 10 Feb 2009 16:55:51 +0000 Subject: USB: Add platform device support for the ISP1760 USB chip Currently, the driver only supports PCI and PPC_OF but there are boards like ARM RealView where this is a platform device. The patch adds the necessary functions and registration to the isp1760-if.c file and modifies the corresponding Makefile and Kconfig to be able to use this driver even if PCI and PPC_OF are not enabled. Signed-off-by: Catalin Marinas Cc: Sebastian Siewior Cc: Russell King Signed-off-by: Greg Kroah-Hartman --- drivers/usb/Makefile | 1 + drivers/usb/host/Kconfig | 2 +- drivers/usb/host/isp1760-if.c | 95 +++++++++++++++++++++++++++++++++++-------- 3 files changed, 81 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index b2ceb4aff23..89299a5ce16 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile @@ -19,6 +19,7 @@ obj-$(CONFIG_USB_SL811_HCD) += host/ obj-$(CONFIG_USB_U132_HCD) += host/ obj-$(CONFIG_USB_R8A66597_HCD) += host/ obj-$(CONFIG_USB_HWA_HCD) += host/ +obj-$(CONFIG_USB_ISP1760_HCD) += host/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/ diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index c1cfed7eefb..845479f7c70 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig @@ -120,7 +120,7 @@ config USB_ISP116X_HCD config USB_ISP1760_HCD tristate "ISP 1760 HCD support" - depends on USB && EXPERIMENTAL && (PCI || PPC_OF) + depends on USB && EXPERIMENTAL ---help--- The ISP1760 chip is a USB 2.0 host controller. diff --git a/drivers/usb/host/isp1760-if.c b/drivers/usb/host/isp1760-if.c index 4cf7ca428b3..3fa3a170279 100644 --- a/drivers/usb/host/isp1760-if.c +++ b/drivers/usb/host/isp1760-if.c @@ -10,6 +10,7 @@ #include #include +#include #include "../core/hcd.h" #include "isp1760-hcd.h" @@ -300,39 +301,101 @@ static struct pci_driver isp1761_pci_driver = { }; #endif +static int __devinit isp1760_plat_probe(struct platform_device *pdev) +{ + int ret = 0; + struct usb_hcd *hcd; + struct resource *mem_res; + struct resource *irq_res; + resource_size_t mem_size; + unsigned long irqflags = IRQF_SHARED | IRQF_DISABLED; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!mem_res) { + pr_warning("isp1760: Memory resource not available\n"); + ret = -ENODEV; + goto out; + } + mem_size = resource_size(mem_res); + if (!request_mem_region(mem_res->start, mem_size, "isp1760")) { + pr_warning("isp1760: Cannot reserve the memory resource\n"); + ret = -EBUSY; + goto out; + } + + irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (!irq_res) { + pr_warning("isp1760: IRQ resource not available\n"); + return -ENODEV; + } + irqflags |= irq_res->flags & IRQF_TRIGGER_MASK; + + hcd = isp1760_register(mem_res->start, mem_size, irq_res->start, + irqflags, &pdev->dev, dev_name(&pdev->dev), 0); + if (IS_ERR(hcd)) { + pr_warning("isp1760: Failed to register the HCD device\n"); + ret = -ENODEV; + goto cleanup; + } + + pr_info("ISP1760 USB device initialised\n"); + return ret; + +cleanup: + release_mem_region(mem_res->start, mem_size); +out: + return ret; +} + +static int __devexit isp1760_plat_remove(struct platform_device *pdev) +{ + struct resource *mem_res; + resource_size_t mem_size; + + mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + mem_size = resource_size(mem_res); + release_mem_region(mem_res->start, mem_size); + + return 0; +} + +static struct platform_driver isp1760_plat_driver = { + .probe = isp1760_plat_probe, + .remove = isp1760_plat_remove, + .driver = { + .name = "isp1760", + }, +}; + static int __init isp1760_init(void) { - int ret; + int ret, any_ret = -ENODEV; init_kmem_once(); + ret = platform_driver_register(&isp1760_plat_driver); + if (!ret) + any_ret = 0; #ifdef CONFIG_PPC_OF ret = of_register_platform_driver(&isp1760_of_driver); - if (ret) { - deinit_kmem_cache(); - return ret; - } + if (!ret) + any_ret = 0; #endif #ifdef CONFIG_PCI ret = pci_register_driver(&isp1761_pci_driver); - if (ret) - goto unreg_of; + if (!ret) + any_ret = 0; #endif - return ret; -#ifdef CONFIG_PCI -unreg_of: -#endif -#ifdef CONFIG_PPC_OF - of_unregister_platform_driver(&isp1760_of_driver); -#endif - deinit_kmem_cache(); - return ret; + if (any_ret) + deinit_kmem_cache(); + return any_ret; } module_init(isp1760_init); static void __exit isp1760_exit(void) { + platform_driver_unregister(&isp1760_plat_driver); #ifdef CONFIG_PPC_OF of_unregister_platform_driver(&isp1760_of_driver); #endif -- cgit v1.2.3 From 68b44eaed5def7b6490c23c3e88c6f2ccec57beb Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 13 Feb 2009 17:25:46 -0800 Subject: USB: serial: add symbol serial driver This is for the Symbol 6608 barcode scanner in a fake "HID" mode. Thanks to Dalibor Grgec for working with me to get this to start to work properly. Cc: Dalibor Grgec Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 9 + drivers/usb/serial/Makefile | 1 + drivers/usb/serial/symbolserial.c | 340 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 350 insertions(+) create mode 100644 drivers/usb/serial/symbolserial.c (limited to 'drivers') diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index b361f05cafa..dbc0781a416 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -515,6 +515,15 @@ config USB_SERIAL_SIERRAWIRELESS To compile this driver as a module, choose M here: the module will be called sierra. +config USB_SERIAL_SYMBOL + tristate "USB Symbol Barcode driver (serial mode)" + help + Say Y here if you want to use a Symbol USB Barcode device + in serial emulation mode. + + To compile this driver as a module, choose M here: the + module will be called symbolserial. + config USB_SERIAL_TI tristate "USB TI 3410/5052 Serial Driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index b75be91eb8f..222939739ff 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o obj-$(CONFIG_USB_SERIAL_SPCP8X5) += spcp8x5.o +obj-$(CONFIG_USB_SERIAL_SYMBOL) += symbolserial.o obj-$(CONFIG_USB_SERIAL_TI) += ti_usb_3410_5052.o obj-$(CONFIG_USB_SERIAL_VISOR) += visor.o obj-$(CONFIG_USB_SERIAL_WHITEHEAT) += whiteheat.o diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c new file mode 100644 index 00000000000..c5990fd88e2 --- /dev/null +++ b/drivers/usb/serial/symbolserial.c @@ -0,0 +1,340 @@ +/* + * Symbol USB barcode to serial driver + * + * Copyright (C) 2009 Greg Kroah-Hartman + * Copyright (C) 2009 Novell Inc. + * + * 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 + +static int debug; + +static struct usb_device_id id_table[] = { + { USB_DEVICE(0x05e0, 0x0600) }, + { }, +}; +MODULE_DEVICE_TABLE(usb, id_table); + +/* This structure holds all of the individual device information */ +struct symbol_private { + struct usb_device *udev; + struct usb_serial *serial; + struct usb_serial_port *port; + unsigned char *int_buffer; + struct urb *int_urb; + int buffer_size; + u8 bInterval; + u8 int_address; + spinlock_t lock; /* protects the following flags */ + bool throttled; + bool actually_throttled; + bool rts; +}; + +static void symbol_int_callback(struct urb *urb) +{ + struct symbol_private *priv = urb->context; + unsigned char *data = urb->transfer_buffer; + struct usb_serial_port *port = priv->port; + int status = urb->status; + struct tty_struct *tty; + int result; + int available_room = 0; + int data_length; + + dbg("%s - port %d", __func__, port->number); + + switch (status) { + case 0: + /* success */ + break; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __func__, status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __func__, status); + goto exit; + } + + usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, + data); + + if (urb->actual_length > 1) { + data_length = urb->actual_length - 1; + + /* + * Data from the device comes with a 1 byte header: + * + * data... + * This is real data to be sent to the tty layer + * we pretty much just ignore the size and send everything + * else to the tty layer. + */ + tty = tty_port_tty_get(&port->port); + if (tty) { + available_room = tty_buffer_request_room(tty, + data_length); + if (available_room) { + tty_insert_flip_string(tty, &data[1], + available_room); + tty_flip_buffer_push(tty); + } + tty_kref_put(tty); + } + } else { + dev_dbg(&priv->udev->dev, + "Improper ammount of data received from the device, " + "%d bytes", urb->actual_length); + } + +exit: + spin_lock(&priv->lock); + + /* Continue trying to always read if we should */ + if (!priv->throttled) { + usb_fill_int_urb(priv->int_urb, priv->udev, + usb_rcvintpipe(priv->udev, + priv->int_address), + priv->int_buffer, priv->buffer_size, + symbol_int_callback, priv, priv->bInterval); + result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); + if (result) + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); + } else + priv->actually_throttled = true; + spin_unlock(&priv->lock); +} + +static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct symbol_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + int result = 0; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = false; + priv->actually_throttled = false; + priv->port = port; + spin_unlock_irqrestore(&priv->lock, flags); + + /* + * Force low_latency on so that our tty_push actually forces the data + * through, otherwise it is scheduled, and with high data rates (like + * with OHCI) data can get lost. + */ + if (tty) + tty->low_latency = 1; + + /* Start reading from the device */ + usb_fill_int_urb(priv->int_urb, priv->udev, + usb_rcvintpipe(priv->udev, priv->int_address), + priv->int_buffer, priv->buffer_size, + symbol_int_callback, priv, priv->bInterval); + result = usb_submit_urb(priv->int_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, + "%s - failed resubmitting read urb, error %d\n", + __func__, result); + return result; +} + +static void symbol_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct symbol_private *priv = usb_get_serial_data(port->serial); + + dbg("%s - port %d", __func__, port->number); + + /* shutdown our urbs */ + usb_kill_urb(priv->int_urb); +} + +static void symbol_throttle(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct symbol_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + + dbg("%s - port %d", __func__, port->number); + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = true; + spin_unlock_irqrestore(&priv->lock, flags); +} + +static void symbol_unthrottle(struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + struct symbol_private *priv = usb_get_serial_data(port->serial); + unsigned long flags; + int result; + + dbg("%s - port %d", __func__, port->number); + + spin_lock_irqsave(&priv->lock, flags); + priv->throttled = false; + priv->actually_throttled = false; + spin_unlock_irqrestore(&priv->lock, flags); + + priv->int_urb->dev = port->serial->dev; + result = usb_submit_urb(priv->int_urb, GFP_ATOMIC); + if (result) + dev_err(&port->dev, + "%s - failed submitting read urb, error %d\n", + __func__, result); +} + +static int symbol_startup(struct usb_serial *serial) +{ + struct symbol_private *priv; + struct usb_host_interface *intf; + int i; + int retval = -ENOMEM; + bool int_in_found = false; + + /* create our private serial structure */ + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (priv == NULL) { + dev_err(&serial->dev->dev, "%s - Out of memory\n", __func__); + return -ENOMEM; + } + spin_lock_init(&priv->lock); + priv->serial = serial; + priv->port = serial->port[0]; + priv->udev = serial->dev; + + /* find our interrupt endpoint */ + intf = serial->interface->altsetting; + for (i = 0; i < intf->desc.bNumEndpoints; ++i) { + struct usb_endpoint_descriptor *endpoint; + + endpoint = &intf->endpoint[i].desc; + if (!usb_endpoint_is_int_in(endpoint)) + continue; + + priv->int_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!priv->int_urb) { + dev_err(&priv->udev->dev, "out of memory\n"); + goto error; + } + + priv->buffer_size = le16_to_cpu(endpoint->wMaxPacketSize) * 2; + priv->int_buffer = kmalloc(priv->buffer_size, GFP_KERNEL); + if (!priv->int_buffer) { + dev_err(&priv->udev->dev, "out of memory\n"); + goto error; + } + + priv->int_address = endpoint->bEndpointAddress; + priv->bInterval = endpoint->bInterval; + + /* set up our int urb */ + usb_fill_int_urb(priv->int_urb, priv->udev, + usb_rcvintpipe(priv->udev, + endpoint->bEndpointAddress), + priv->int_buffer, priv->buffer_size, + symbol_int_callback, priv, priv->bInterval); + + int_in_found = true; + break; + } + + if (!int_in_found) { + dev_err(&priv->udev->dev, + "Error - the proper endpoints were not found!\n"); + goto error; + } + + usb_set_serial_data(serial, priv); + return 0; + +error: + usb_free_urb(priv->int_urb); + kfree(priv->int_buffer); + kfree(priv); + return retval; +} + +static void symbol_shutdown(struct usb_serial *serial) +{ + struct symbol_private *priv = usb_get_serial_data(serial); + + dbg("%s", __func__); + + usb_kill_urb(priv->int_urb); + usb_free_urb(priv->int_urb); + kfree(priv->int_buffer); + kfree(priv); + usb_set_serial_data(serial, NULL); +} + +static struct usb_driver symbol_driver = { + .name = "symbol", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static struct usb_serial_driver symbol_device = { + .driver = { + .owner = THIS_MODULE, + .name = "symbol", + }, + .id_table = id_table, + .usb_driver = &symbol_driver, + .num_ports = 1, + .attach = symbol_startup, + .open = symbol_open, + .close = symbol_close, + .shutdown = symbol_shutdown, + .throttle = symbol_throttle, + .unthrottle = symbol_unthrottle, +}; + +static int __init symbol_init(void) +{ + int retval; + + retval = usb_serial_register(&symbol_device); + if (retval) + return retval; + retval = usb_register(&symbol_driver); + if (retval) + usb_serial_deregister(&symbol_device); + return retval; +} + +static void __exit symbol_exit(void) +{ + usb_deregister(&symbol_driver); + usb_serial_deregister(&symbol_device); +} + +module_init(symbol_init); +module_exit(symbol_exit); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v1.2.3 From 3d940b7d27c5fec35de66449836ab9a01575447c Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 20 Mar 2009 20:26:30 -0700 Subject: USB: symbolserial: log the ioctl commands We need to figure out what userspace programs are expecting from this driver, so log them so we can try to get it right. Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/symbolserial.c | 59 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index c5990fd88e2..8b3cbc87adc 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c @@ -205,6 +205,62 @@ static void symbol_unthrottle(struct tty_struct *tty) __func__, result); } +static int symbol_ioctl(struct tty_struct *tty, struct file *file, + unsigned int cmd, unsigned long arg) +{ + struct usb_serial_port *port = tty->driver_data; + struct device *dev = &port->dev; + + /* + * Right now we need to figure out what commands + * most userspace tools want to see for this driver, + * so just log the things. + */ + switch (cmd) { + case TIOCSERGETLSR: + dev_info(dev, "%s: TIOCSERGETLSR\n", __func__); + break; + + case TIOCGSERIAL: + dev_info(dev, "%s: TIOCGSERIAL\n", __func__); + break; + + case TIOCMIWAIT: + dev_info(dev, "%s: TIOCMIWAIT\n", __func__); + break; + + case TIOCGICOUNT: + dev_info(dev, "%s: TIOCGICOUNT\n", __func__); + break; + default: + dev_info(dev, "%s: unknown (%d)\n", __func__, cmd); + } + return -ENOIOCTLCMD; +} + +static int symbol_tiocmget(struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + struct device *dev = &port->dev; + + /* TODO */ + /* probably just need to shadow whatever was sent to us here */ + dev_info(dev, "%s\n", __func__); + return 0; +} + +static int symbol_tiocmset(struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + struct device *dev = &port->dev; + + /* TODO */ + /* probably just need to shadow whatever was sent to us here */ + dev_info(dev, "%s\n", __func__); + return 0; +} + static int symbol_startup(struct usb_serial *serial) { struct symbol_private *priv; @@ -311,6 +367,9 @@ static struct usb_serial_driver symbol_device = { .shutdown = symbol_shutdown, .throttle = symbol_throttle, .unthrottle = symbol_unthrottle, + .ioctl = symbol_ioctl, + .tiocmget = symbol_tiocmget, + .tiocmset = symbol_tiocmset, }; static int __init symbol_init(void) -- cgit v1.2.3 From a78b42824dd7c2b40d72fb01f1b1842f7e845f3a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 17 Feb 2009 22:39:56 -0800 Subject: USB: serial: add qualcomm wireless modem driver Driver originally written by Qualcomm, but rewritten by me due to the totally different coding style. Cleaned up the probe logic to make a bit more sense, this is one wierd device. They could have prevented all of this by just writing sane firmware for the modem. Cc: Tamm Liu Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 9 +++ drivers/usb/serial/Makefile | 1 + drivers/usb/serial/qcserial.c | 145 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 155 insertions(+) create mode 100644 drivers/usb/serial/qcserial.c (limited to 'drivers') diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index dbc0781a416..4afe73e8ec4 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -472,6 +472,15 @@ config USB_SERIAL_OTI6858 To compile this driver as a module, choose M here: the module will be called oti6858. +config USB_SERIAL_QUALCOMM + tristate "USB Qualcomm Serial modem" + help + Say Y here if you have a Qualcomm USB modem device. These are + usually wireless cellular modems. + + To compile this driver as a module, choose M here: the + module will be called qcserial. + config USB_SERIAL_SPCP8X5 tristate "USB SPCP8x5 USB To Serial Driver" help diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 222939739ff..94043babe1d 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_USB_SERIAL_OPTICON) += opticon.o obj-$(CONFIG_USB_SERIAL_OPTION) += option.o obj-$(CONFIG_USB_SERIAL_OTI6858) += oti6858.o obj-$(CONFIG_USB_SERIAL_PL2303) += pl2303.o +obj-$(CONFIG_USB_SERIAL_QUALCOMM) += qcserial.o obj-$(CONFIG_USB_SERIAL_SAFE) += safe_serial.o obj-$(CONFIG_USB_SERIAL_SIEMENS_MPI) += siemens_mpi.o obj-$(CONFIG_USB_SERIAL_SIERRAWIRELESS) += sierra.o diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c new file mode 100644 index 00000000000..6c6add50fea --- /dev/null +++ b/drivers/usb/serial/qcserial.c @@ -0,0 +1,145 @@ +/* + * Qualcomm Serial USB driver + * + * Copyright (c) 2008 QUALCOMM Incorporated. + * Copyright (c) 2009 Greg Kroah-Hartman + * Copyright (c) 2009 Novell Inc. + * + * 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 + +#define DRIVER_AUTHOR "Qualcomm Inc" +#define DRIVER_DESC "Qualcomm USB Serial driver" + +static int debug; + +static struct usb_device_id id_table[] = { + {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ + {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver qcdriver = { + .name = "qcserial", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, + .supports_autosuspend = true, +}; + +static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) +{ + int retval = -ENODEV; + __u8 nintf; + __u8 ifnum; + + dbg("%s", __func__); + + nintf = serial->dev->actconfig->desc.bNumInterfaces; + dbg("Num Interfaces = %d", nintf); + ifnum = serial->interface->cur_altsetting->desc.bInterfaceNumber; + dbg("This Interface = %d", ifnum); + + switch (nintf) { + case 1: + /* QDL mode */ + if (serial->interface->num_altsetting == 2) { + struct usb_host_interface *intf; + + intf = &serial->interface->altsetting[1]; + if (intf->desc.bNumEndpoints == 2) { + if (usb_endpoint_is_bulk_in(&intf->endpoint[0].desc) && + usb_endpoint_is_bulk_out(&intf->endpoint[1].desc)) { + dbg("QDL port found"); + retval = usb_set_interface(serial->dev, ifnum, 1); + if (retval < 0) { + dev_err(&serial->dev->dev, + "Could not set interface, error %d\n", + retval); + retval = -ENODEV; + } + return retval; + } + } + } + break; + + case 4: + /* Composite mode */ + if (ifnum == 2) { + dbg("Modem port found"); + retval = usb_set_interface(serial->dev, ifnum, 0); + if (retval < 0) { + dev_err(&serial->dev->dev, + "Could not set interface, error %d\n", + retval); + retval = -ENODEV; + } + return retval; + } + break; + + default: + dev_err(&serial->dev->dev, + "unknown number of interfaces: %d\n", nintf); + return -ENODEV; + } + + return retval; +} + +static struct usb_serial_driver qcdevice = { + .driver = { + .owner = THIS_MODULE, + .name = "qcserial", + }, + .description = "Qualcomm USB modem", + .id_table = id_table, + .usb_driver = &qcdriver, + .num_ports = 1, + .probe = qcprobe, +}; + +static int __init qcinit(void) +{ + int retval; + + retval = usb_serial_register(&qcdevice); + if (retval) + return retval; + + retval = usb_register(&qcdriver); + if (retval) { + usb_serial_deregister(&qcdevice); + return retval; + } + + return 0; +} + +static void __exit qcexit(void) +{ + usb_deregister(&qcdriver); + usb_serial_deregister(&qcdevice); +} + +module_init(qcinit); +module_exit(qcexit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL v2"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug enabled or not"); -- cgit v1.2.3 From 551509d267905705f6d723e51ec706916f06b859 Mon Sep 17 00:00:00 2001 From: Harvey Harrison Date: Wed, 11 Feb 2009 14:11:36 -0800 Subject: USB: replace uses of __constant_{endian} The base versions handle constant folding now. Signed-off-by: Harvey Harrison Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 2 +- drivers/usb/core/hub.c | 8 ++++---- drivers/usb/gadget/amd5536udc.c | 2 +- drivers/usb/gadget/atmel_usba_udc.c | 20 ++++++++++---------- drivers/usb/gadget/cdc2.c | 8 ++++---- drivers/usb/gadget/dummy_hcd.c | 2 +- drivers/usb/gadget/epautoconf.c | 2 +- drivers/usb/gadget/ether.c | 8 ++++---- drivers/usb/gadget/f_acm.c | 10 +++++----- drivers/usb/gadget/f_ecm.c | 16 ++++++++-------- drivers/usb/gadget/f_loopback.c | 4 ++-- drivers/usb/gadget/f_obex.c | 8 ++++---- drivers/usb/gadget/f_phonet.c | 8 ++++---- drivers/usb/gadget/f_rndis.c | 10 +++++----- drivers/usb/gadget/f_serial.c | 4 ++-- drivers/usb/gadget/f_sourcesink.c | 4 ++-- drivers/usb/gadget/f_subset.c | 14 +++++++------- drivers/usb/gadget/file_storage.c | 22 +++++++++++----------- drivers/usb/gadget/gmidi.c | 16 ++++++++-------- drivers/usb/gadget/goku_udc.c | 8 ++++---- drivers/usb/gadget/inode.c | 4 ++-- drivers/usb/gadget/net2280.c | 16 ++++++++-------- drivers/usb/gadget/printer.c | 18 +++++++++--------- drivers/usb/gadget/serial.c | 12 ++++++------ drivers/usb/gadget/u_serial.c | 2 +- drivers/usb/gadget/zero.c | 8 ++++---- drivers/usb/host/ehci-sched.c | 2 +- drivers/usb/host/ehci.h | 2 +- drivers/usb/host/isp1760-hcd.c | 4 ++-- drivers/usb/host/oxu210hp-hcd.c | 22 +++++++++++----------- drivers/usb/host/oxu210hp.h | 8 ++++---- drivers/usb/host/uhci-hcd.h | 10 +++++----- drivers/usb/host/uhci-q.c | 10 +++++----- drivers/usb/image/mdc800.c | 8 ++++---- drivers/usb/musb/musb_virthub.c | 2 +- 35 files changed, 152 insertions(+), 152 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 3c711db55d8..0eee32a65e2 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -901,7 +901,7 @@ static int register_root_hub(struct usb_hcd *hcd) mutex_lock(&usb_bus_list_lock); - usb_dev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + usb_dev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); retval = usb_get_device_descriptor(usb_dev, USB_DT_DEVICE_SIZE); if (retval != sizeof usb_dev->descriptor) { mutex_unlock(&usb_bus_list_lock); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index cd50d86029e..7e33d63ab92 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2471,20 +2471,20 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, */ switch (udev->speed) { case USB_SPEED_VARIABLE: /* fixed at 512 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(512); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(512); break; case USB_SPEED_HIGH: /* fixed at 64 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); break; case USB_SPEED_FULL: /* 8, 16, 32, or 64 */ /* to determine the ep0 maxpacket size, try to read * the device descriptor to get bMaxPacketSize0 and * then correct our initial guess. */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(64); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(64); break; case USB_SPEED_LOW: /* fixed at 8 */ - udev->ep0.desc.wMaxPacketSize = __constant_cpu_to_le16(8); + udev->ep0.desc.wMaxPacketSize = cpu_to_le16(8); break; default: goto fail; diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index abf8192f89e..826f3adde5d 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -551,7 +551,7 @@ udc_alloc_request(struct usb_ep *usbep, gfp_t gfp) dma_desc->status = AMD_ADDBITS(dma_desc->status, UDC_DMA_STP_STS_BS_HOST_BUSY, UDC_DMA_STP_STS_BS); - dma_desc->bufptr = __constant_cpu_to_le32(DMA_DONT_USE); + dma_desc->bufptr = cpu_to_le32(DMA_DONT_USE); req->td_data = dma_desc; req->td_data_last = NULL; req->chain_len = 1; diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 65b03e3445a..c22fab16411 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c @@ -1017,7 +1017,7 @@ static struct usb_endpoint_descriptor usba_ep0_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = 0, .bmAttributes = USB_ENDPOINT_XFER_CONTROL, - .wMaxPacketSize = __constant_cpu_to_le16(64), + .wMaxPacketSize = cpu_to_le16(64), /* FIXME: I have no idea what to put here */ .bInterval = 1, }; @@ -1207,21 +1207,21 @@ static int do_test_mode(struct usba_udc *udc) /* Avoid overly long expressions */ static inline bool feature_is_dev_remote_wakeup(struct usb_ctrlrequest *crq) { - if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP)) + if (crq->wValue == cpu_to_le16(USB_DEVICE_REMOTE_WAKEUP)) return true; return false; } static inline bool feature_is_dev_test_mode(struct usb_ctrlrequest *crq) { - if (crq->wValue == __constant_cpu_to_le16(USB_DEVICE_TEST_MODE)) + if (crq->wValue == cpu_to_le16(USB_DEVICE_TEST_MODE)) return true; return false; } static inline bool feature_is_ep_halt(struct usb_ctrlrequest *crq) { - if (crq->wValue == __constant_cpu_to_le16(USB_ENDPOINT_HALT)) + if (crq->wValue == cpu_to_le16(USB_ENDPOINT_HALT)) return true; return false; } @@ -1239,7 +1239,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, status = cpu_to_le16(udc->devstatus); } else if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_INTERFACE)) { - status = __constant_cpu_to_le16(0); + status = cpu_to_le16(0); } else if (crq->bRequestType == (USB_DIR_IN | USB_RECIP_ENDPOINT)) { struct usba_ep *target; @@ -1250,12 +1250,12 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, status = 0; if (is_stalled(udc, target)) - status |= __constant_cpu_to_le16(1); + status |= cpu_to_le16(1); } else goto delegate; /* Write directly to the FIFO. No queueing is done. */ - if (crq->wLength != __constant_cpu_to_le16(sizeof(status))) + if (crq->wLength != cpu_to_le16(sizeof(status))) goto stall; ep->state = DATA_STAGE_IN; __raw_writew(status, ep->fifo); @@ -1274,7 +1274,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { struct usba_ep *target; - if (crq->wLength != __constant_cpu_to_le16(0) + if (crq->wLength != cpu_to_le16(0) || !feature_is_ep_halt(crq)) goto stall; target = get_ep_by_addr(udc, le16_to_cpu(crq->wIndex)); @@ -1308,7 +1308,7 @@ static int handle_ep0_setup(struct usba_udc *udc, struct usba_ep *ep, } else if (crq->bRequestType == USB_RECIP_ENDPOINT) { struct usba_ep *target; - if (crq->wLength != __constant_cpu_to_le16(0) + if (crq->wLength != cpu_to_le16(0) || !feature_is_ep_halt(crq)) goto stall; @@ -1514,7 +1514,7 @@ restart: */ ep->state = DATA_STAGE_IN; } else { - if (crq.crq.wLength != __constant_cpu_to_le16(0)) + if (crq.crq.wLength != cpu_to_le16(0)) ep->state = DATA_STAGE_OUT; else ep->state = STATUS_STAGE_IN; diff --git a/drivers/usb/gadget/cdc2.c b/drivers/usb/gadget/cdc2.c index 5495b171cf2..928137d3dbd 100644 --- a/drivers/usb/gadget/cdc2.c +++ b/drivers/usb/gadget/cdc2.c @@ -66,7 +66,7 @@ static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_COMM, .bDeviceSubClass = 0, @@ -74,8 +74,8 @@ static struct usb_device_descriptor device_desc = { /* .bMaxPacketSize0 = f(hardware) */ /* Vendor and product id can be overridden by module parameters. */ - .idVendor = __constant_cpu_to_le16(CDC_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(CDC_PRODUCT_NUM), + .idVendor = cpu_to_le16(CDC_VENDOR_NUM), + .idProduct = cpu_to_le16(CDC_PRODUCT_NUM), /* .bcdDevice = f(hardware) */ /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ @@ -193,7 +193,7 @@ static int __init cdc_bind(struct usb_composite_dev *cdev) gadget->name, cdc_config_driver.label); device_desc.bcdDevice = - __constant_cpu_to_le16(0x0300 | 0x0099); + cpu_to_le16(0x0300 | 0x0099); } diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 9064696636a..3b42888b72f 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1626,7 +1626,7 @@ static int dummy_hub_control ( hub_descriptor ((struct usb_hub_descriptor *) buf); break; case GetHubStatus: - *(__le32 *) buf = __constant_cpu_to_le32 (0); + *(__le32 *) buf = cpu_to_le32 (0); break; case GetPortStatus: if (wIndex != 1) diff --git a/drivers/usb/gadget/epautoconf.c b/drivers/usb/gadget/epautoconf.c index a36b1175b18..cd0914ec898 100644 --- a/drivers/usb/gadget/epautoconf.c +++ b/drivers/usb/gadget/epautoconf.c @@ -148,7 +148,7 @@ ep_matches ( return 0; /* BOTH: "high bandwidth" works only at high speed */ - if ((desc->wMaxPacketSize & __constant_cpu_to_le16(3<<11))) { + if ((desc->wMaxPacketSize & cpu_to_le16(3<<11))) { if (!gadget->is_dualspeed) return 0; /* configure your hardware with enough buffering!! */ diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 37252d0012a..d006dc652e0 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -156,7 +156,7 @@ static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16 (0x0200), + .bcdUSB = cpu_to_le16 (0x0200), .bDeviceClass = USB_CLASS_COMM, .bDeviceSubClass = 0, @@ -167,8 +167,8 @@ static struct usb_device_descriptor device_desc = { * we support. (As does bNumConfigurations.) These values can * also be overridden by module parameters. */ - .idVendor = __constant_cpu_to_le16 (CDC_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16 (CDC_PRODUCT_NUM), + .idVendor = cpu_to_le16 (CDC_VENDOR_NUM), + .idProduct = cpu_to_le16 (CDC_PRODUCT_NUM), /* .bcdDevice = f(hardware) */ /* .iManufacturer = DYNAMIC */ /* .iProduct = DYNAMIC */ @@ -318,7 +318,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev) gadget->name, eth_config_driver.label); device_desc.bcdDevice = - __constant_cpu_to_le16(0x0300 | 0x0099); + cpu_to_le16(0x0300 | 0x0099); } diff --git a/drivers/usb/gadget/f_acm.c b/drivers/usb/gadget/f_acm.c index c1d34df0b15..7953948bfe4 100644 --- a/drivers/usb/gadget/f_acm.c +++ b/drivers/usb/gadget/f_acm.c @@ -125,7 +125,7 @@ static struct usb_cdc_header_desc acm_header_desc __initdata = { .bLength = sizeof(acm_header_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_call_mgmt_descriptor @@ -159,7 +159,7 @@ static struct usb_endpoint_descriptor acm_fs_notify_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), + .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET), .bInterval = 1 << GS_LOG2_NOTIFY_INTERVAL, }; @@ -197,7 +197,7 @@ static struct usb_endpoint_descriptor acm_hs_notify_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(GS_NOTIFY_MAXPACKET), + .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET), .bInterval = GS_LOG2_NOTIFY_INTERVAL+4, }; @@ -205,14 +205,14 @@ static struct usb_endpoint_descriptor acm_hs_in_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor acm_hs_out_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *acm_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_ecm.c b/drivers/usb/gadget/f_ecm.c index 4ae579948e5..ecf5bdd0ae0 100644 --- a/drivers/usb/gadget/f_ecm.c +++ b/drivers/usb/gadget/f_ecm.c @@ -130,7 +130,7 @@ static struct usb_cdc_header_desc ecm_header_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_union_desc ecm_union_desc __initdata = { @@ -148,9 +148,9 @@ static struct usb_cdc_ether_desc ecm_desc __initdata = { /* this descriptor actually adds value, surprise! */ /* .iMACAddress = DYNAMIC */ - .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */ - .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN), - .wNumberMCFilters = __constant_cpu_to_le16(0), + .bmEthernetStatistics = cpu_to_le32(0), /* no statistics */ + .wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN), + .wNumberMCFilters = cpu_to_le16(0), .bNumberPowerFilters = 0, }; @@ -192,7 +192,7 @@ static struct usb_endpoint_descriptor fs_ecm_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT), .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, }; @@ -236,7 +236,7 @@ static struct usb_endpoint_descriptor hs_ecm_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(ECM_STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(ECM_STATUS_BYTECOUNT), .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, }; static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = { @@ -245,7 +245,7 @@ static struct usb_endpoint_descriptor hs_ecm_in_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = { @@ -254,7 +254,7 @@ static struct usb_endpoint_descriptor hs_ecm_out_desc __initdata = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *ecm_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 8affe1dfc2c..83301bdcdd1 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -100,7 +100,7 @@ static struct usb_endpoint_descriptor hs_loop_source_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_loop_sink_desc = { @@ -108,7 +108,7 @@ static struct usb_endpoint_descriptor hs_loop_sink_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_loopback_descs[] = { diff --git a/drivers/usb/gadget/f_obex.c b/drivers/usb/gadget/f_obex.c index 38aa896cc5d..46d6266f30e 100644 --- a/drivers/usb/gadget/f_obex.c +++ b/drivers/usb/gadget/f_obex.c @@ -123,7 +123,7 @@ static struct usb_cdc_header_desc obex_cdc_header_desc __initdata = { .bLength = sizeof(obex_cdc_header_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0120), + .bcdCDC = cpu_to_le16(0x0120), }; static struct usb_cdc_union_desc obex_cdc_union_desc __initdata = { @@ -138,7 +138,7 @@ static struct usb_cdc_obex_desc obex_desc __initdata = { .bLength = sizeof(obex_desc), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_OBEX_TYPE, - .bcdVersion = __constant_cpu_to_le16(0x0100), + .bcdVersion = cpu_to_le16(0x0100), }; /* High-Speed Support */ @@ -149,7 +149,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_out_desc __initdata = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { @@ -158,7 +158,7 @@ static struct usb_endpoint_descriptor obex_hs_ep_in_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_phonet.c b/drivers/usb/gadget/f_phonet.c index c0916c7b217..c1abeb89b41 100644 --- a/drivers/usb/gadget/f_phonet.c +++ b/drivers/usb/gadget/f_phonet.c @@ -79,7 +79,7 @@ pn_header_desc = { .bLength = sizeof pn_header_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static const struct usb_cdc_header_desc @@ -87,7 +87,7 @@ pn_phonet_desc = { .bLength = sizeof pn_phonet_desc, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_PHONET_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x1505), /* ??? */ + .bcdCDC = cpu_to_le16(0x1505), /* ??? */ }; static struct usb_cdc_union_desc @@ -138,7 +138,7 @@ pn_hs_sink_desc = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor @@ -157,7 +157,7 @@ pn_hs_source_desc = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *fs_pn_function[] = { diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index fd7b356f902..3279a472604 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -137,7 +137,7 @@ static struct usb_cdc_header_desc header_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_call_mgmt_descriptor call_mgmt_descriptor __initdata = { @@ -187,7 +187,7 @@ static struct usb_endpoint_descriptor fs_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), .bInterval = 1 << LOG2_STATUS_INTERVAL_MSEC, }; @@ -230,7 +230,7 @@ static struct usb_endpoint_descriptor hs_notify_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(STATUS_BYTECOUNT), + .wMaxPacketSize = cpu_to_le16(STATUS_BYTECOUNT), .bInterval = LOG2_STATUS_INTERVAL_MSEC + 4, }; static struct usb_endpoint_descriptor hs_in_desc __initdata = { @@ -239,7 +239,7 @@ static struct usb_endpoint_descriptor hs_in_desc __initdata = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_out_desc __initdata = { @@ -248,7 +248,7 @@ static struct usb_endpoint_descriptor hs_out_desc __initdata = { .bEndpointAddress = USB_DIR_OUT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *eth_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_serial.c b/drivers/usb/gadget/f_serial.c index fe5674db344..db0aa93606e 100644 --- a/drivers/usb/gadget/f_serial.c +++ b/drivers/usb/gadget/f_serial.c @@ -89,14 +89,14 @@ static struct usb_endpoint_descriptor gser_hs_in_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor gser_hs_out_desc __initdata = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *gser_hs_function[] __initdata = { diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index dc84d26d283..6aca5c81414 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -118,7 +118,7 @@ static struct usb_endpoint_descriptor hs_source_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_sink_desc = { @@ -126,7 +126,7 @@ static struct usb_endpoint_descriptor hs_sink_desc = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_source_sink_descs[] = { diff --git a/drivers/usb/gadget/f_subset.c b/drivers/usb/gadget/f_subset.c index fe183287577..a9c98fdb626 100644 --- a/drivers/usb/gadget/f_subset.c +++ b/drivers/usb/gadget/f_subset.c @@ -108,7 +108,7 @@ static struct usb_cdc_header_desc mdlm_header_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_HEADER_TYPE, - .bcdCDC = __constant_cpu_to_le16(0x0110), + .bcdCDC = cpu_to_le16(0x0110), }; static struct usb_cdc_mdlm_desc mdlm_desc __initdata = { @@ -116,7 +116,7 @@ static struct usb_cdc_mdlm_desc mdlm_desc __initdata = { .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = USB_CDC_MDLM_TYPE, - .bcdVersion = __constant_cpu_to_le16(0x0100), + .bcdVersion = cpu_to_le16(0x0100), .bGUID = { 0x5d, 0x34, 0xcf, 0x66, 0x11, 0x18, 0x11, 0xd6, 0xa2, 0x1a, 0x00, 0x01, 0x02, 0xca, 0x9a, 0x7f, @@ -144,9 +144,9 @@ static struct usb_cdc_ether_desc ether_desc __initdata = { /* this descriptor actually adds value, surprise! */ /* .iMACAddress = DYNAMIC */ - .bmEthernetStatistics = __constant_cpu_to_le32(0), /* no statistics */ - .wMaxSegmentSize = __constant_cpu_to_le16(ETH_FRAME_LEN), - .wNumberMCFilters = __constant_cpu_to_le16(0), + .bmEthernetStatistics = cpu_to_le32(0), /* no statistics */ + .wMaxSegmentSize = cpu_to_le16(ETH_FRAME_LEN), + .wNumberMCFilters = cpu_to_le16(0), .bNumberPowerFilters = 0, }; @@ -186,7 +186,7 @@ static struct usb_endpoint_descriptor hs_subset_in_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = { @@ -194,7 +194,7 @@ static struct usb_endpoint_descriptor hs_subset_out_desc __initdata = { .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_descriptor_header *hs_eth_function[] __initdata = { diff --git a/drivers/usb/gadget/file_storage.c b/drivers/usb/gadget/file_storage.c index 1ab9dac7e12..d3c2464dee8 100644 --- a/drivers/usb/gadget/file_storage.c +++ b/drivers/usb/gadget/file_storage.c @@ -847,13 +847,13 @@ device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, /* The next three values can be overridden by module parameters */ - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_ID), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_ID), - .bcdDevice = __constant_cpu_to_le16(0xffff), + .idVendor = cpu_to_le16(DRIVER_VENDOR_ID), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_ID), + .bcdDevice = cpu_to_le16(0xffff), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, @@ -926,7 +926,7 @@ fs_intr_in_desc = { .bEndpointAddress = USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(2), + .wMaxPacketSize = cpu_to_le16(2), .bInterval = 32, // frames -> 32 ms }; @@ -954,7 +954,7 @@ dev_qualifier = { .bLength = sizeof dev_qualifier, .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, .bNumConfigurations = 1, @@ -967,7 +967,7 @@ hs_bulk_in_desc = { /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), }; static struct usb_endpoint_descriptor @@ -977,7 +977,7 @@ hs_bulk_out_desc = { /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512), + .wMaxPacketSize = cpu_to_le16(512), .bInterval = 1, // NAK every 1 uframe }; @@ -988,7 +988,7 @@ hs_intr_in_desc = { /* bEndpointAddress copied from fs_intr_in_desc during fsg_bind() */ .bmAttributes = USB_ENDPOINT_XFER_INT, - .wMaxPacketSize = __constant_cpu_to_le16(2), + .wMaxPacketSize = cpu_to_le16(2), .bInterval = 9, // 2**(9-1) = 256 uframes -> 32 ms }; @@ -2646,7 +2646,7 @@ static int send_status(struct fsg_dev *fsg) struct bulk_cs_wrap *csw = bh->buf; /* Store and send the Bulk-only CSW */ - csw->Signature = __constant_cpu_to_le32(USB_BULK_CS_SIG); + csw->Signature = cpu_to_le32(USB_BULK_CS_SIG); csw->Tag = fsg->tag; csw->Residue = cpu_to_le32(fsg->residue); csw->Status = status; @@ -3089,7 +3089,7 @@ static int received_cbw(struct fsg_dev *fsg, struct fsg_buffhd *bh) /* Is the CBW valid? */ if (req->actual != USB_BULK_CB_WRAP_LEN || - cbw->Signature != __constant_cpu_to_le32( + cbw->Signature != cpu_to_le32( USB_BULK_CB_SIG)) { DBG(fsg, "invalid CBW: len %u sig 0x%x\n", req->actual, diff --git a/drivers/usb/gadget/gmidi.c b/drivers/usb/gadget/gmidi.c index 60d3f9e9b51..bb738bc96d4 100644 --- a/drivers/usb/gadget/gmidi.c +++ b/drivers/usb/gadget/gmidi.c @@ -199,10 +199,10 @@ DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1); static struct usb_device_descriptor device_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), + .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, .bNumConfigurations = 1, @@ -241,8 +241,8 @@ static const struct usb_ac_header_descriptor_1 ac_header_desc = { .bLength = USB_DT_AC_HEADER_SIZE(1), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = USB_MS_HEADER, - .bcdADC = __constant_cpu_to_le16(0x0100), - .wTotalLength = __constant_cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)), + .bcdADC = cpu_to_le16(0x0100), + .wTotalLength = cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)), .bInCollection = 1, .baInterfaceNr = { [0] = GMIDI_MS_INTERFACE, @@ -265,8 +265,8 @@ static const struct usb_ms_header_descriptor ms_header_desc = { .bLength = USB_DT_MS_HEADER_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = USB_MS_HEADER, - .bcdMSC = __constant_cpu_to_le16(0x0100), - .wTotalLength = __constant_cpu_to_le16(USB_DT_MS_HEADER_SIZE + .bcdMSC = cpu_to_le16(0x0100), + .wTotalLength = cpu_to_le16(USB_DT_MS_HEADER_SIZE + 2*USB_DT_MIDI_IN_SIZE + 2*USB_DT_MIDI_OUT_SIZE(1)), }; @@ -1227,7 +1227,7 @@ autoconf_fail: */ pr_warning("%s: controller '%s' not recognized\n", shortname, gadget->name); - device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); + device_desc.bcdDevice = cpu_to_le16(0x9999); } diff --git a/drivers/usb/gadget/goku_udc.c b/drivers/usb/gadget/goku_udc.c index 63419c4d503..de010c939db 100644 --- a/drivers/usb/gadget/goku_udc.c +++ b/drivers/usb/gadget/goku_udc.c @@ -1472,7 +1472,7 @@ static void ep0_setup(struct goku_udc *dev) /* active endpoint */ if (tmp > 3 || (!dev->ep[tmp].desc && tmp != 0)) goto stall; - if (ctrl.wIndex & __constant_cpu_to_le16( + if (ctrl.wIndex & cpu_to_le16( USB_DIR_IN)) { if (!dev->ep[tmp].is_in) goto stall; @@ -1480,7 +1480,7 @@ static void ep0_setup(struct goku_udc *dev) if (dev->ep[tmp].is_in) goto stall; } - if (ctrl.wValue != __constant_cpu_to_le16( + if (ctrl.wValue != cpu_to_le16( USB_ENDPOINT_HALT)) goto stall; if (tmp) @@ -1493,7 +1493,7 @@ succeed: return; case USB_RECIP_DEVICE: /* device remote wakeup: always clear */ - if (ctrl.wValue != __constant_cpu_to_le16(1)) + if (ctrl.wValue != cpu_to_le16(1)) goto stall; VDBG(dev, "clear dev remote wakeup\n"); goto succeed; @@ -1519,7 +1519,7 @@ succeed: dev->req_config = (ctrl.bRequest == USB_REQ_SET_CONFIGURATION && ctrl.bRequestType == USB_RECIP_DEVICE); if (unlikely(dev->req_config)) - dev->configured = (ctrl.wValue != __constant_cpu_to_le16(0)); + dev->configured = (ctrl.wValue != cpu_to_le16(0)); /* delegate everything to the gadget driver. * it may respond after this irq handler returns. diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 317b48fdbf0..d20937f28a1 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c @@ -1334,7 +1334,7 @@ static void make_qualifier (struct dev_data *dev) qual.bLength = sizeof qual; qual.bDescriptorType = USB_DT_DEVICE_QUALIFIER; - qual.bcdUSB = __constant_cpu_to_le16 (0x0200); + qual.bcdUSB = cpu_to_le16 (0x0200); desc = dev->dev; qual.bDeviceClass = desc->bDeviceClass; @@ -1908,7 +1908,7 @@ dev_config (struct file *fd, const char __user *buf, size_t len, loff_t *ptr) || dev->dev->bNumConfigurations != 1) goto fail; dev->dev->bNumConfigurations = 1; - dev->dev->bcdUSB = __constant_cpu_to_le16 (0x0200); + dev->dev->bcdUSB = cpu_to_le16 (0x0200); /* triggers gadgetfs_bind(); then we can enumerate. */ spin_unlock_irq (&dev->lock); diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index 12c6d83b218..9498be87a72 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c @@ -142,8 +142,8 @@ static char *type_string (u8 bmAttributes) #include "net2280.h" -#define valid_bit __constant_cpu_to_le32 (1 << VALID_BIT) -#define dma_done_ie __constant_cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE) +#define valid_bit cpu_to_le32 (1 << VALID_BIT) +#define dma_done_ie cpu_to_le32 (1 << DMA_DONE_INTERRUPT_ENABLE) /*-------------------------------------------------------------------------*/ @@ -425,7 +425,7 @@ net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags) return NULL; } td->dmacount = 0; /* not VALID */ - td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); + td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID); td->dmadesc = td->dmaaddr; req->td = td; } @@ -775,7 +775,7 @@ static void start_dma (struct net2280_ep *ep, struct net2280_request *req) fill_dma_desc (ep, req, 1); if (!use_dma_chaining) - req->td->dmacount |= __constant_cpu_to_le32 (1 << END_OF_CHAIN); + req->td->dmacount |= cpu_to_le32 (1 << END_OF_CHAIN); start_queue (ep, tmp, req->td_dma); } @@ -2407,9 +2407,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat) if (readl (&e->regs->ep_rsp) & (1 << SET_ENDPOINT_HALT)) - status = __constant_cpu_to_le32 (1); + status = cpu_to_le32 (1); else - status = __constant_cpu_to_le32 (0); + status = cpu_to_le32 (0); /* don't bother with a request object! */ writel (0, &dev->epregs [0].ep_irqenb); @@ -2667,7 +2667,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat) req = list_entry (ep->queue.next, struct net2280_request, queue); dmacount = req->td->dmacount; - dmacount &= __constant_cpu_to_le32 ( + dmacount &= cpu_to_le32 ( (1 << VALID_BIT) | DMA_BYTE_COUNT_MASK); if (dmacount && (dmacount & valid_bit) == 0) @@ -2881,7 +2881,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) goto done; } td->dmacount = 0; /* not VALID */ - td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID); + td->dmaaddr = cpu_to_le32 (DMA_ADDR_INVALID); td->dmadesc = td->dmaaddr; dev->ep [i].dummy = td; } diff --git a/drivers/usb/gadget/printer.c b/drivers/usb/gadget/printer.c index 5a3034fdfe4..29500154d00 100644 --- a/drivers/usb/gadget/printer.c +++ b/drivers/usb/gadget/printer.c @@ -225,12 +225,12 @@ module_param(qlen, uint, S_IRUGO|S_IWUSR); static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PER_INTERFACE, .bDeviceSubClass = 0, .bDeviceProtocol = 0, - .idVendor = __constant_cpu_to_le16(PRINTER_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(PRINTER_PRODUCT_NUM), + .idVendor = cpu_to_le16(PRINTER_VENDOR_NUM), + .idProduct = cpu_to_le16(PRINTER_PRODUCT_NUM), .iManufacturer = STRING_MANUFACTURER, .iProduct = STRING_PRODUCT, .iSerialNumber = STRING_SERIALNUM, @@ -299,20 +299,20 @@ static struct usb_endpoint_descriptor hs_ep_in_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512) + .wMaxPacketSize = cpu_to_le16(512) }; static struct usb_endpoint_descriptor hs_ep_out_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = __constant_cpu_to_le16(512) + .wMaxPacketSize = cpu_to_le16(512) }; static struct usb_qualifier_descriptor dev_qualifier = { .bLength = sizeof dev_qualifier, .bDescriptorType = USB_DT_DEVICE_QUALIFIER, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_PRINTER, .bNumConfigurations = 1 }; @@ -1406,16 +1406,16 @@ printer_bind(struct usb_gadget *gadget) gadget->name); /* unrecognized, but safe unless bulk is REALLY quirky */ device_desc.bcdDevice = - __constant_cpu_to_le16(0xFFFF); + cpu_to_le16(0xFFFF); } snprintf(manufacturer, sizeof(manufacturer), "%s %s with %s", init_utsname()->sysname, init_utsname()->release, gadget->name); device_desc.idVendor = - __constant_cpu_to_le16(PRINTER_VENDOR_NUM); + cpu_to_le16(PRINTER_VENDOR_NUM); device_desc.idProduct = - __constant_cpu_to_le16(PRINTER_PRODUCT_NUM); + cpu_to_le16(PRINTER_PRODUCT_NUM); /* support optional vendor/distro customization */ if (idVendor) { diff --git a/drivers/usb/gadget/serial.c b/drivers/usb/gadget/serial.c index 37879af1c43..f46a60962da 100644 --- a/drivers/usb/gadget/serial.c +++ b/drivers/usb/gadget/serial.c @@ -87,12 +87,12 @@ static struct usb_gadget_strings *dev_strings[] = { static struct usb_device_descriptor device_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), /* .bDeviceClass = f(use_acm) */ .bDeviceSubClass = 0, .bDeviceProtocol = 0, /* .bMaxPacketSize0 = f(hardware) */ - .idVendor = __constant_cpu_to_le16(GS_VENDOR_ID), + .idVendor = cpu_to_le16(GS_VENDOR_ID), /* .idProduct = f(use_acm) */ /* .bcdDevice = f(hardware) */ /* .iManufacturer = DYNAMIC */ @@ -216,7 +216,7 @@ static int __init gs_bind(struct usb_composite_dev *cdev) pr_warning("gs_bind: controller '%s' not recognized\n", gadget->name); device_desc.bcdDevice = - __constant_cpu_to_le16(GS_VERSION_NUM | 0x0099); + cpu_to_le16(GS_VERSION_NUM | 0x0099); } if (gadget_is_otg(cdev->gadget)) { @@ -255,19 +255,19 @@ static int __init init(void) serial_config_driver.bConfigurationValue = 2; device_desc.bDeviceClass = USB_CLASS_COMM; device_desc.idProduct = - __constant_cpu_to_le16(GS_CDC_PRODUCT_ID); + cpu_to_le16(GS_CDC_PRODUCT_ID); } else if (use_obex) { serial_config_driver.label = "CDC OBEX config"; serial_config_driver.bConfigurationValue = 3; device_desc.bDeviceClass = USB_CLASS_COMM; device_desc.idProduct = - __constant_cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID); + cpu_to_le16(GS_CDC_OBEX_PRODUCT_ID); } else { serial_config_driver.label = "Generic Serial config"; serial_config_driver.bConfigurationValue = 1; device_desc.bDeviceClass = USB_CLASS_VENDOR_SPEC; device_desc.idProduct = - __constant_cpu_to_le16(GS_PRODUCT_ID); + cpu_to_le16(GS_PRODUCT_ID); } strings_dev[STRING_DESCRIPTION_IDX].s = serial_config_driver.label; diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index 53d59287f2b..0a4d99ab40d 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c @@ -1092,7 +1092,7 @@ int __init gserial_setup(struct usb_gadget *g, unsigned count) gs_tty_driver->init_termios.c_ispeed = 9600; gs_tty_driver->init_termios.c_ospeed = 9600; - coding.dwDTERate = __constant_cpu_to_le32(9600); + coding.dwDTERate = cpu_to_le32(9600); coding.bCharFormat = 8; coding.bParityType = USB_CDC_NO_PARITY; coding.bDataBits = USB_CDC_1_STOP_BITS; diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 361d9659ac4..20614dce8db 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -113,11 +113,11 @@ static struct usb_device_descriptor device_desc = { .bLength = sizeof device_desc, .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = __constant_cpu_to_le16(0x0200), + .bcdUSB = cpu_to_le16(0x0200), .bDeviceClass = USB_CLASS_VENDOR_SPEC, - .idVendor = __constant_cpu_to_le16(DRIVER_VENDOR_NUM), - .idProduct = __constant_cpu_to_le16(DRIVER_PRODUCT_NUM), + .idVendor = cpu_to_le16(DRIVER_VENDOR_NUM), + .idProduct = cpu_to_le16(DRIVER_PRODUCT_NUM), .bNumConfigurations = 2, }; @@ -265,7 +265,7 @@ static int __init zero_bind(struct usb_composite_dev *cdev) */ pr_warning("%s: controller '%s' not recognized\n", longname, gadget->name); - device_desc.bcdDevice = __constant_cpu_to_le16(0x9999); + device_desc.bcdDevice = cpu_to_le16(0x9999); } diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 1d0b49e3f19..ada5d2ba297 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c @@ -563,7 +563,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) // and this qh is active in the current uframe // (and overlay token SplitXstate is false?) // THEN - // qh->hw_info1 |= __constant_cpu_to_hc32(1 << 7 /* "ignore" */); + // qh->hw_info1 |= cpu_to_hc32(1 << 7 /* "ignore" */); /* high bandwidth, or otherwise part of every microframe */ if ((period = qh->period) == 0) diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 9aba560fd56..6cff195e1a3 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h @@ -253,7 +253,7 @@ struct ehci_qtd { /* * Now the following defines are not converted using the - * __constant_cpu_to_le32() macro anymore, since we have to support + * cpu_to_le32() macro anymore, since we have to support * "dynamic" switching between be and le support, so that the driver * can be used on one system with SoC EHCI controller using big-endian * descriptors as well as a normal little-endian PCI EHCI controller. diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 8ee2f415984..3172c0fd2a6 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -644,7 +644,7 @@ static void transform_add_int(struct isp1760_hcd *priv, struct isp1760_qh *qh, if (urb->dev->speed != USB_SPEED_HIGH) { /* split */ - ptd->dw5 = __constant_cpu_to_le32(0x1c); + ptd->dw5 = cpu_to_le32(0x1c); if (qh->period >= 32) period = qh->period / 2; @@ -1054,7 +1054,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs, sizeof(ptd)); - ptd.dw0 |= __constant_cpu_to_le32(PTD_VALID); + ptd.dw0 |= cpu_to_le32(PTD_VALID); priv_write_copy(priv, (u32 *)&ptd, usb_hcd->regs + atl_regs, sizeof(ptd)); diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 75548f7c716..2947c69b347 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -845,14 +845,14 @@ static inline void qh_update(struct oxu_hcd *oxu, is_out = !(qtd->hw_token & cpu_to_le32(1 << 8)); epnum = (le32_to_cpup(&qh->hw_info1) >> 8) & 0x0f; if (unlikely(!usb_gettoggle(qh->dev, epnum, is_out))) { - qh->hw_token &= ~__constant_cpu_to_le32(QTD_TOGGLE); + qh->hw_token &= ~cpu_to_le32(QTD_TOGGLE); usb_settoggle(qh->dev, epnum, is_out, 1); } } /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ wmb(); - qh->hw_token &= __constant_cpu_to_le32(QTD_TOGGLE | QTD_STS_PING); + qh->hw_token &= cpu_to_le32(QTD_TOGGLE | QTD_STS_PING); } /* If it weren't for a common silicon quirk (writing the dummy into the qh @@ -937,7 +937,7 @@ __acquires(oxu->lock) struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; /* S-mask in a QH means it's an interrupt urb */ - if ((qh->hw_info2 & __constant_cpu_to_le32(QH_SMASK)) != 0) { + if ((qh->hw_info2 & cpu_to_le32(QH_SMASK)) != 0) { /* ... update hc-wide periodic stats (for usbfs) */ oxu_to_hcd(oxu)->self.bandwidth_int_reqs--; @@ -981,7 +981,7 @@ static void unlink_async(struct oxu_hcd *oxu, struct ehci_qh *qh); static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh); static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh); -#define HALT_BIT __constant_cpu_to_le32(QTD_STS_HALT) +#define HALT_BIT cpu_to_le32(QTD_STS_HALT) /* Process and free completed qtds for a qh, returning URBs to drivers. * Chases up to qh->hw_current. Returns number of completions called, @@ -1160,7 +1160,7 @@ halt: /* should be rare for periodic transfers, * except maybe high bandwidth ... */ - if ((__constant_cpu_to_le32(QH_SMASK) + if ((cpu_to_le32(QH_SMASK) & qh->hw_info2) != 0) { intr_deschedule(oxu, qh); (void) qh_schedule(oxu, qh); @@ -1350,7 +1350,7 @@ static struct list_head *qh_urb_transaction(struct oxu_hcd *oxu, } /* by default, enable interrupt on urb completion */ - qtd->hw_token |= __constant_cpu_to_le32(QTD_IOC); + qtd->hw_token |= cpu_to_le32(QTD_IOC); return head; cleanup: @@ -1539,7 +1539,7 @@ static void qh_link_async(struct oxu_hcd *oxu, struct ehci_qh *qh) /* qtd completions reported later by interrupt */ } -#define QH_ADDR_MASK __constant_cpu_to_le32(0x7f) +#define QH_ADDR_MASK cpu_to_le32(0x7f) /* * For control/bulk/interrupt, return QH with these TDs appended. @@ -2012,7 +2012,7 @@ static void qh_unlink_periodic(struct oxu_hcd *oxu, struct ehci_qh *qh) * and this qh is active in the current uframe * (and overlay token SplitXstate is false?) * THEN - * qh->hw_info1 |= __constant_cpu_to_le32(1 << 7 "ignore"); + * qh->hw_info1 |= cpu_to_le32(1 << 7 "ignore"); */ /* high bandwidth, or otherwise part of every microframe */ @@ -2057,7 +2057,7 @@ static void intr_deschedule(struct oxu_hcd *oxu, struct ehci_qh *qh) * active high speed queues may need bigger delays... */ if (list_empty(&qh->qtd_list) - || (__constant_cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0) + || (cpu_to_le32(QH_CMASK) & qh->hw_info2) != 0) wait = 2; else wait = 55; /* worst case: 3 * 1024 */ @@ -2183,10 +2183,10 @@ static int qh_schedule(struct oxu_hcd *oxu, struct ehci_qh *qh) qh->start = frame; /* reset S-frame and (maybe) C-frame masks */ - qh->hw_info2 &= __constant_cpu_to_le32(~(QH_CMASK | QH_SMASK)); + qh->hw_info2 &= cpu_to_le32(~(QH_CMASK | QH_SMASK)); qh->hw_info2 |= qh->period ? cpu_to_le32(1 << uframe) - : __constant_cpu_to_le32(QH_SMASK); + : cpu_to_le32(QH_SMASK); qh->hw_info2 |= c_mask; } else oxu_dbg(oxu, "reused qh %p schedule\n", qh); diff --git a/drivers/usb/host/oxu210hp.h b/drivers/usb/host/oxu210hp.h index 8910e271cc7..1c216ad9aad 100644 --- a/drivers/usb/host/oxu210hp.h +++ b/drivers/usb/host/oxu210hp.h @@ -235,21 +235,21 @@ struct ehci_qtd { } __attribute__ ((aligned(32))); /* mask NakCnt+T in qh->hw_alt_next */ -#define QTD_MASK __constant_cpu_to_le32 (~0x1f) +#define QTD_MASK cpu_to_le32 (~0x1f) #define IS_SHORT_READ(token) (QTD_LENGTH(token) != 0 && QTD_PID(token) == 1) /* Type tag from {qh, itd, sitd, fstn}->hw_next */ -#define Q_NEXT_TYPE(dma) ((dma) & __constant_cpu_to_le32 (3 << 1)) +#define Q_NEXT_TYPE(dma) ((dma) & cpu_to_le32 (3 << 1)) /* values for that type tag */ -#define Q_TYPE_QH __constant_cpu_to_le32 (1 << 1) +#define Q_TYPE_QH cpu_to_le32 (1 << 1) /* next async queue entry, or pointer to interrupt/periodic QH */ #define QH_NEXT(dma) (cpu_to_le32(((u32)dma)&~0x01f)|Q_TYPE_QH) /* for periodic/async schedules and qtd lists, mark end of list */ -#define EHCI_LIST_END __constant_cpu_to_le32(1) /* "null pointer" to hw */ +#define EHCI_LIST_END cpu_to_le32(1) /* "null pointer" to hw */ /* * Entries in periodic shadow table are pointers to one of four kinds diff --git a/drivers/usb/host/uhci-hcd.h b/drivers/usb/host/uhci-hcd.h index 7d01c5677f9..26bd1b2bcbf 100644 --- a/drivers/usb/host/uhci-hcd.h +++ b/drivers/usb/host/uhci-hcd.h @@ -73,11 +73,11 @@ #define USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ #define USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ -#define UHCI_PTR_BITS __constant_cpu_to_le32(0x000F) -#define UHCI_PTR_TERM __constant_cpu_to_le32(0x0001) -#define UHCI_PTR_QH __constant_cpu_to_le32(0x0002) -#define UHCI_PTR_DEPTH __constant_cpu_to_le32(0x0004) -#define UHCI_PTR_BREADTH __constant_cpu_to_le32(0x0000) +#define UHCI_PTR_BITS cpu_to_le32(0x000F) +#define UHCI_PTR_TERM cpu_to_le32(0x0001) +#define UHCI_PTR_QH cpu_to_le32(0x0002) +#define UHCI_PTR_DEPTH cpu_to_le32(0x0004) +#define UHCI_PTR_BREADTH cpu_to_le32(0x0000) #define UHCI_NUMFRAMES 1024 /* in the frame list [array] */ #define UHCI_MAX_SOF_NUMBER 2047 /* in an SOF packet */ diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 5631d89c873..58f87367914 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -402,7 +402,7 @@ static void uhci_fixup_toggles(struct uhci_qh *qh, int skip_first) /* Otherwise all the toggles in the URB have to be switched */ } else { list_for_each_entry(td, &urbp->td_list, list) { - td->token ^= __constant_cpu_to_le32( + td->token ^= cpu_to_le32( TD_TOKEN_TOGGLE); toggle ^= 1; } @@ -883,7 +883,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); wmb(); - qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); + qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE); qh->dummy_td = td; /* Low-speed transfers get a different queue, and won't hog the bus. @@ -1003,7 +1003,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, * fast side but not enough to justify delaying an interrupt * more than 2 or 3 URBs, so we will ignore the URB_NO_INTERRUPT * flag setting. */ - td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); + td->status |= cpu_to_le32(TD_CTRL_IOC); /* * Build the new dummy TD and activate the old one @@ -1015,7 +1015,7 @@ static int uhci_submit_common(struct uhci_hcd *uhci, struct urb *urb, uhci_fill_td(td, 0, USB_PID_OUT | uhci_explen(0), 0); wmb(); - qh->dummy_td->status |= __constant_cpu_to_le32(TD_CTRL_ACTIVE); + qh->dummy_td->status |= cpu_to_le32(TD_CTRL_ACTIVE); qh->dummy_td = td; usb_settoggle(urb->dev, usb_pipeendpoint(urb->pipe), @@ -1317,7 +1317,7 @@ static int uhci_submit_isochronous(struct uhci_hcd *uhci, struct urb *urb, } /* Set the interrupt-on-completion flag on the last packet. */ - td->status |= __constant_cpu_to_le32(TD_CTRL_IOC); + td->status |= cpu_to_le32(TD_CTRL_IOC); /* Add the TDs to the frame list */ frame = urb->start_frame; diff --git a/drivers/usb/image/mdc800.c b/drivers/usb/image/mdc800.c index 972f20b3406..eca355dccf6 100644 --- a/drivers/usb/image/mdc800.c +++ b/drivers/usb/image/mdc800.c @@ -188,7 +188,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x01, .bmAttributes = 0x02, - .wMaxPacketSize = __constant_cpu_to_le16(8), + .wMaxPacketSize = cpu_to_le16(8), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, @@ -198,7 +198,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x82, .bmAttributes = 0x03, - .wMaxPacketSize = __constant_cpu_to_le16(8), + .wMaxPacketSize = cpu_to_le16(8), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, @@ -208,7 +208,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x03, .bmAttributes = 0x02, - .wMaxPacketSize = __constant_cpu_to_le16(64), + .wMaxPacketSize = cpu_to_le16(64), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, @@ -218,7 +218,7 @@ static struct usb_endpoint_descriptor mdc800_ed [4] = .bDescriptorType = 0, .bEndpointAddress = 0x84, .bmAttributes = 0x02, - .wMaxPacketSize = __constant_cpu_to_le16(64), + .wMaxPacketSize = cpu_to_le16(64), .bInterval = 0, .bRefresh = 0, .bSynchAddress = 0, diff --git a/drivers/usb/musb/musb_virthub.c b/drivers/usb/musb/musb_virthub.c index e0e9ce58417..bf677acc83d 100644 --- a/drivers/usb/musb/musb_virthub.c +++ b/drivers/usb/musb/musb_virthub.c @@ -285,7 +285,7 @@ int musb_hub_control( desc->bDescLength = 9; desc->bDescriptorType = 0x29; desc->bNbrPorts = 1; - desc->wHubCharacteristics = __constant_cpu_to_le16( + desc->wHubCharacteristics = cpu_to_le16( 0x0001 /* per-port power switching */ | 0x0010 /* no overcurrent reporting */ ); -- cgit v1.2.3 From d0626808f7a6181c1c750d261da9a7a845c29e13 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 13 Feb 2009 11:22:06 -0800 Subject: USB: fix ehci printk formats Fix ehci printk formats: drivers/usb/host/ehci-q.c:351: warning: format '%d' expects type 'int', but argument 4 has type 'size_t' drivers/usb/host/ehci-q.c:351: warning: format '%d' expects type 'int', but argument 5 has type 'size_t' Signed-off-by: Randy Dunlap Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ehci-q.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 01132ac74eb..1976b1b3778 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c @@ -349,7 +349,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) --qh->xacterrs > 0 && !urb->unlinked) { ehci_dbg(ehci, - "detected XactErr len %d/%d retry %d\n", + "detected XactErr len %zu/%zu retry %d\n", qtd->length - QTD_LENGTH(token), qtd->length, QH_XACTERR_MAX - qh->xacterrs); -- cgit v1.2.3 From e4abe6658aa17a5d7e7321dfda807d287255511b Mon Sep 17 00:00:00 2001 From: Dave Young Date: Sat, 14 Feb 2009 21:21:13 +0800 Subject: usb-serial: fix usb_serial_register bug when boot with nousb param With "nousb" cmdline booting, built-in serial drivers (ie. airecable) will trigger kernel oops. Indeed, if nousb, usb_serial_init will failed, and the usb serial bus type will not be registerd, then usb_serial_register call driver_register which try to register the driver to a not registered bus. Here add usb_disabled() check in usb_serial_register to fix it. Signed-off-by: Dave Young Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/usb-serial.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 73172898ccb..742a5bc44be 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c @@ -1241,6 +1241,9 @@ int usb_serial_register(struct usb_serial_driver *driver) /* must be called with BKL held */ int retval; + if (usb_disabled()) + return -ENODEV; + fixup_generic(driver); if (!driver->description) -- cgit v1.2.3 From e6e244b6cb1f70e7109381626293cd40a8334ed3 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:44 -0500 Subject: usb-storage: prepare for subdriver separation This patch (as1206) is the first step in converting usb-storage's subdrivers into separate modules. It makes the following large-scale changes: Remove a bunch of unnecessary #ifdef's from usb_usual.h. Not truly necessary, but it does clean things up. Move the USB device-ID table (which is duplicated between libusual and usb-storage) into its own source file, usual-tables.c, and arrange for this to be linked with either libusual or usb-storage according to whether USB_LIBUSUAL is configured. Add to usual-tables.c a new usb_usual_ignore_device() function to detect whether a particular device needs to be managed by a subdriver and not by the standard handlers in usb-storage. Export a whole bunch of functions in usb-storage, renaming some of them because their names don't already begin with "usb_stor_". These functions will be needed by the new subdriver modules. Split usb-storage's probe routine into two functions. The subdrivers will call the probe1 routine, then fill in their transport and protocol settings, and then call the probe2 routine. Take the default cases and error checking out of get_transport() and get_protocol(), which run during probe1, and instead put a check for invalid transport or protocol values into the probe2 function. Add a new probe routine to be used for standard devices, i.e., those that don't need a subdriver. This new routine checks whether the device should be ignored (because it should be handled by ub or by a subdriver), and if not, calls the probe1 and probe2 functions. Signed-off-by: Alan Stern CC: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/block/ub.c | 2 +- drivers/usb/storage/Makefile | 6 +- drivers/usb/storage/libusual.c | 33 +----- drivers/usb/storage/protocol.c | 3 + drivers/usb/storage/scsiglue.c | 2 +- drivers/usb/storage/transport.c | 10 ++ drivers/usb/storage/usb.c | 209 ++++++++++++++++++++----------------- drivers/usb/storage/usb.h | 21 ++++ drivers/usb/storage/usual-tables.c | 105 +++++++++++++++++++ 9 files changed, 257 insertions(+), 134 deletions(-) create mode 100644 drivers/usb/storage/usual-tables.c (limited to 'drivers') diff --git a/drivers/block/ub.c b/drivers/block/ub.c index b36b84fbe39..69b7f8e7759 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c @@ -391,7 +391,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum); */ #ifdef CONFIG_USB_LIBUSUAL -#define ub_usb_ids storage_usb_ids +#define ub_usb_ids usb_storage_usb_ids #else static struct usb_device_id ub_usb_ids[] = { diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index b3206931339..a9e475e127a 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -25,6 +25,8 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) -ifneq ($(CONFIG_USB_LIBUSUAL),) - obj-$(CONFIG_USB) += libusual.o +ifeq ($(CONFIG_USB_LIBUSUAL),) + usb-storage-objs += usual-tables.o +else + obj-$(CONFIG_USB) += libusual.o usual-tables.o endif diff --git a/drivers/usb/storage/libusual.c b/drivers/usb/storage/libusual.c index f970b27ba30..fe3ffe1459b 100644 --- a/drivers/usb/storage/libusual.c +++ b/drivers/usb/storage/libusual.c @@ -37,37 +37,6 @@ static atomic_t total_threads = ATOMIC_INIT(0); static int usu_probe_thread(void *arg); -/* - * The table. - */ -#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName,useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } - -#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName, useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ - .driver_info = (flags) } - -#define USUAL_DEV(useProto, useTrans, useType) \ -{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ - .driver_info = ((useType)<<24) } - -struct usb_device_id storage_usb_ids [] = { -# include "unusual_devs.h" - { } /* Terminating entry */ -}; - -#undef USUAL_DEV -#undef UNUSUAL_DEV -#undef COMPLIANT_DEV - -MODULE_DEVICE_TABLE(usb, storage_usb_ids); -EXPORT_SYMBOL_GPL(storage_usb_ids); - /* * @type: the module type as an integer */ @@ -167,7 +136,7 @@ static struct usb_driver usu_driver = { .name = "libusual", .probe = usu_probe, .disconnect = usu_disconnect, - .id_table = storage_usb_ids, + .id_table = usb_storage_usb_ids, }; /* diff --git a/drivers/usb/storage/protocol.c b/drivers/usb/storage/protocol.c index be441d84bc6..fc310f75ead 100644 --- a/drivers/usb/storage/protocol.c +++ b/drivers/usb/storage/protocol.c @@ -121,6 +121,7 @@ void usb_stor_transparent_scsi_command(struct scsi_cmnd *srb, /* send the command to the transport layer */ usb_stor_invoke_transport(srb, us); } +EXPORT_SYMBOL_GPL(usb_stor_transparent_scsi_command); /*********************************************************************** * Scatter-gather transfer buffer access routines @@ -199,6 +200,7 @@ unsigned int usb_stor_access_xfer_buf(unsigned char *buffer, /* Return the amount actually transferred */ return cnt; } +EXPORT_SYMBOL_GPL(usb_stor_access_xfer_buf); /* Store the contents of buffer into srb's transfer buffer and set the * SCSI residue. @@ -215,3 +217,4 @@ void usb_stor_set_xfer_buf(unsigned char *buffer, if (buflen < scsi_bufflen(srb)) scsi_set_resid(srb, scsi_bufflen(srb) - buflen); } +EXPORT_SYMBOL_GPL(usb_stor_set_xfer_buf); diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index ed710bcdaab..4ca3b586064 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c @@ -569,4 +569,4 @@ unsigned char usb_stor_sense_invalidCDB[18] = { [7] = 0x0a, /* additional length */ [12] = 0x24 /* Invalid Field in CDB */ }; - +EXPORT_SYMBOL_GPL(usb_stor_sense_invalidCDB); diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c index fb65d221ced..d48c8553539 100644 --- a/drivers/usb/storage/transport.c +++ b/drivers/usb/storage/transport.c @@ -220,6 +220,7 @@ int usb_stor_control_msg(struct us_data *us, unsigned int pipe, status = us->current_urb->actual_length; return status; } +EXPORT_SYMBOL_GPL(usb_stor_control_msg); /* This is a version of usb_clear_halt() that allows early termination and * doesn't read the status from the device -- this is because some devices @@ -254,6 +255,7 @@ int usb_stor_clear_halt(struct us_data *us, unsigned int pipe) US_DEBUGP("%s: result = %d\n", __func__, result); return result; } +EXPORT_SYMBOL_GPL(usb_stor_clear_halt); /* @@ -352,6 +354,7 @@ int usb_stor_ctrl_transfer(struct us_data *us, unsigned int pipe, return interpret_urb_result(us, pipe, size, result, us->current_urb->actual_length); } +EXPORT_SYMBOL_GPL(usb_stor_ctrl_transfer); /* * Receive one interrupt buffer, without timeouts, but allowing early @@ -407,6 +410,7 @@ int usb_stor_bulk_transfer_buf(struct us_data *us, unsigned int pipe, return interpret_urb_result(us, pipe, length, result, us->current_urb->actual_length); } +EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_buf); /* * Transfer a scatter-gather list via bulk transfer @@ -474,6 +478,7 @@ int usb_stor_bulk_srb(struct us_data* us, unsigned int pipe, scsi_set_resid(srb, scsi_bufflen(srb) - partial); return result; } +EXPORT_SYMBOL_GPL(usb_stor_bulk_srb); /* * Transfer an entire SCSI command's worth of data payload over the bulk @@ -509,6 +514,7 @@ int usb_stor_bulk_transfer_sg(struct us_data* us, unsigned int pipe, *residual = length_left; return result; } +EXPORT_SYMBOL_GPL(usb_stor_bulk_transfer_sg); /*********************************************************************** * Transport routines @@ -940,6 +946,7 @@ int usb_stor_CB_transport(struct scsi_cmnd *srb, struct us_data *us) usb_stor_clear_halt(us, pipe); return USB_STOR_TRANSPORT_FAILED; } +EXPORT_SYMBOL_GPL(usb_stor_CB_transport); /* * Bulk only transport @@ -1156,6 +1163,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us) /* we should never get here, but if we do, we're in trouble */ return USB_STOR_TRANSPORT_ERROR; } +EXPORT_SYMBOL_GPL(usb_stor_Bulk_transport); /*********************************************************************** * Reset routines @@ -1230,6 +1238,7 @@ int usb_stor_CB_reset(struct us_data *us) USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, us->iobuf, CB_RESET_CMD_SIZE); } +EXPORT_SYMBOL_GPL(usb_stor_CB_reset); /* This issues a Bulk-only Reset to the device in question, including * clearing the subsequent endpoint halts that may occur. @@ -1242,6 +1251,7 @@ int usb_stor_Bulk_reset(struct us_data *us) USB_TYPE_CLASS | USB_RECIP_INTERFACE, 0, us->ifnum, NULL, 0); } +EXPORT_SYMBOL_GPL(usb_stor_Bulk_reset); /* Issue a USB port reset to the device. The caller must not hold * us->dev_mutex. diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index b01dade63cb..490ea761398 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -5,7 +5,7 @@ * * Developed with the assistance of: * (c) 2000 David L. Brown, Jr. (usb-storage@davidb.org) - * (c) 2003 Alan Stern (stern@rowland.harvard.edu) + * (c) 2003-2009 Alan Stern (stern@rowland.harvard.edu) * * Initial work by: * (c) 1999 Michael Gee (michael@linuxspecific.com) @@ -118,36 +118,8 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); /* * The entries in this table correspond, line for line, - * with the entries of us_unusual_dev_list[]. + * with the entries in usb_storage_usb_ids[], defined in usual-tables.c. */ -#ifndef CONFIG_USB_LIBUSUAL - -#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ - vendorName, productName,useProtocol, useTransport, \ - initFunction, flags) \ -{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin,bcdDeviceMax), \ - .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } - -#define COMPLIANT_DEV UNUSUAL_DEV - -#define USUAL_DEV(useProto, useTrans, useType) \ -{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ - .driver_info = (USB_US_TYPE_STOR<<24) } - -static struct usb_device_id storage_usb_ids [] = { - -# include "unusual_devs.h" -#undef UNUSUAL_DEV -#undef COMPLIANT_DEV -#undef USUAL_DEV - /* Terminating entry */ - { } -}; - -MODULE_DEVICE_TABLE (usb, storage_usb_ids); -#endif /* CONFIG_USB_LIBUSUAL */ - -/* This is the list of devices we recognize, along with their flag data */ /* The vendor name should be kept at eight characters or less, and * the product name should be kept at 16 characters or less. If a device @@ -179,18 +151,17 @@ MODULE_DEVICE_TABLE (usb, storage_usb_ids); static struct us_unusual_dev us_unusual_dev_list[] = { # include "unusual_devs.h" -# undef UNUSUAL_DEV -# undef COMPLIANT_DEV -# undef USUAL_DEV - - /* Terminating entry */ - { NULL } + { } /* Terminating entry */ }; +#undef UNUSUAL_DEV +#undef COMPLIANT_DEV +#undef USUAL_DEV + #ifdef CONFIG_PM /* Minimal support for suspend and resume */ -static int storage_suspend(struct usb_interface *iface, pm_message_t message) +int usb_stor_suspend(struct usb_interface *iface, pm_message_t message) { struct us_data *us = usb_get_intfdata(iface); @@ -207,8 +178,9 @@ static int storage_suspend(struct usb_interface *iface, pm_message_t message) mutex_unlock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_suspend); -static int storage_resume(struct usb_interface *iface) +int usb_stor_resume(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -221,8 +193,9 @@ static int storage_resume(struct usb_interface *iface) mutex_unlock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_resume); -static int storage_reset_resume(struct usb_interface *iface) +int usb_stor_reset_resume(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -235,6 +208,7 @@ static int storage_reset_resume(struct usb_interface *iface) * the device */ return 0; } +EXPORT_SYMBOL_GPL(usb_stor_reset_resume); #endif /* CONFIG_PM */ @@ -243,7 +217,7 @@ static int storage_reset_resume(struct usb_interface *iface) * a USB port reset, whether from this driver or a different one. */ -static int storage_pre_reset(struct usb_interface *iface) +int usb_stor_pre_reset(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -253,8 +227,9 @@ static int storage_pre_reset(struct usb_interface *iface) mutex_lock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_pre_reset); -static int storage_post_reset(struct usb_interface *iface) +int usb_stor_post_reset(struct usb_interface *iface) { struct us_data *us = usb_get_intfdata(iface); @@ -269,6 +244,7 @@ static int storage_post_reset(struct usb_interface *iface) mutex_unlock(&us->dev_mutex); return 0; } +EXPORT_SYMBOL_GPL(usb_stor_post_reset); /* * fill_inquiry_response takes an unsigned char array (which must @@ -311,6 +287,7 @@ void fill_inquiry_response(struct us_data *us, unsigned char *data, usb_stor_set_xfer_buf(data, data_len, us->srb); } +EXPORT_SYMBOL_GPL(fill_inquiry_response); static int usb_stor_control_thread(void * __us) { @@ -551,20 +528,13 @@ static void adjust_quirks(struct us_data *us) vid, pid, f); } -/* Find an unusual_dev descriptor (always succeeds in the current code) */ -static struct us_unusual_dev *find_unusual(const struct usb_device_id *id) -{ - const int id_index = id - storage_usb_ids; - return &us_unusual_dev_list[id_index]; -} - /* Get the unusual_devs entries and the string descriptors */ -static int get_device_info(struct us_data *us, const struct usb_device_id *id) +static int get_device_info(struct us_data *us, const struct usb_device_id *id, + struct us_unusual_dev *unusual_dev) { struct usb_device *dev = us->pusb_dev; struct usb_interface_descriptor *idesc = &us->pusb_intf->cur_altsetting->desc; - struct us_unusual_dev *unusual_dev = find_unusual(id); /* Store the entries */ us->unusual_dev = unusual_dev; @@ -629,7 +599,7 @@ static int get_device_info(struct us_data *us, const struct usb_device_id *id) } /* Get the transport settings */ -static int get_transport(struct us_data *us) +static void get_transport(struct us_data *us) { switch (us->protocol) { case US_PR_CB: @@ -732,19 +702,11 @@ static int get_transport(struct us_data *us) break; #endif - default: - return -EIO; } - US_DEBUGP("Transport: %s\n", us->transport_name); - - /* fix for single-lun devices */ - if (us->fflags & US_FL_SINGLE_LUN) - us->max_lun = 0; - return 0; } /* Get the protocol settings */ -static int get_protocol(struct us_data *us) +static void get_protocol(struct us_data *us) { switch (us->subclass) { case US_SC_RBC: @@ -794,11 +756,7 @@ static int get_protocol(struct us_data *us) break; #endif - default: - return -EIO; } - US_DEBUGP("Protocol: %s\n", us->protocol_name); - return 0; } /* Get the pipe settings */ @@ -1012,17 +970,15 @@ static int usb_stor_scan_thread(void * __us) } -/* Probe to see if we can drive a newly-connected USB device */ -static int storage_probe(struct usb_interface *intf, - const struct usb_device_id *id) +/* First part of general USB mass-storage probing */ +int usb_stor_probe1(struct us_data **pus, + struct usb_interface *intf, + const struct usb_device_id *id, + struct us_unusual_dev *unusual_dev) { struct Scsi_Host *host; struct us_data *us; int result; - struct task_struct *th; - - if (usb_usual_check_type(id, USB_US_TYPE_STOR)) - return -ENXIO; US_DEBUGP("USB Mass Storage device detected\n"); @@ -1041,7 +997,7 @@ static int storage_probe(struct usb_interface *intf, * Allow 16-byte CDBs and thus > 2TB */ host->max_cmd_len = 16; - us = host_to_us(host); + *pus = us = host_to_us(host); memset(us, 0, sizeof(struct us_data)); mutex_init(&(us->dev_mutex)); init_completion(&us->cmnd_ready); @@ -1054,24 +1010,46 @@ static int storage_probe(struct usb_interface *intf, if (result) goto BadDevice; - /* - * Get the unusual_devs entries and the descriptors - * - * id_index is calculated in the declaration to be the index number - * of the match from the usb_device_id table, so we can find the - * corresponding entry in the private table. - */ - result = get_device_info(us, id); + /* Get the unusual_devs entries and the descriptors */ + result = get_device_info(us, id, unusual_dev); if (result) goto BadDevice; - /* Get the transport, protocol, and pipe settings */ - result = get_transport(us); - if (result) - goto BadDevice; - result = get_protocol(us); - if (result) + /* Get standard transport and protocol settings */ + get_transport(us); + get_protocol(us); + + /* Give the caller a chance to fill in specialized transport + * or protocol settings. + */ + return 0; + +BadDevice: + US_DEBUGP("storage_probe() failed\n"); + release_everything(us); + return result; +} +EXPORT_SYMBOL_GPL(usb_stor_probe1); + +/* Second part of general USB mass-storage probing */ +int usb_stor_probe2(struct us_data *us) +{ + struct task_struct *th; + int result; + + /* Make sure the transport and protocol have both been set */ + if (!us->transport || !us->proto_handler) { + result = -ENXIO; goto BadDevice; + } + US_DEBUGP("Transport: %s\n", us->transport_name); + US_DEBUGP("Protocol: %s\n", us->protocol_name); + + /* fix for single-lun devices */ + if (us->fflags & US_FL_SINGLE_LUN) + us->max_lun = 0; + + /* Find the endpoints and calculate pipe values */ result = get_pipes(us); if (result) goto BadDevice; @@ -1080,7 +1058,7 @@ static int storage_probe(struct usb_interface *intf, result = usb_stor_acquire_resources(us); if (result) goto BadDevice; - result = scsi_add_host(host, &intf->dev); + result = scsi_add_host(us_to_host(us), &us->pusb_intf->dev); if (result) { printk(KERN_WARNING USB_STORAGE "Unable to add the scsi host\n"); @@ -1108,9 +1086,10 @@ BadDevice: release_everything(us); return result; } +EXPORT_SYMBOL_GPL(usb_stor_probe2); -/* Handle a disconnect event from the USB core */ -static void storage_disconnect(struct usb_interface *intf) +/* Handle a USB mass-storage disconnect */ +void usb_stor_disconnect(struct usb_interface *intf) { struct us_data *us = usb_get_intfdata(intf); @@ -1118,6 +1097,42 @@ static void storage_disconnect(struct usb_interface *intf) quiesce_and_remove_host(us); release_everything(us); } +EXPORT_SYMBOL_GPL(usb_stor_disconnect); + +/* The main probe routine for standard devices */ +static int storage_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + /* + * If libusual is configured, let it decide whether a standard + * device should be handled by usb-storage or by ub. + * If the device isn't standard (is handled by a subdriver + * module) then don't accept it. + */ + if (usb_usual_check_type(id, USB_US_TYPE_STOR) || + usb_usual_ignore_device(intf)) + return -ENXIO; + + /* + * Call the general probe procedures. + * + * The unusual_dev_list array is parallel to the usb_storage_usb_ids + * table, so we use the index of the id entry to find the + * corresponding unusual_devs entry. + */ + result = usb_stor_probe1(&us, intf, id, + (id - usb_storage_usb_ids) + us_unusual_dev_list); + if (result) + return result; + + /* No special transport or protocol settings in the main module */ + + result = usb_stor_probe2(us); + return result; +} /*********************************************************************** * Initialization and registration @@ -1126,15 +1141,13 @@ static void storage_disconnect(struct usb_interface *intf) static struct usb_driver usb_storage_driver = { .name = "usb-storage", .probe = storage_probe, - .disconnect = storage_disconnect, -#ifdef CONFIG_PM - .suspend = storage_suspend, - .resume = storage_resume, - .reset_resume = storage_reset_resume, -#endif - .pre_reset = storage_pre_reset, - .post_reset = storage_post_reset, - .id_table = storage_usb_ids, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = usb_storage_usb_ids, .soft_unbind = 1, }; diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h index 65e674e4be9..2609efb2bd7 100644 --- a/drivers/usb/storage/usb.h +++ b/drivers/usb/storage/usb.h @@ -177,4 +177,25 @@ extern void fill_inquiry_response(struct us_data *us, #define scsi_unlock(host) spin_unlock_irq(host->host_lock) #define scsi_lock(host) spin_lock_irq(host->host_lock) +/* General routines provided by the usb-storage standard core */ +#ifdef CONFIG_PM +extern int usb_stor_suspend(struct usb_interface *iface, pm_message_t message); +extern int usb_stor_resume(struct usb_interface *iface); +extern int usb_stor_reset_resume(struct usb_interface *iface); +#else +#define usb_stor_suspend NULL +#define usb_stor_resume NULL +#define usb_stor_reset_resume NULL +#endif + +extern int usb_stor_pre_reset(struct usb_interface *iface); +extern int usb_stor_post_reset(struct usb_interface *iface); + +extern int usb_stor_probe1(struct us_data **pus, + struct usb_interface *intf, + const struct usb_device_id *id, + struct us_unusual_dev *unusual_dev); +extern int usb_stor_probe2(struct us_data *us); +extern void usb_stor_disconnect(struct usb_interface *intf); + #endif diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c new file mode 100644 index 00000000000..1924e322940 --- /dev/null +++ b/drivers/usb/storage/usual-tables.c @@ -0,0 +1,105 @@ +/* Driver for USB Mass Storage devices + * Usual Tables File for usb-storage and libusual + * + * Copyright (C) 2009 Alan Stern (stern@rowland.harvard.edu) + * + * Please see http://www.one-eyed-alien.net/~mdharm/linux-usb for more + * information about this driver. + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +#define COMPLIANT_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags) } + +#define USUAL_DEV(useProto, useTrans, useType) \ +{ USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans), \ + .driver_info = ((useType)<<24) } + +struct usb_device_id usb_storage_usb_ids[] = { +# include "unusual_devs.h" + { } /* Terminating entry */ +}; +EXPORT_SYMBOL_GPL(usb_storage_usb_ids); + +MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids); + +#undef UNUSUAL_DEV +#undef COMPLIANT_DEV +#undef USUAL_DEV + + +/* + * The table of devices to ignore + */ +struct ignore_entry { + u16 vid, pid, bcdmin, bcdmax; +}; + +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ \ + .vid = id_vendor, \ + .pid = id_product, \ + .bcdmin = bcdDeviceMin, \ + .bcdmax = bcdDeviceMax, \ +} + +static struct ignore_entry ignore_ids[] = { + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + +/* Return an error if a device is in the ignore_ids list */ +int usb_usual_ignore_device(struct usb_interface *intf) +{ + struct usb_device *udev; + unsigned vid, pid, bcd; + struct ignore_entry *p; + + udev = interface_to_usbdev(intf); + vid = le16_to_cpu(udev->descriptor.idVendor); + pid = le16_to_cpu(udev->descriptor.idProduct); + bcd = le16_to_cpu(udev->descriptor.bcdDevice); + + for (p = ignore_ids; p->vid; ++p) { + if (p->vid == vid && p->pid == pid && + p->bcdmin <= bcd && p->bcdmax >= bcd) + return -ENXIO; + } + return 0; +} +EXPORT_SYMBOL_GPL(usb_usual_ignore_device); -- cgit v1.2.3 From 0ff71883b2d60136430458413c135d545c69b0c4 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:49 -0500 Subject: usb-storage: make sddr09 a separate module This patch (as1207) converts usb-storage's sddr09 subdriver into a separate module. An unexpected complication arises because of DPCM devices, in which one LUN uses the sddr09 transport and one uses the standard CB transport. Since these devices can be used even when USB_STORAGE_SDDR09 isn't configured, their entries in unusual_devs.h require special treatment. If SDDR09 isn't configured then the entries remain in unusual_devs.h; if it is then the entries are present in unusual_sddr09.h instead. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 5 +- drivers/usb/storage/sddr09.c | 107 +++++++++++++++++++++++++++++++++-- drivers/usb/storage/sddr09.h | 38 ------------- drivers/usb/storage/unusual_devs.h | 50 +++------------- drivers/usb/storage/unusual_sddr09.h | 56 ++++++++++++++++++ drivers/usb/storage/usb.c | 21 ------- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 174 insertions(+), 108 deletions(-) delete mode 100644 drivers/usb/storage/sddr09.h create mode 100644 drivers/usb/storage/unusual_sddr09.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 5c367566be8..7be8899f255 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -83,13 +83,15 @@ config USB_STORAGE_USBAT - Sandisk ImageMate SDDR-05b config USB_STORAGE_SDDR09 - bool "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support" + tristate "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support" depends on USB_STORAGE help Say Y here to include additional code to support the Sandisk SDDR-09 SmartMedia reader in the USB Mass Storage driver. Also works for the Microtech Zio! CompactFlash/SmartMedia reader. + If this driver is compiled as a module, it will be named ums-sddr09. + config USB_STORAGE_SDDR55 bool "SanDisk SDDR-55 SmartMedia support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index a9e475e127a..a52740a9560 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o -usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR09) += sddr09.o usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o @@ -30,3 +29,7 @@ ifeq ($(CONFIG_USB_LIBUSUAL),) else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif + +obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o + +ums-sddr09-objs := sddr09.o diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index b667c7d2b83..170ad86b2d3 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -41,6 +41,7 @@ */ #include +#include #include #include @@ -51,7 +52,50 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "sddr09.h" + + +static int usb_stor_sddr09_dpcm_init(struct us_data *us); +static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); +static int usb_stor_sddr09_init(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id sddr09_usb_ids[] = { +# include "unusual_sddr09.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, sddr09_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev sddr09_unusual_dev_list[] = { +# include "unusual_sddr09.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) @@ -1406,7 +1450,7 @@ sddr09_common_init(struct us_data *us) { * unusual devices list but called from here then LUN 0 of the combo reader * is not recognized. But I do not know what precisely these calls do. */ -int +static int usb_stor_sddr09_dpcm_init(struct us_data *us) { int result; unsigned char *data = us->iobuf; @@ -1456,7 +1500,7 @@ usb_stor_sddr09_dpcm_init(struct us_data *us) { /* * Transport for the Microtech DPCM-USB */ -int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) +static int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) { int ret; @@ -1498,7 +1542,7 @@ int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us) /* * Transport for the Sandisk SDDR-09 */ -int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) +static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) { static unsigned char sensekey = 0, sensecode = 0; static unsigned char havefakesense = 0; @@ -1697,7 +1741,60 @@ int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us) /* * Initialization routine for the sddr09 subdriver */ -int +static int usb_stor_sddr09_init(struct us_data *us) { return sddr09_common_init(us); } + +static int sddr09_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - sddr09_usb_ids) + sddr09_unusual_dev_list); + if (result) + return result; + + if (us->protocol == US_PR_DPCM_USB) { + us->transport_name = "Control/Bulk-EUSB/SDDR09"; + us->transport = dpcm_transport; + us->transport_reset = usb_stor_CB_reset; + us->max_lun = 1; + } else { + us->transport_name = "EUSB/SDDR09"; + us->transport = sddr09_transport; + us->transport_reset = usb_stor_CB_reset; + us->max_lun = 0; + } + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver sddr09_driver = { + .name = "ums-sddr09", + .probe = sddr09_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = sddr09_usb_ids, + .soft_unbind = 1, +}; + +static int __init sddr09_init(void) +{ + return usb_register(&sddr09_driver); +} + +static void __exit sddr09_exit(void) +{ + usb_deregister(&sddr09_driver); +} + +module_init(sddr09_init); +module_exit(sddr09_exit); diff --git a/drivers/usb/storage/sddr09.h b/drivers/usb/storage/sddr09.h deleted file mode 100644 index b701172e12e..00000000000 --- a/drivers/usb/storage/sddr09.h +++ /dev/null @@ -1,38 +0,0 @@ -/* Driver for SanDisk SDDR-09 SmartMedia reader - * Header File - * - * Current development and maintenance by: - * (c) 2000 Robert Baruch (autophile@dol.net) - * (c) 2002 Andries Brouwer (aeb@cwi.nl) - * - * See sddr09.c for more explanation - * - * 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, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_SHUTTLE_EUSB_SDDR09_H -#define _USB_SHUTTLE_EUSB_SDDR09_H - -/* Sandisk SDDR-09 stuff */ - -extern int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int usb_stor_sddr09_init(struct us_data *us); - -/* Microtech DPCM-USB stuff */ - -extern int dpcm_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int usb_stor_sddr09_dpcm_init(struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index cfde74a6faa..1fe7062f1cd 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -53,6 +53,11 @@ * as opposed to devices that do something strangely or wrongly. */ +#if !defined(CONFIG_USB_STORAGE_SDDR09) && \ + !defined(CONFIG_USB_STORAGE_SDDR09_MODULE) +#define NO_SDDR09 +#endif + /* patch submitted by Vivian Bregier */ UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, @@ -246,12 +251,7 @@ UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, - "Microtech", - "CameraMate (DPCM_USB)", - US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), -#else +#ifdef NO_SDDR09 UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, "Microtech", "CameraMate", @@ -467,20 +467,7 @@ UNUSUAL_DEV( 0x04e6, 0x0002, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, - "Sandisk", - "ImageMate SDDR09", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), - -/* This entry is from Andries.Brouwer@cwi.nl */ -UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, - "SCM Microsystems", - "eUSB SmartMedia / CompactFlash Adapter", - US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, - 0), -#else +#ifdef NO_SDDR09 UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, "SCM Microsystems", "eUSB CompactFlash Adapter", @@ -935,14 +922,6 @@ UNUSUAL_DEV( 0x0644, 0x0000, 0x0100, 0x0100, "Floppy Drive", US_SC_UFI, US_PR_CB, NULL, 0 ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, - "Olympus", - "Camedia MAUSB-2", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), -#endif - /* Reported by Darsen Lu */ UNUSUAL_DEV( 0x066f, 0x8000, 0x0001, 0x0001, "SigmaTel", @@ -1057,14 +1036,6 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, - "Sandisk", - "ImageMate SDDR-09", - US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, - 0), -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, "Freecom", @@ -1091,12 +1062,7 @@ UNUSUAL_DEV( 0x07af, 0x0005, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, usb_stor_euscsi_init, US_FL_SCM_MULT_TARG ), -#ifdef CONFIG_USB_STORAGE_SDDR09 -UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, - "Microtech", - "CameraMate (DPCM_USB)", - US_SC_SCSI, US_PR_DPCM_USB, NULL, 0 ), -#else +#ifdef NO_SDDR09 UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, "Microtech", "CameraMate", diff --git a/drivers/usb/storage/unusual_sddr09.h b/drivers/usb/storage/unusual_sddr09.h new file mode 100644 index 00000000000..50cab511a4d --- /dev/null +++ b/drivers/usb/storage/unusual_sddr09.h @@ -0,0 +1,56 @@ +/* Unusual Devices File for SanDisk SDDR-09 SmartMedia reader + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_SDDR09) || \ + defined(CONFIG_USB_STORAGE_SDDR09_MODULE) + +UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, + "Microtech", + "CameraMate (DPCM_USB)", + US_SC_SCSI, US_PR_DPCM_USB, NULL, 0), + +UNUSUAL_DEV( 0x04e6, 0x0003, 0x0000, 0x9999, + "Sandisk", + "ImageMate SDDR09", + US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + 0), + +/* This entry is from Andries.Brouwer@cwi.nl */ +UNUSUAL_DEV( 0x04e6, 0x0005, 0x0100, 0x0208, + "SCM Microsystems", + "eUSB SmartMedia / CompactFlash Adapter", + US_SC_SCSI, US_PR_DPCM_USB, usb_stor_sddr09_dpcm_init, + 0), + +UNUSUAL_DEV( 0x066b, 0x0105, 0x0100, 0x0100, + "Olympus", + "Camedia MAUSB-2", + US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + 0), + +UNUSUAL_DEV( 0x0781, 0x0200, 0x0000, 0x9999, + "Sandisk", + "ImageMate SDDR-09", + US_SC_SCSI, US_PR_EUSB_SDDR09, usb_stor_sddr09_init, + 0), + +UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, + "Microtech", + "CameraMate (DPCM_USB)", + US_SC_SCSI, US_PR_DPCM_USB, NULL, 0), + +#endif /* defined(CONFIG_USB_STORAGE_SDDR09) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 490ea761398..33cce41a5e8 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_USBAT #include "shuttle_usbat.h" #endif -#ifdef CONFIG_USB_STORAGE_SDDR09 -#include "sddr09.h" -#endif #ifdef CONFIG_USB_STORAGE_SDDR55 #include "sddr55.h" #endif @@ -631,15 +628,6 @@ static void get_transport(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_SDDR09 - case US_PR_EUSB_SDDR09: - us->transport_name = "EUSB/SDDR09"; - us->transport = sddr09_transport; - us->transport_reset = usb_stor_CB_reset; - us->max_lun = 0; - break; -#endif - #ifdef CONFIG_USB_STORAGE_SDDR55 case US_PR_SDDR55: us->transport_name = "SDDR55"; @@ -649,15 +637,6 @@ static void get_transport(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_DPCM - case US_PR_DPCM_USB: - us->transport_name = "Control/Bulk-EUSB/SDDR09"; - us->transport = dpcm_transport; - us->transport_reset = usb_stor_CB_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: us->transport_name = "Freecom"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 1924e322940..f808c5262d0 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_sddr09.h" { } /* Terminating entry */ }; -- cgit v1.2.3 From 32d5493eb83a217c3b1eba4b98cd6d19864f71a8 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:54 -0500 Subject: usb-storage: make isd200 a separate module This patch (as1208) converts usb-storage's isd200 subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/isd200.c | 94 ++++++++++++++++++++++++++++++++++-- drivers/usb/storage/isd200.h | 31 ------------ drivers/usb/storage/unusual_devs.h | 42 ---------------- drivers/usb/storage/unusual_isd200.h | 57 ++++++++++++++++++++++ drivers/usb/storage/usb.c | 10 ---- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 154 insertions(+), 88 deletions(-) delete mode 100644 drivers/usb/storage/isd200.h create mode 100644 drivers/usb/storage/unusual_isd200.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7be8899f255..fc356a770a7 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -46,7 +46,7 @@ config USB_STORAGE_FREECOM Freecom has a web page at . config USB_STORAGE_ISD200 - bool "ISD-200 USB/ATA Bridge support" + tristate "ISD-200 USB/ATA Bridge support" depends on USB_STORAGE ---help--- Say Y here if you want to use USB Mass Store devices based @@ -61,6 +61,8 @@ config USB_STORAGE_ISD200 - CyQ've CQ8060A CDRW drive - Planex eXtreme Drive RX-25HU USB-IDE cable (not model RX-25U) + If this driver is compiled as a module, it will be named ums-isd200. + config USB_STORAGE_USBAT bool "USBAT/USBAT02-based storage support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index a52740a9560..b47f94e59fd 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -13,7 +13,6 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o -usb-storage-obj-$(CONFIG_USB_STORAGE_ISD200) += isd200.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o @@ -30,6 +29,8 @@ else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif +obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o +ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index 383abf2516a..df943008538 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -44,6 +44,7 @@ #include #include +#include #include #include #include @@ -57,7 +58,50 @@ #include "protocol.h" #include "debug.h" #include "scsiglue.h" -#include "isd200.h" + + +static int isd200_Initialization(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id isd200_usb_ids[] = { +# include "unusual_isd200.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, isd200_usb_ids); + +#undef UNUSUAL_DEV +#undef USUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev isd200_unusual_dev_list[] = { +# include "unusual_isd200.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV +#undef USUAL_DEV /* Timeout defines (in Seconds) */ @@ -1518,7 +1562,7 @@ static int isd200_init_info(struct us_data *us) * Initialization for the ISD200 */ -int isd200_Initialization(struct us_data *us) +static int isd200_Initialization(struct us_data *us) { US_DEBUGP("ISD200 Initialization...\n"); @@ -1549,7 +1593,7 @@ int isd200_Initialization(struct us_data *us) * */ -void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) +static void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) { int sendToTransport = 1, orig_bufflen; union ata_cdb ataCdb; @@ -1570,3 +1614,47 @@ void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us) isd200_srb_set_bufflen(srb, orig_bufflen); } + +static int isd200_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - isd200_usb_ids) + isd200_unusual_dev_list); + if (result) + return result; + + us->protocol_name = "ISD200 ATA/ATAPI"; + us->proto_handler = isd200_ata_command; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver isd200_driver = { + .name = "ums-isd200", + .probe = isd200_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = isd200_usb_ids, + .soft_unbind = 1, +}; + +static int __init isd200_init(void) +{ + return usb_register(&isd200_driver); +} + +static void __exit isd200_exit(void) +{ + usb_deregister(&isd200_driver); +} + +module_init(isd200_init); +module_exit(isd200_exit); diff --git a/drivers/usb/storage/isd200.h b/drivers/usb/storage/isd200.h deleted file mode 100644 index 0a35f4fa78f..00000000000 --- a/drivers/usb/storage/isd200.h +++ /dev/null @@ -1,31 +0,0 @@ -/* Header File for In-System Design, Inc. ISD200 ASIC - * - * First release - * - * Current development and maintenance by: - * (c) 2000 In-System Design, Inc. (support@in-system.com) - * - * See isd200.c for more information. - * - * 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, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_ISD200_H -#define _USB_ISD200_H - -extern void isd200_ata_command(struct scsi_cmnd *srb, struct us_data *us); -extern int isd200_Initialization(struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 1fe7062f1cd..83ce1d33554 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -632,14 +632,6 @@ UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_ISD200 -UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110, - "Sony", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), -#endif - /* Submitted by Olaf Hering, SuSE Bugzilla #49049 */ UNUSUAL_DEV( 0x054c, 0x002c, 0x0501, 0x2000, "Sony", @@ -785,32 +777,6 @@ UNUSUAL_DEV( 0x05ab, 0x0060, 0x1104, 0x1110, US_SC_SCSI, US_PR_BULK, NULL, US_FL_NEED_OVERRIDE ), -#ifdef CONFIG_USB_STORAGE_ISD200 -UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, - "In-System", - "USB/IDE Bridge (ATA/ATAPI)", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x05ab, 0x0301, 0x0100, 0x0110, - "In-System", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x05ab, 0x0351, 0x0100, 0x0110, - "In-System", - "Portable USB Harddrive V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), - -UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110, - "In-System", - "USB Storage Adapter V2", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), -#endif - /* Submitted by Sven Anderson * There are at least four ProductIDs used for iPods, so I added 0x1202 and * 0x1204. They just need the US_FL_FIX_CAPACITY. As the bcdDevice appears @@ -1375,14 +1341,6 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SANE_SENSE ), -#ifdef CONFIG_USB_STORAGE_ISD200 -UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, - "ATI", - "USB Cable 205", - US_SC_ISD200, US_PR_BULK, isd200_Initialization, - 0 ), -#endif - #ifdef CONFIG_USB_STORAGE_DATAFAB UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, "Acomdata", diff --git a/drivers/usb/storage/unusual_isd200.h b/drivers/usb/storage/unusual_isd200.h new file mode 100644 index 00000000000..0d99dde3382 --- /dev/null +++ b/drivers/usb/storage/unusual_isd200.h @@ -0,0 +1,57 @@ +/* Unusual Devices File for In-System Design, Inc. ISD200 ASIC + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_ISD200) || \ + defined(CONFIG_USB_STORAGE_ISD200_MODULE) + +UNUSUAL_DEV( 0x054c, 0x002b, 0x0100, 0x0110, + "Sony", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x0031, 0x0100, 0x0110, + "In-System", + "USB/IDE Bridge (ATA/ATAPI)", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x0301, 0x0100, 0x0110, + "In-System", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x0351, 0x0100, 0x0110, + "In-System", + "Portable USB Harddrive V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110, + "In-System", + "USB Storage Adapter V2", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +UNUSUAL_DEV( 0x0bf6, 0xa001, 0x0100, 0x0110, + "ATI", + "USB Cable 205", + US_SC_ISD200, US_PR_BULK, isd200_Initialization, + 0), + +#endif /* defined(CONFIG_USB_STORAGE_ISD200) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 33cce41a5e8..e65cbba452b 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -75,9 +75,6 @@ #ifdef CONFIG_USB_STORAGE_FREECOM #include "freecom.h" #endif -#ifdef CONFIG_USB_STORAGE_ISD200 -#include "isd200.h" -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB #include "datafab.h" #endif @@ -721,13 +718,6 @@ static void get_protocol(struct us_data *us) us->proto_handler = usb_stor_ufi_command; break; -#ifdef CONFIG_USB_STORAGE_ISD200 - case US_SC_ISD200: - us->protocol_name = "ISD200 ATA/ATAPI"; - us->proto_handler = isd200_ata_command; - break; -#endif - #ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB case US_SC_CYP_ATACB: us->protocol_name = "Transparent SCSI with Cypress ATACB"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index f808c5262d0..61ebddcc9ae 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_isd200.h" # include "unusual_sddr09.h" { } /* Terminating entry */ }; -- cgit v1.2.3 From 70fcc0050733a7cd1b452cfa3de3a9b376412565 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:47:59 -0500 Subject: usb-storage: make sddr55 a separate module This patch (as1209) converts usb-storage's sddr55 subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/sddr55.c | 92 ++++++++++++++++++++++++++++++++++-- drivers/usb/storage/sddr55.h | 32 ------------- drivers/usb/storage/unusual_devs.h | 32 ------------- drivers/usb/storage/unusual_sddr55.h | 44 +++++++++++++++++ drivers/usb/storage/usb.c | 12 ----- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 139 insertions(+), 81 deletions(-) delete mode 100644 drivers/usb/storage/sddr55.h create mode 100644 drivers/usb/storage/unusual_sddr55.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index fc356a770a7..e6cc245257f 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -95,12 +95,14 @@ config USB_STORAGE_SDDR09 If this driver is compiled as a module, it will be named ums-sddr09. config USB_STORAGE_SDDR55 - bool "SanDisk SDDR-55 SmartMedia support" + tristate "SanDisk SDDR-55 SmartMedia support" depends on USB_STORAGE help Say Y here to include additional code to support the Sandisk SDDR-55 SmartMedia reader in the USB Mass Storage driver. + If this driver is compiled as a module, it will be named ums-sddr55. + config USB_STORAGE_JUMPSHOT bool "Lexar Jumpshot Compact Flash Reader" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index b47f94e59fd..5fb7847e41a 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o -usb-storage-obj-$(CONFIG_USB_STORAGE_SDDR55) += sddr55.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o @@ -31,6 +30,8 @@ endif obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o +obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o +ums-sddr55-objs := sddr55.o diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index 5a0106ba256..e97716f8eb0 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -24,6 +24,7 @@ #include #include +#include #include #include @@ -33,7 +34,45 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "sddr55.h" + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id sddr55_usb_ids[] = { +# include "unusual_sddr55.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, sddr55_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev sddr55_unusual_dev_list[] = { +# include "unusual_sddr55.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) @@ -513,7 +552,8 @@ static int sddr55_read_deviceID(struct us_data *us, } -int sddr55_reset(struct us_data *us) { +static int sddr55_reset(struct us_data *us) +{ return 0; } @@ -734,7 +774,7 @@ static void sddr55_card_info_destructor(void *extra) { /* * Transport for the Sandisk SDDR-55 */ -int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) +static int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) { int result; static unsigned char inquiry_response[8] = { @@ -931,3 +971,49 @@ int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; // FIXME: sense buffer? } + +static int sddr55_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - sddr55_usb_ids) + sddr55_unusual_dev_list); + if (result) + return result; + + us->transport_name = "SDDR55"; + us->transport = sddr55_transport; + us->transport_reset = sddr55_reset; + us->max_lun = 0; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver sddr55_driver = { + .name = "ums-sddr55", + .probe = sddr55_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = sddr55_usb_ids, + .soft_unbind = 1, +}; + +static int __init sddr55_init(void) +{ + return usb_register(&sddr55_driver); +} + +static void __exit sddr55_exit(void) +{ + usb_deregister(&sddr55_driver); +} + +module_init(sddr55_init); +module_exit(sddr55_exit); diff --git a/drivers/usb/storage/sddr55.h b/drivers/usb/storage/sddr55.h deleted file mode 100644 index a815a0470c8..00000000000 --- a/drivers/usb/storage/sddr55.h +++ /dev/null @@ -1,32 +0,0 @@ -/* Driver for SanDisk SDDR-55 SmartMedia reader - * Header File - * - * Current development and maintenance by: - * (c) 2002 Simon Munton - * - * See sddr55.c for more explanation - * - * 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, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_SHUTTLE_EUSB_SDDR55_H -#define _USB_SHUTTLE_EUSB_SDDR55_H - -/* Sandisk SDDR-55 stuff */ - -extern int sddr55_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int sddr55_reset(struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 83ce1d33554..50034e141f9 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1098,15 +1098,6 @@ UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, US_SC_SCSI, US_PR_DATAFAB, NULL, 0 ), #endif - -#ifdef CONFIG_USB_STORAGE_SDDR55 -/* Contributed by Peter Waechtler */ -UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, - "Datafab", - "MDSM-B reader", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_FIX_INQUIRY ), -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB /* Submitted by Olaf Hering */ @@ -1116,14 +1107,6 @@ UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, US_SC_SCSI, US_PR_DATAFAB, NULL, 0 ), #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 -/* SM part - aeb */ -UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, - "Datafab Systems, Inc.", - "USB to CF + SM Combo (LC1)", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_SINGLE_LUN ), -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB /* Reported by Felix Moeller @@ -1348,13 +1331,6 @@ UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, US_SC_SCSI, US_PR_DATAFAB, NULL, US_FL_SINGLE_LUN ), #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 -UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, - "Acomdata", - "SM", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_SINGLE_LUN ), -#endif UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", @@ -2041,14 +2017,6 @@ UNUSUAL_DEV( 0x4146, 0xba01, 0x0100, 0x0100, "Micro Mini 1GB", US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), -#ifdef CONFIG_USB_STORAGE_SDDR55 -UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, - "Sandisk", - "ImageMate SDDR55", - US_SC_SCSI, US_PR_SDDR55, NULL, - US_FL_SINGLE_LUN), -#endif - /* Reported by Andrew Simmons */ UNUSUAL_DEV( 0xed06, 0x4500, 0x0001, 0x0001, "DataStor", diff --git a/drivers/usb/storage/unusual_sddr55.h b/drivers/usb/storage/unusual_sddr55.h new file mode 100644 index 00000000000..ae81ef7a1cf --- /dev/null +++ b/drivers/usb/storage/unusual_sddr55.h @@ -0,0 +1,44 @@ +/* Unusual Devices File for SanDisk SDDR-55 SmartMedia reader + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_SDDR55) || \ + defined(CONFIG_USB_STORAGE_SDDR55_MODULE) + +/* Contributed by Peter Waechtler */ +UNUSUAL_DEV( 0x07c4, 0xa103, 0x0000, 0x9999, + "Datafab", + "MDSM-B reader", + US_SC_SCSI, US_PR_SDDR55, NULL, + US_FL_FIX_INQUIRY), + +/* SM part - aeb */ +UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, + "Datafab Systems, Inc.", + "USB to CF + SM Combo (LC1)", + US_SC_SCSI, US_PR_SDDR55, NULL, 0), + +UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, + "Acomdata", + "SM", + US_SC_SCSI, US_PR_SDDR55, NULL, 0), + +UNUSUAL_DEV( 0x55aa, 0xa103, 0x0000, 0x9999, + "Sandisk", + "ImageMate SDDR55", + US_SC_SCSI, US_PR_SDDR55, NULL, 0), + +#endif /* defined(CONFIG_USB_STORAGE_SDDR55) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index e65cbba452b..238f271d817 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_USBAT #include "shuttle_usbat.h" #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 -#include "sddr55.h" -#endif #ifdef CONFIG_USB_STORAGE_FREECOM #include "freecom.h" #endif @@ -625,15 +622,6 @@ static void get_transport(struct us_data *us) break; #endif -#ifdef CONFIG_USB_STORAGE_SDDR55 - case US_PR_SDDR55: - us->transport_name = "SDDR55"; - us->transport = sddr55_transport; - us->transport_reset = sddr55_reset; - us->max_lun = 0; - break; -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: us->transport_name = "Freecom"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 61ebddcc9ae..5f2703fa48e 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -79,6 +79,7 @@ struct ignore_entry { static struct ignore_entry ignore_ids[] = { # include "unusual_isd200.h" # include "unusual_sddr09.h" +# include "unusual_sddr55.h" { } /* Terminating entry */ }; -- cgit v1.2.3 From fcdb51401f7f695b7fb782721b2e33372c5a06ce Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:04 -0500 Subject: usb-storage: make cypress_atacb a separate module This patch (as1210) converts usb-storage's cypress_atacb subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/cypress_atacb.c | 88 ++++++++++++++++++++++++++++++++++- drivers/usb/storage/cypress_atacb.h | 25 ---------- drivers/usb/storage/unusual_cypress.h | 34 ++++++++++++++ drivers/usb/storage/unusual_devs.h | 16 ------- drivers/usb/storage/usb.c | 11 ----- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 127 insertions(+), 55 deletions(-) delete mode 100644 drivers/usb/storage/cypress_atacb.h create mode 100644 drivers/usb/storage/unusual_cypress.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index e6cc245257f..2c73fa97d94 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -146,7 +146,7 @@ config USB_STORAGE_KARMA operation. config USB_STORAGE_CYPRESS_ATACB - bool "SAT emulation on Cypress USB/ATA Bridge with ATACB" + tristate "SAT emulation on Cypress USB/ATA Bridge with ATACB" depends on USB_STORAGE ---help--- Say Y here if you want to use SAT (ata pass through) on devices based @@ -156,6 +156,8 @@ config USB_STORAGE_CYPRESS_ATACB If you say no here your device will still work with the standard usb mass storage class. + If this driver is compiled as a module, it will be named ums-cypress. + config USB_LIBUSUAL bool "The shared table of common (or usual) storage devices" depends on USB diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 5fb7847e41a..0650f022e56 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -17,7 +17,6 @@ usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o -usb-storage-obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += cypress_atacb.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) @@ -28,10 +27,12 @@ else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif +obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o +ums-cypress-objs := cypress_atacb.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 9466a99baab..19306f7b1da 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -19,6 +19,7 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include #include #include #include @@ -29,6 +30,46 @@ #include "scsiglue.h" #include "debug.h" + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id cypress_usb_ids[] = { +# include "unusual_cypress.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, cypress_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev cypress_unusual_dev_list[] = { +# include "unusual_cypress.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + /* * ATACB is a protocol used on cypress usb<->ata bridge to * send raw ATA command over mass storage @@ -36,7 +77,7 @@ * More info that be found on cy7c68310_8.pdf and cy7c68300c_8.pdf * datasheet from cypress.com. */ -void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) +static void cypress_atacb_passthrough(struct scsi_cmnd *srb, struct us_data *us) { unsigned char save_cmnd[MAX_COMMAND_SIZE]; @@ -197,3 +238,48 @@ end: if (srb->cmnd[0] == ATA_12) srb->cmd_len = 12; } + + +static int cypress_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - cypress_usb_ids) + cypress_unusual_dev_list); + if (result) + return result; + + us->protocol_name = "Transparent SCSI with Cypress ATACB"; + us->proto_handler = cypress_atacb_passthrough; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver cypress_driver = { + .name = "ums-cypress", + .probe = cypress_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = cypress_usb_ids, + .soft_unbind = 1, +}; + +static int __init cypress_init(void) +{ + return usb_register(&cypress_driver); +} + +static void __exit cypress_exit(void) +{ + usb_deregister(&cypress_driver); +} + +module_init(cypress_init); +module_exit(cypress_exit); diff --git a/drivers/usb/storage/cypress_atacb.h b/drivers/usb/storage/cypress_atacb.h deleted file mode 100644 index fbada898d56..00000000000 --- a/drivers/usb/storage/cypress_atacb.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Support for emulating SAT (ata pass through) on devices based - * on the Cypress USB/ATA bridge supporting ATACB. - * - * Copyright (c) 2008 Matthieu Castet (castet.matthieu@free.fr) - * - * 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, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _CYPRESS_ATACB_H_ -#define _CYPRESS_ATACB_H_ -extern void cypress_atacb_passthrough(struct scsi_cmnd*, struct us_data*); -#endif diff --git a/drivers/usb/storage/unusual_cypress.h b/drivers/usb/storage/unusual_cypress.h new file mode 100644 index 00000000000..44be6d75dab --- /dev/null +++ b/drivers/usb/storage/unusual_cypress.h @@ -0,0 +1,34 @@ +/* Unusual Devices File for devices based on the Cypress USB/ATA bridge + * with support for ATACB + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || \ + defined(CONFIG_USB_STORAGE_CYPRESS_ATACB_MODULE) + +/* CY7C68300 : support atacb */ +UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, + "Cypress", + "Cypress AT2LP", + US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), + +/* CY7C68310 : support atacb and atacb2 */ +UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, + "Cypress", + "Cypress ISD-300LP", + US_SC_CYP_ATACB, US_PR_DEVICE, NULL, 0), + +#endif /* defined(CONFIG_USB_STORAGE_CYPRESS_ATACB) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 50034e141f9..eff97aed7bf 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -375,22 +375,6 @@ UNUSUAL_DEV( 0x04b3, 0x4001, 0x0110, 0x0110, US_SC_DEVICE, US_PR_CB, NULL, US_FL_MAX_SECTORS_MIN), -#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB -/* CY7C68300 : support atacb */ -UNUSUAL_DEV( 0x04b4, 0x6830, 0x0000, 0x9999, - "Cypress", - "Cypress AT2LP", - US_SC_CYP_ATACB, US_PR_DEVICE, NULL, - 0), - -/* CY7C68310 : support atacb and atacb2 */ -UNUSUAL_DEV( 0x04b4, 0x6831, 0x0000, 0x9999, - "Cypress", - "Cypress ISD-300LP", - US_SC_CYP_ATACB, US_PR_DEVICE, NULL, - 0), -#endif - /* Reported by Simon Levitt * This entry needs Sub and Proto fields */ UNUSUAL_DEV( 0x04b8, 0x0601, 0x0100, 0x0100, diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 238f271d817..241e1944cf1 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -87,9 +87,6 @@ #ifdef CONFIG_USB_STORAGE_KARMA #include "karma.h" #endif -#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB -#include "cypress_atacb.h" -#endif #include "sierra_ms.h" #include "option_ms.h" @@ -705,14 +702,6 @@ static void get_protocol(struct us_data *us) us->protocol_name = "Uniform Floppy Interface (UFI)"; us->proto_handler = usb_stor_ufi_command; break; - -#ifdef CONFIG_USB_STORAGE_CYPRESS_ATACB - case US_SC_CYP_ATACB: - us->protocol_name = "Transparent SCSI with Cypress ATACB"; - us->proto_handler = cypress_atacb_passthrough; - break; -#endif - } } diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 5f2703fa48e..be461ee9f00 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_cypress.h" # include "unusual_isd200.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" -- cgit v1.2.3 From 26d6818f19d0ab018f28a20d699511c1efdf508b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:08 -0500 Subject: usb-storage: make shuttle_usbat a separate module This patch (as1211) converts usb-storage's shuttle_usbat subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/shuttle_usbat.c | 199 ++++++++++++++++++++++++++++++++---- drivers/usb/storage/shuttle_usbat.h | 123 ---------------------- drivers/usb/storage/unusual_devs.h | 28 ----- drivers/usb/storage/unusual_usbat.h | 43 ++++++++ drivers/usb/storage/usb.c | 12 --- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 227 insertions(+), 186 deletions(-) delete mode 100644 drivers/usb/storage/shuttle_usbat.h create mode 100644 drivers/usb/storage/unusual_usbat.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 2c73fa97d94..44c6b1940f7 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -64,7 +64,7 @@ config USB_STORAGE_ISD200 If this driver is compiled as a module, it will be named ums-isd200. config USB_STORAGE_USBAT - bool "USBAT/USBAT02-based storage support" + tristate "USBAT/USBAT02-based storage support" depends on USB_STORAGE help Say Y here to include additional code to support storage devices @@ -84,6 +84,8 @@ config USB_STORAGE_USBAT - RCA LYRA MP3 portable - Sandisk ImageMate SDDR-05b + If this driver is compiled as a module, it will be named ums-usbat. + config USB_STORAGE_SDDR09 tristate "SanDisk SDDR-09 (and other SmartMedia, including DPCM) support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 0650f022e56..2387368cb7a 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_USBAT) += shuttle_usbat.o usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o @@ -31,8 +30,10 @@ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o +obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o ums-cypress-objs := cypress_atacb.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o +ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index ae6d64810d2..d4fe0bb327a 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -42,6 +42,7 @@ */ #include +#include #include #include @@ -52,7 +53,97 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "shuttle_usbat.h" + + +/* Supported device types */ +#define USBAT_DEV_HP8200 0x01 +#define USBAT_DEV_FLASH 0x02 + +#define USBAT_EPP_PORT 0x10 +#define USBAT_EPP_REGISTER 0x30 +#define USBAT_ATA 0x40 +#define USBAT_ISA 0x50 + +/* Commands (need to be logically OR'd with an access type */ +#define USBAT_CMD_READ_REG 0x00 +#define USBAT_CMD_WRITE_REG 0x01 +#define USBAT_CMD_READ_BLOCK 0x02 +#define USBAT_CMD_WRITE_BLOCK 0x03 +#define USBAT_CMD_COND_READ_BLOCK 0x04 +#define USBAT_CMD_COND_WRITE_BLOCK 0x05 +#define USBAT_CMD_WRITE_REGS 0x07 + +/* Commands (these don't need an access type) */ +#define USBAT_CMD_EXEC_CMD 0x80 +#define USBAT_CMD_SET_FEAT 0x81 +#define USBAT_CMD_UIO 0x82 + +/* Methods of accessing UIO register */ +#define USBAT_UIO_READ 1 +#define USBAT_UIO_WRITE 0 + +/* Qualifier bits */ +#define USBAT_QUAL_FCQ 0x20 /* full compare */ +#define USBAT_QUAL_ALQ 0x10 /* auto load subcount */ + +/* USBAT Flash Media status types */ +#define USBAT_FLASH_MEDIA_NONE 0 +#define USBAT_FLASH_MEDIA_CF 1 + +/* USBAT Flash Media change types */ +#define USBAT_FLASH_MEDIA_SAME 0 +#define USBAT_FLASH_MEDIA_CHANGED 1 + +/* USBAT ATA registers */ +#define USBAT_ATA_DATA 0x10 /* read/write data (R/W) */ +#define USBAT_ATA_FEATURES 0x11 /* set features (W) */ +#define USBAT_ATA_ERROR 0x11 /* error (R) */ +#define USBAT_ATA_SECCNT 0x12 /* sector count (R/W) */ +#define USBAT_ATA_SECNUM 0x13 /* sector number (R/W) */ +#define USBAT_ATA_LBA_ME 0x14 /* cylinder low (R/W) */ +#define USBAT_ATA_LBA_HI 0x15 /* cylinder high (R/W) */ +#define USBAT_ATA_DEVICE 0x16 /* head/device selection (R/W) */ +#define USBAT_ATA_STATUS 0x17 /* device status (R) */ +#define USBAT_ATA_CMD 0x17 /* device command (W) */ +#define USBAT_ATA_ALTSTATUS 0x0E /* status (no clear IRQ) (R) */ + +/* USBAT User I/O Data registers */ +#define USBAT_UIO_EPAD 0x80 /* Enable Peripheral Control Signals */ +#define USBAT_UIO_CDT 0x40 /* Card Detect (Read Only) */ + /* CDT = ACKD & !UI1 & !UI0 */ +#define USBAT_UIO_1 0x20 /* I/O 1 */ +#define USBAT_UIO_0 0x10 /* I/O 0 */ +#define USBAT_UIO_EPP_ATA 0x08 /* 1=EPP mode, 0=ATA mode */ +#define USBAT_UIO_UI1 0x04 /* Input 1 */ +#define USBAT_UIO_UI0 0x02 /* Input 0 */ +#define USBAT_UIO_INTR_ACK 0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */ + +/* USBAT User I/O Enable registers */ +#define USBAT_UIO_DRVRST 0x80 /* Reset Peripheral */ +#define USBAT_UIO_ACKD 0x40 /* Enable Card Detect */ +#define USBAT_UIO_OE1 0x20 /* I/O 1 set=output/clr=input */ + /* If ACKD=1, set OE1 to 1 also. */ +#define USBAT_UIO_OE0 0x10 /* I/O 0 set=output/clr=input */ +#define USBAT_UIO_ADPRST 0x01 /* Reset SCM chip */ + +/* USBAT Features */ +#define USBAT_FEAT_ETEN 0x80 /* External trigger enable */ +#define USBAT_FEAT_U1 0x08 +#define USBAT_FEAT_U0 0x04 +#define USBAT_FEAT_ET1 0x02 +#define USBAT_FEAT_ET2 0x01 + +struct usbat_info { + int devicetype; + + /* Used for Flash readers only */ + unsigned long sectors; /* total sector count */ + unsigned long ssize; /* sector size in bytes */ + + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; #define short_pack(LSB,MSB) ( ((u16)(LSB)) | ( ((u16)(MSB))<<8 ) ) #define LSB_of(s) ((s)&0xFF) @@ -63,6 +154,48 @@ static int transferred = 0; static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us); static int usbat_hp8200e_transport(struct scsi_cmnd *srb, struct us_data *us); +static int init_usbat_cd(struct us_data *us); +static int init_usbat_flash(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id usbat_usb_ids[] = { +# include "unusual_usbat.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, usbat_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev usbat_unusual_dev_list[] = { +# include "unusual_usbat.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + /* * Convenience function to produce an ATA read/write sectors command * Use cmd=0x20 for read, cmd=0x30 for write @@ -1684,37 +1817,61 @@ static int usbat_flash_transport(struct scsi_cmnd * srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; } -int init_usbat_cd(struct us_data *us) +static int init_usbat_cd(struct us_data *us) { return init_usbat(us, USBAT_DEV_HP8200); } - -int init_usbat_flash(struct us_data *us) +static int init_usbat_flash(struct us_data *us) { return init_usbat(us, USBAT_DEV_FLASH); } -int init_usbat_probe(struct us_data *us) +static int usbat_probe(struct usb_interface *intf, + const struct usb_device_id *id) { - return init_usbat(us, 0); + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - usbat_usb_ids) + usbat_unusual_dev_list); + if (result) + return result; + + /* The actual transport will be determined later by the + * initialization routine; this is just a placeholder. + */ + us->transport_name = "Shuttle USBAT"; + us->transport = usbat_flash_transport; + us->transport_reset = usb_stor_CB_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; } -/* - * Default transport function. Attempts to detect which transport function - * should be called, makes it the new default, and calls it. - * - * This function should never be called. Our usbat_init() function detects the - * device type and changes the us->transport ptr to the transport function - * relevant to the device. - * However, we'll support this impossible(?) case anyway. - */ -int usbat_transport(struct scsi_cmnd *srb, struct us_data *us) +static struct usb_driver usbat_driver = { + .name = "ums-usbat", + .probe = usbat_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = usbat_usb_ids, + .soft_unbind = 1, +}; + +static int __init usbat_init(void) { - struct usbat_info *info = (struct usbat_info*) (us->extra); - - if (usbat_set_transport(us, info, 0)) - return USB_STOR_TRANSPORT_ERROR; + return usb_register(&usbat_driver); +} - return us->transport(srb, us); +static void __exit usbat_exit(void) +{ + usb_deregister(&usbat_driver); } + +module_init(usbat_init); +module_exit(usbat_exit); diff --git a/drivers/usb/storage/shuttle_usbat.h b/drivers/usb/storage/shuttle_usbat.h deleted file mode 100644 index d8bfc43e904..00000000000 --- a/drivers/usb/storage/shuttle_usbat.h +++ /dev/null @@ -1,123 +0,0 @@ -/* Driver for SCM Microsystems USB-ATAPI cable - * Header File - * - * Current development and maintenance by: - * (c) 2000 Robert Baruch (autophile@dol.net) - * (c) 2004, 2005 Daniel Drake - * - * See shuttle_usbat.c for more explanation - * - * 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, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_SHUTTLE_USBAT_H -#define _USB_SHUTTLE_USBAT_H - -/* Supported device types */ -#define USBAT_DEV_HP8200 0x01 -#define USBAT_DEV_FLASH 0x02 - -#define USBAT_EPP_PORT 0x10 -#define USBAT_EPP_REGISTER 0x30 -#define USBAT_ATA 0x40 -#define USBAT_ISA 0x50 - -/* Commands (need to be logically OR'd with an access type */ -#define USBAT_CMD_READ_REG 0x00 -#define USBAT_CMD_WRITE_REG 0x01 -#define USBAT_CMD_READ_BLOCK 0x02 -#define USBAT_CMD_WRITE_BLOCK 0x03 -#define USBAT_CMD_COND_READ_BLOCK 0x04 -#define USBAT_CMD_COND_WRITE_BLOCK 0x05 -#define USBAT_CMD_WRITE_REGS 0x07 - -/* Commands (these don't need an access type) */ -#define USBAT_CMD_EXEC_CMD 0x80 -#define USBAT_CMD_SET_FEAT 0x81 -#define USBAT_CMD_UIO 0x82 - -/* Methods of accessing UIO register */ -#define USBAT_UIO_READ 1 -#define USBAT_UIO_WRITE 0 - -/* Qualifier bits */ -#define USBAT_QUAL_FCQ 0x20 /* full compare */ -#define USBAT_QUAL_ALQ 0x10 /* auto load subcount */ - -/* USBAT Flash Media status types */ -#define USBAT_FLASH_MEDIA_NONE 0 -#define USBAT_FLASH_MEDIA_CF 1 - -/* USBAT Flash Media change types */ -#define USBAT_FLASH_MEDIA_SAME 0 -#define USBAT_FLASH_MEDIA_CHANGED 1 - -/* USBAT ATA registers */ -#define USBAT_ATA_DATA 0x10 /* read/write data (R/W) */ -#define USBAT_ATA_FEATURES 0x11 /* set features (W) */ -#define USBAT_ATA_ERROR 0x11 /* error (R) */ -#define USBAT_ATA_SECCNT 0x12 /* sector count (R/W) */ -#define USBAT_ATA_SECNUM 0x13 /* sector number (R/W) */ -#define USBAT_ATA_LBA_ME 0x14 /* cylinder low (R/W) */ -#define USBAT_ATA_LBA_HI 0x15 /* cylinder high (R/W) */ -#define USBAT_ATA_DEVICE 0x16 /* head/device selection (R/W) */ -#define USBAT_ATA_STATUS 0x17 /* device status (R) */ -#define USBAT_ATA_CMD 0x17 /* device command (W) */ -#define USBAT_ATA_ALTSTATUS 0x0E /* status (no clear IRQ) (R) */ - -/* USBAT User I/O Data registers */ -#define USBAT_UIO_EPAD 0x80 /* Enable Peripheral Control Signals */ -#define USBAT_UIO_CDT 0x40 /* Card Detect (Read Only) */ - /* CDT = ACKD & !UI1 & !UI0 */ -#define USBAT_UIO_1 0x20 /* I/O 1 */ -#define USBAT_UIO_0 0x10 /* I/O 0 */ -#define USBAT_UIO_EPP_ATA 0x08 /* 1=EPP mode, 0=ATA mode */ -#define USBAT_UIO_UI1 0x04 /* Input 1 */ -#define USBAT_UIO_UI0 0x02 /* Input 0 */ -#define USBAT_UIO_INTR_ACK 0x01 /* Interrupt (ATA/ISA)/Acknowledge (EPP) */ - -/* USBAT User I/O Enable registers */ -#define USBAT_UIO_DRVRST 0x80 /* Reset Peripheral */ -#define USBAT_UIO_ACKD 0x40 /* Enable Card Detect */ -#define USBAT_UIO_OE1 0x20 /* I/O 1 set=output/clr=input */ - /* If ACKD=1, set OE1 to 1 also. */ -#define USBAT_UIO_OE0 0x10 /* I/O 0 set=output/clr=input */ -#define USBAT_UIO_ADPRST 0x01 /* Reset SCM chip */ - -/* USBAT Features */ -#define USBAT_FEAT_ETEN 0x80 /* External trigger enable */ -#define USBAT_FEAT_U1 0x08 -#define USBAT_FEAT_U0 0x04 -#define USBAT_FEAT_ET1 0x02 -#define USBAT_FEAT_ET2 0x01 - -extern int usbat_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int init_usbat_cd(struct us_data *us); -extern int init_usbat_flash(struct us_data *us); -extern int init_usbat_probe(struct us_data *us); - -struct usbat_info { - int devicetype; - - /* Used for Flash readers only */ - unsigned long sectors; /* total sector count */ - unsigned long ssize; /* sector size in bytes */ - - unsigned char sense_key; - unsigned long sense_asc; /* additional sense code */ - unsigned long sense_ascq; /* additional sense code qualifier */ -}; - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index eff97aed7bf..6462c4c54dc 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -85,18 +85,6 @@ UNUSUAL_DEV( 0x03f0, 0x0107, 0x0200, 0x0200, "CD-Writer+", US_SC_8070, US_PR_CB, NULL, 0), -#ifdef CONFIG_USB_STORAGE_USBAT -UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, - "HP", - "CD-Writer+ 8200e", - US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), - -UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, - "HP", - "CD-Writer+ CD-4e", - US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), -#endif - /* Reported by Ben Efros */ UNUSUAL_DEV( 0x03f0, 0x070c, 0x0000, 0x0000, "HP", @@ -506,14 +494,6 @@ UNUSUAL_DEV( 0x04e6, 0x0101, 0x0200, 0x0200, "CD-RW Device", US_SC_8020, US_PR_CB, NULL, 0), -#ifdef CONFIG_USB_STORAGE_USBAT -UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, - "Shuttle/SCM", - "USBAT-02", - US_SC_SCSI, US_PR_USBAT, init_usbat_flash, - US_FL_SINGLE_LUN), -#endif - /* Reported by Dmitry Khlystov */ UNUSUAL_DEV( 0x04e8, 0x507c, 0x0220, 0x0220, "Samsung", @@ -972,14 +952,6 @@ UNUSUAL_DEV( 0x0781, 0x0002, 0x0009, 0x0009, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_CAPACITY ), -#ifdef CONFIG_USB_STORAGE_USBAT -UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, - "Sandisk", - "ImageMate SDDR-05b", - US_SC_SCSI, US_PR_USBAT, init_usbat_flash, - US_FL_SINGLE_LUN ), -#endif - UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, "Sandisk", "ImageMate SDDR-12", diff --git a/drivers/usb/storage/unusual_usbat.h b/drivers/usb/storage/unusual_usbat.h new file mode 100644 index 00000000000..80e869f1018 --- /dev/null +++ b/drivers/usb/storage/unusual_usbat.h @@ -0,0 +1,43 @@ +/* Unusual Devices File for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_USBAT) || \ + defined(CONFIG_USB_STORAGE_USBAT_MODULE) + +UNUSUAL_DEV( 0x03f0, 0x0207, 0x0001, 0x0001, + "HP", + "CD-Writer+ 8200e", + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), + +UNUSUAL_DEV( 0x03f0, 0x0307, 0x0001, 0x0001, + "HP", + "CD-Writer+ CD-4e", + US_SC_8070, US_PR_USBAT, init_usbat_cd, 0), + +UNUSUAL_DEV( 0x04e6, 0x1010, 0x0000, 0x9999, + "Shuttle/SCM", + "USBAT-02", + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, + US_FL_SINGLE_LUN), + +UNUSUAL_DEV( 0x0781, 0x0005, 0x0005, 0x0005, + "Sandisk", + "ImageMate SDDR-05b", + US_SC_SCSI, US_PR_USBAT, init_usbat_flash, + US_FL_SINGLE_LUN), + +#endif /* defined(CONFIG_USB_STORAGE_USBAT) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 241e1944cf1..3ad22a8142c 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_USBAT -#include "shuttle_usbat.h" -#endif #ifdef CONFIG_USB_STORAGE_FREECOM #include "freecom.h" #endif @@ -610,15 +607,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_USBAT - case US_PR_USBAT: - us->transport_name = "Shuttle USBAT"; - us->transport = usbat_transport; - us->transport_reset = usb_stor_CB_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_FREECOM case US_PR_FREECOM: us->transport_name = "Freecom"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index be461ee9f00..899a8c8da71 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -81,6 +81,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_isd200.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" +# include "unusual_usbat.h" { } /* Terminating entry */ }; -- cgit v1.2.3 From 0d62939fab3cf28a23ac6934cec599793d3a1d9d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:11 -0500 Subject: usb-storage: make freecom a separate module This patch (as1212) converts usb-storage's freecom subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/freecom.c | 95 +++++++++++++++++++++++++++++++++-- drivers/usb/storage/freecom.h | 34 ------------- drivers/usb/storage/unusual_devs.h | 7 --- drivers/usb/storage/unusual_freecom.h | 26 ++++++++++ drivers/usb/storage/usb.c | 12 ----- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 122 insertions(+), 60 deletions(-) delete mode 100644 drivers/usb/storage/freecom.h create mode 100644 drivers/usb/storage/unusual_freecom.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 44c6b1940f7..14508b8a55f 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -39,12 +39,14 @@ config USB_STORAGE_DATAFAB Datafab has a web page at . config USB_STORAGE_FREECOM - bool "Freecom USB/ATAPI Bridge support" + tristate "Freecom USB/ATAPI Bridge support" depends on USB_STORAGE help Support for the Freecom USB to IDE/ATAPI adaptor. Freecom has a web page at . + If this driver is compiled as a module, it will be named ums-freecom. + config USB_STORAGE_ISD200 tristate "ISD-200 USB/ATA Bridge support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 2387368cb7a..93e91ec3a2d 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_FREECOM) += freecom.o usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o @@ -27,12 +26,14 @@ else endif obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o +obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o ums-cypress-objs := cypress_atacb.o +ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 73ac7262239..393047b3890 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -26,6 +26,7 @@ * (http://www.freecom.de/) */ +#include #include #include @@ -33,7 +34,6 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "freecom.h" #ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (void *, int); @@ -103,6 +103,47 @@ struct freecom_status { #define FCM_PACKET_LENGTH 64 #define FCM_STATUS_PACKET_LENGTH 4 +static int init_freecom(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id freecom_usb_ids[] = { +# include "unusual_freecom.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, freecom_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev freecom_unusual_dev_list[] = { +# include "unusual_freecom.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + static int freecom_readdata (struct scsi_cmnd *srb, struct us_data *us, unsigned int ipipe, unsigned int opipe, int count) @@ -173,7 +214,7 @@ freecom_writedata (struct scsi_cmnd *srb, struct us_data *us, * Transport for the Freecom USB/IDE adaptor. * */ -int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) +static int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) { struct freecom_cb_wrap *fcb; struct freecom_status *fst; @@ -377,8 +418,7 @@ int freecom_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -int -freecom_init (struct us_data *us) +static int init_freecom(struct us_data *us) { int result; char *buffer = us->iobuf; @@ -417,7 +457,7 @@ freecom_init (struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -int usb_stor_freecom_reset(struct us_data *us) +static int usb_stor_freecom_reset(struct us_data *us) { printk (KERN_CRIT "freecom reset called\n"); @@ -479,3 +519,48 @@ static void pdump (void *ibuffer, int length) } #endif +static int freecom_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - freecom_usb_ids) + freecom_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Freecom"; + us->transport = freecom_transport; + us->transport_reset = usb_stor_freecom_reset; + us->max_lun = 0; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver freecom_driver = { + .name = "ums-freecom", + .probe = freecom_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = freecom_usb_ids, + .soft_unbind = 1, +}; + +static int __init freecom_init(void) +{ + return usb_register(&freecom_driver); +} + +static void __exit freecom_exit(void) +{ + usb_deregister(&freecom_driver); +} + +module_init(freecom_init); +module_exit(freecom_exit); diff --git a/drivers/usb/storage/freecom.h b/drivers/usb/storage/freecom.h deleted file mode 100644 index 20d0fe6ba0c..00000000000 --- a/drivers/usb/storage/freecom.h +++ /dev/null @@ -1,34 +0,0 @@ -/* Driver for Freecom USB/IDE adaptor - * - * Freecom v0.1: - * - * First release - * - * Current development and maintenance by: - * (c) 2000 David Brown - * - * See freecom.c for more explanation - * - * 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, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _FREECOM_USB_H -#define _FREECOM_USB_H - -extern int freecom_transport(struct scsi_cmnd *srb, struct us_data *us); -extern int usb_stor_freecom_reset(struct us_data *us); -extern int freecom_init (struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 6462c4c54dc..eef2075cf2e 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -958,13 +958,6 @@ UNUSUAL_DEV( 0x0781, 0x0100, 0x0100, 0x0100, US_SC_SCSI, US_PR_CB, NULL, US_FL_SINGLE_LUN ), -#ifdef CONFIG_USB_STORAGE_FREECOM -UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, - "Freecom", - "USB-IDE", - US_SC_QIC, US_PR_FREECOM, freecom_init, 0), -#endif - /* Reported by Eero Volotinen */ UNUSUAL_DEV( 0x07ab, 0xfccd, 0x0000, 0x9999, "Freecom Technologies", diff --git a/drivers/usb/storage/unusual_freecom.h b/drivers/usb/storage/unusual_freecom.h new file mode 100644 index 00000000000..37586794239 --- /dev/null +++ b/drivers/usb/storage/unusual_freecom.h @@ -0,0 +1,26 @@ +/* Unusual Devices File for the Freecom USB/IDE adaptor + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_FREECOM) || \ + defined(CONFIG_USB_STORAGE_FREECOM_MODULE) + +UNUSUAL_DEV( 0x07ab, 0xfc01, 0x0000, 0x9999, + "Freecom", + "USB-IDE", + US_SC_QIC, US_PR_FREECOM, init_freecom, 0), + +#endif /* defined(CONFIG_USB_STORAGE_FREECOM) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 3ad22a8142c..985275d5d4c 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_FREECOM -#include "freecom.h" -#endif #ifdef CONFIG_USB_STORAGE_DATAFAB #include "datafab.h" #endif @@ -607,15 +604,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_FREECOM - case US_PR_FREECOM: - us->transport_name = "Freecom"; - us->transport = freecom_transport; - us->transport_reset = usb_stor_freecom_reset; - us->max_lun = 0; - break; -#endif - #ifdef CONFIG_USB_STORAGE_DATAFAB case US_PR_DATAFAB: us->transport_name = "Datafab Bulk-Only"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 899a8c8da71..a50f0eefb73 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -78,6 +78,7 @@ struct ignore_entry { static struct ignore_entry ignore_ids[] = { # include "unusual_cypress.h" +# include "unusual_freecom.h" # include "unusual_isd200.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" -- cgit v1.2.3 From 2cbbf3576aa9eae9a92f2669f38a453b6cb8e956 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:15 -0500 Subject: usb-storage: make datafab a separate module This patch (as1213) converts usb-storage's datafab subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/datafab.c | 100 +++++++++++++++++++++++++++++++++- drivers/usb/storage/datafab.h | 40 -------------- drivers/usb/storage/unusual_datafab.h | 98 +++++++++++++++++++++++++++++++++ drivers/usb/storage/unusual_devs.h | 86 ----------------------------- drivers/usb/storage/usb.c | 12 ---- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 202 insertions(+), 142 deletions(-) delete mode 100644 drivers/usb/storage/datafab.h create mode 100644 drivers/usb/storage/unusual_datafab.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 14508b8a55f..7dac413e0f2 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -32,12 +32,14 @@ config USB_STORAGE_DEBUG verbose debugging messages. config USB_STORAGE_DATAFAB - bool "Datafab Compact Flash Reader support" + tristate "Datafab Compact Flash Reader support" depends on USB_STORAGE help Support for certain Datafab CompactFlash readers. Datafab has a web page at . + If this driver is compiled as a module, it will be named ums-datafab. + config USB_STORAGE_FREECOM tristate "Freecom USB/ATAPI Bridge support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 93e91ec3a2d..0f78bd680f0 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_DATAFAB) += datafab.o usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o @@ -26,6 +25,7 @@ else endif obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o +obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o @@ -33,6 +33,7 @@ obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o ums-cypress-objs := cypress_atacb.o +ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-sddr09-objs := sddr09.o diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 17f1ae23291..2d8d8351909 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -49,6 +49,7 @@ */ #include +#include #include #include @@ -58,12 +59,61 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "datafab.h" + +struct datafab_info { + unsigned long sectors; /* total sector count */ + unsigned long ssize; /* sector size in bytes */ + signed char lun; /* used for dual-slot readers */ + + /* the following aren't used yet */ + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; static int datafab_determine_lun(struct us_data *us, struct datafab_info *info); +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id datafab_usb_ids[] = { +# include "unusual_datafab.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, datafab_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev datafab_unusual_dev_list[] = { +# include "unusual_datafab.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + static inline int datafab_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) { if (len == 0) @@ -500,7 +550,7 @@ static void datafab_info_destructor(void *extra) // Transport for the Datafab MDCFE-B // -int datafab_transport(struct scsi_cmnd * srb, struct us_data *us) +static int datafab_transport(struct scsi_cmnd *srb, struct us_data *us) { struct datafab_info *info; int rc; @@ -665,3 +715,49 @@ int datafab_transport(struct scsi_cmnd * srb, struct us_data *us) info->sense_ascq = 0x00; return USB_STOR_TRANSPORT_FAILED; } + +static int datafab_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - datafab_usb_ids) + datafab_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Datafab Bulk-Only"; + us->transport = datafab_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver datafab_driver = { + .name = "ums-datafab", + .probe = datafab_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = datafab_usb_ids, + .soft_unbind = 1, +}; + +static int __init datafab_init(void) +{ + return usb_register(&datafab_driver); +} + +static void __exit datafab_exit(void) +{ + usb_deregister(&datafab_driver); +} + +module_init(datafab_init); +module_exit(datafab_exit); diff --git a/drivers/usb/storage/datafab.h b/drivers/usb/storage/datafab.h deleted file mode 100644 index 32e3f271e58..00000000000 --- a/drivers/usb/storage/datafab.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Driver for Datafab MDCFE-B USB Compact Flash reader - * Header File - * - * Current development and maintenance by: - * (c) 2000 Jimmie Mayfield (mayfield+datafab@sackheads.org) - * - * See datafab.c for more explanation - * - * 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, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_DATAFAB_MDCFE_B_H -#define _USB_DATAFAB_MDCFE_B_H - -extern int datafab_transport(struct scsi_cmnd *srb, struct us_data *us); - -struct datafab_info { - unsigned long sectors; // total sector count - unsigned long ssize; // sector size in bytes - signed char lun; // used for dual-slot readers - - // the following aren't used yet - unsigned char sense_key; - unsigned long sense_asc; // additional sense code - unsigned long sense_ascq; // additional sense code qualifier -}; - -#endif diff --git a/drivers/usb/storage/unusual_datafab.h b/drivers/usb/storage/unusual_datafab.h new file mode 100644 index 00000000000..c9298ce9f22 --- /dev/null +++ b/drivers/usb/storage/unusual_datafab.h @@ -0,0 +1,98 @@ +/* Unusual Devices File for the Datafab USB Compact Flash reader + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_DATAFAB) || \ + defined(CONFIG_USB_STORAGE_DATAFAB_MODULE) + +UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, + "Datafab", + "MDCFE-B USB CF Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* + * The following Datafab-based devices may or may not work + * using the current driver...the 0xffff is arbitrary since I + * don't know what device versions exist for these guys. + * + * The 0xa003 and 0xa004 devices in particular I'm curious about. + * I'm told they exist but so far nobody has come forward to say that + * they work with this driver. Given the success we've had getting + * other Datafab-based cards operational with this driver, I've decided + * to leave these two devices in the list. + */ +UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff, + "SIIG/Datafab", + "SIIG/Datafab Memory Stick+CF Reader/Writer", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* Reported by Josef Reisinger */ +UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff, + "Datafab/Unknown", + "MD2/MD3 Disk enclosure", + US_SC_SCSI, US_PR_DATAFAB, NULL, + US_FL_SINGLE_LUN), + +UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff, + "Datafab/Unknown", + "Datafab-based Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff, + "Datafab/Unknown", + "Datafab-based Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff, + "PNY/Datafab", + "PNY/Datafab CF+SM Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, + "Simple Tech/Datafab", + "Simple Tech/Datafab CF+SM Reader", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* Submitted by Olaf Hering */ +UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, + "Datafab Systems, Inc.", + "USB to CF + SM Combo (LC1)", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +/* Reported by Felix Moeller + * in Germany this is sold by Hama with the productnumber 46952 + * as "DualSlot CompactFlash(TM) & MStick Drive USB" + */ +UNUSUAL_DEV( 0x07c4, 0xa10b, 0x0000, 0xffff, + "DataFab Systems Inc.", + "USB CF+MS", + US_SC_SCSI, US_PR_DATAFAB, NULL, + 0), + +UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, + "Acomdata", + "CF", + US_SC_SCSI, US_PR_DATAFAB, NULL, + US_FL_SINGLE_LUN), + +#endif /* defined(CONFIG_USB_STORAGE_DATAFAB) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index eef2075cf2e..a5867c6d761 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -992,84 +992,6 @@ UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), #endif -#ifdef CONFIG_USB_STORAGE_DATAFAB -UNUSUAL_DEV( 0x07c4, 0xa000, 0x0000, 0x0015, - "Datafab", - "MDCFE-B USB CF Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -/* - * The following Datafab-based devices may or may not work - * using the current driver...the 0xffff is arbitrary since I - * don't know what device versions exist for these guys. - * - * The 0xa003 and 0xa004 devices in particular I'm curious about. - * I'm told they exist but so far nobody has come forward to say that - * they work with this driver. Given the success we've had getting - * other Datafab-based cards operational with this driver, I've decided - * to leave these two devices in the list. - */ -UNUSUAL_DEV( 0x07c4, 0xa001, 0x0000, 0xffff, - "SIIG/Datafab", - "SIIG/Datafab Memory Stick+CF Reader/Writer", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -/* Reported by Josef Reisinger */ -UNUSUAL_DEV( 0x07c4, 0xa002, 0x0000, 0xffff, - "Datafab/Unknown", - "MD2/MD3 Disk enclosure", - US_SC_SCSI, US_PR_DATAFAB, NULL, - US_FL_SINGLE_LUN ), - -UNUSUAL_DEV( 0x07c4, 0xa003, 0x0000, 0xffff, - "Datafab/Unknown", - "Datafab-based Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -UNUSUAL_DEV( 0x07c4, 0xa004, 0x0000, 0xffff, - "Datafab/Unknown", - "Datafab-based Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -UNUSUAL_DEV( 0x07c4, 0xa005, 0x0000, 0xffff, - "PNY/Datafab", - "PNY/Datafab CF+SM Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -UNUSUAL_DEV( 0x07c4, 0xa006, 0x0000, 0xffff, - "Simple Tech/Datafab", - "Simple Tech/Datafab CF+SM Reader", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), -#endif - -#ifdef CONFIG_USB_STORAGE_DATAFAB -/* Submitted by Olaf Hering */ -UNUSUAL_DEV( 0x07c4, 0xa109, 0x0000, 0xffff, - "Datafab Systems, Inc.", - "USB to CF + SM Combo (LC1)", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), -#endif - -#ifdef CONFIG_USB_STORAGE_DATAFAB -/* Reported by Felix Moeller - * in Germany this is sold by Hama with the productnumber 46952 - * as "DualSlot CompactFlash(TM) & MStick Drive USB" - */ -UNUSUAL_DEV( 0x07c4, 0xa10b, 0x0000, 0xffff, - "DataFab Systems Inc.", - "USB CF+MS", - US_SC_SCSI, US_PR_DATAFAB, NULL, - 0 ), - -#endif - /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100 * Only revision 1.13 tested (same for all of the above devices, * based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY. @@ -1273,14 +1195,6 @@ UNUSUAL_DEV( 0x0bc2, 0x3010, 0x0000, 0x0000, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SANE_SENSE ), -#ifdef CONFIG_USB_STORAGE_DATAFAB -UNUSUAL_DEV( 0x0c0b, 0xa109, 0x0000, 0xffff, - "Acomdata", - "CF", - US_SC_SCSI, US_PR_DATAFAB, NULL, - US_FL_SINGLE_LUN ), -#endif - UNUSUAL_DEV( 0x0d49, 0x7310, 0x0000, 0x9999, "Maxtor", "USB to SATA", diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 985275d5d4c..a537b3513b9 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_DATAFAB -#include "datafab.h" -#endif #ifdef CONFIG_USB_STORAGE_JUMPSHOT #include "jumpshot.h" #endif @@ -604,15 +601,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_DATAFAB - case US_PR_DATAFAB: - us->transport_name = "Datafab Bulk-Only"; - us->transport = datafab_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_JUMPSHOT case US_PR_JUMPSHOT: us->transport_name = "Lexar Jumpshot Control/Bulk"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index a50f0eefb73..c6ceac62cf6 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -78,6 +78,7 @@ struct ignore_entry { static struct ignore_entry ignore_ids[] = { # include "unusual_cypress.h" +# include "unusual_datafab.h" # include "unusual_freecom.h" # include "unusual_isd200.h" # include "unusual_sddr09.h" -- cgit v1.2.3 From a9fb6d05d59c9e118ad8c355adfdf88c970c61bc Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:19 -0500 Subject: usb-storage: make jumpshot a separate module This patch (as1214) converts usb-storage's jumpshot subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/jumpshot.c | 99 +++++++++++++++++++++++++++++++++- drivers/usb/storage/jumpshot.h | 39 -------------- drivers/usb/storage/unusual_devs.h | 8 --- drivers/usb/storage/unusual_jumpshot.h | 27 ++++++++++ drivers/usb/storage/usb.c | 12 ----- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 130 insertions(+), 63 deletions(-) delete mode 100644 drivers/usb/storage/jumpshot.h create mode 100644 drivers/usb/storage/unusual_jumpshot.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 7dac413e0f2..43e1afeb7f8 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -110,12 +110,14 @@ config USB_STORAGE_SDDR55 If this driver is compiled as a module, it will be named ums-sddr55. config USB_STORAGE_JUMPSHOT - bool "Lexar Jumpshot Compact Flash Reader" + tristate "Lexar Jumpshot Compact Flash Reader" depends on USB_STORAGE help Say Y here to include additional code to support the Lexar Jumpshot USB CompactFlash reader. + If this driver is compiled as a module, it will be named ums-jumpshot. + config USB_STORAGE_ALAUDA bool "Olympus MAUSB-10/Fuji DPC-R1 support" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 0f78bd680f0..7b9d53563d3 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += jumpshot.o usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o @@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o +obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o @@ -36,6 +36,7 @@ ums-cypress-objs := cypress_atacb.o ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o +ums-jumpshot-objs := jumpshot.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index df67f13c9e7..a50d6dc1fe6 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -46,6 +46,7 @@ */ #include +#include #include #include @@ -55,9 +56,57 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "jumpshot.h" +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id jumpshot_usb_ids[] = { +# include "unusual_jumpshot.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, jumpshot_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev jumpshot_unusual_dev_list[] = { +# include "unusual_jumpshot.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + +struct jumpshot_info { + unsigned long sectors; /* total sector count */ + unsigned long ssize; /* sector size in bytes */ + + /* the following aren't used yet */ + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; + static inline int jumpshot_bulk_read(struct us_data *us, unsigned char *data, unsigned int len) @@ -429,7 +478,7 @@ static void jumpshot_info_destructor(void *extra) // Transport for the Lexar 'Jumpshot' // -int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us) +static int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us) { struct jumpshot_info *info; int rc; @@ -592,3 +641,49 @@ int jumpshot_transport(struct scsi_cmnd * srb, struct us_data *us) info->sense_ascq = 0x00; return USB_STOR_TRANSPORT_FAILED; } + +static int jumpshot_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - jumpshot_usb_ids) + jumpshot_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Lexar Jumpshot Control/Bulk"; + us->transport = jumpshot_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver jumpshot_driver = { + .name = "ums-jumpshot", + .probe = jumpshot_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = jumpshot_usb_ids, + .soft_unbind = 1, +}; + +static int __init jumpshot_init(void) +{ + return usb_register(&jumpshot_driver); +} + +static void __exit jumpshot_exit(void) +{ + usb_deregister(&jumpshot_driver); +} + +module_init(jumpshot_init); +module_exit(jumpshot_exit); diff --git a/drivers/usb/storage/jumpshot.h b/drivers/usb/storage/jumpshot.h deleted file mode 100644 index 19bac9d1558..00000000000 --- a/drivers/usb/storage/jumpshot.h +++ /dev/null @@ -1,39 +0,0 @@ -/* Driver for Lexar "Jumpshot" USB Compact Flash reader - * Header File - * - * Current development and maintenance by: - * (c) 2000 Jimmie Mayfield (mayfield+usb@sackheads.org) - * - * See jumpshot.c for more explanation - * - * 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, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_JUMPSHOT_H -#define _USB_JUMPSHOT_H - -extern int jumpshot_transport(struct scsi_cmnd *srb, struct us_data *us); - -struct jumpshot_info { - unsigned long sectors; // total sector count - unsigned long ssize; // sector size in bytes - - // the following aren't used yet - unsigned char sense_key; - unsigned long sense_asc; // additional sense code - unsigned long sense_ascq; // additional sense code qualifier -}; - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index a5867c6d761..24e23c29d29 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -794,14 +794,6 @@ UNUSUAL_DEV( 0x05c6, 0x1000, 0x0000, 0x9999, US_SC_DEVICE, US_PR_DEVICE, option_ms_init, 0), -#ifdef CONFIG_USB_STORAGE_JUMPSHOT -UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, - "Lexar", - "Jumpshot USB CF Reader", - US_SC_SCSI, US_PR_JUMPSHOT, NULL, - US_FL_NEED_OVERRIDE ), -#endif - /* Reported by Blake Matheny */ UNUSUAL_DEV( 0x05dc, 0xb002, 0x0000, 0x0113, "Lexar", diff --git a/drivers/usb/storage/unusual_jumpshot.h b/drivers/usb/storage/unusual_jumpshot.h new file mode 100644 index 00000000000..2e549b1c2c6 --- /dev/null +++ b/drivers/usb/storage/unusual_jumpshot.h @@ -0,0 +1,27 @@ +/* Unusual Devices File for the Lexar "Jumpshot" Compact Flash reader + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_JUMPSHOT) || \ + defined(CONFIG_USB_STORAGE_JUMPSHOT_MODULE) + +UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, + "Lexar", + "Jumpshot USB CF Reader", + US_SC_SCSI, US_PR_JUMPSHOT, NULL, + US_FL_NEED_OVERRIDE), + +#endif /* defined(CONFIG_USB_STORAGE_JUMPSHOT) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index a537b3513b9..2ea57691a7b 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_JUMPSHOT -#include "jumpshot.h" -#endif #ifdef CONFIG_USB_STORAGE_ONETOUCH #include "onetouch.h" #endif @@ -601,15 +598,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_JUMPSHOT - case US_PR_JUMPSHOT: - us->transport_name = "Lexar Jumpshot Control/Bulk"; - us->transport = jumpshot_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_ALAUDA case US_PR_ALAUDA: us->transport_name = "Alauda Control/Bulk"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index c6ceac62cf6..182a097e076 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -81,6 +81,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_datafab.h" # include "unusual_freecom.h" # include "unusual_isd200.h" +# include "unusual_jumpshot.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" # include "unusual_usbat.h" -- cgit v1.2.3 From a74bba3bf92cb6425789ae5050bdcca1283bc6f4 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:22 -0500 Subject: usb-storage: make alauda a separate module This patch (as1215) converts usb-storage's alauda subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/alauda.c | 163 ++++++++++++++++++++++++++++++++++- drivers/usb/storage/alauda.h | 100 --------------------- drivers/usb/storage/unusual_alauda.h | 31 +++++++ drivers/usb/storage/unusual_devs.h | 14 --- drivers/usb/storage/usb.c | 12 --- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 197 insertions(+), 131 deletions(-) delete mode 100644 drivers/usb/storage/alauda.h create mode 100644 drivers/usb/storage/unusual_alauda.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 43e1afeb7f8..c56c2c6d37b 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -119,7 +119,7 @@ config USB_STORAGE_JUMPSHOT If this driver is compiled as a module, it will be named ums-jumpshot. config USB_STORAGE_ALAUDA - bool "Olympus MAUSB-10/Fuji DPC-R1 support" + tristate "Olympus MAUSB-10/Fuji DPC-R1 support" depends on USB_STORAGE help Say Y here to include additional code to support the Olympus MAUSB-10 @@ -128,6 +128,8 @@ config USB_STORAGE_ALAUDA These devices are based on the Alauda chip and support both XD and SmartMedia cards. + If this driver is compiled as a module, it will be named ums-alauda. + config USB_STORAGE_ONETOUCH bool "Support OneTouch Button on Maxtor Hard Drives" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 7b9d53563d3..fea05c0b676 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_ALAUDA) += alauda.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o @@ -23,6 +22,7 @@ else obj-$(CONFIG_USB) += libusual.o usual-tables.o endif +obj-$(CONFIG_USB_STORAGE_ALAUDA) += ums-alauda.o obj-$(CONFIG_USB_STORAGE_CYPRESS_ATACB) += ums-cypress.o obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o @@ -32,6 +32,7 @@ obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o +ums-alauda-objs := alauda.o ums-cypress-objs := cypress_atacb.o ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index 5407411e30e..d3a88ebe690 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -31,6 +31,8 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #include #include #include @@ -39,7 +41,75 @@ #include "transport.h" #include "protocol.h" #include "debug.h" -#include "alauda.h" + +/* + * Status bytes + */ +#define ALAUDA_STATUS_ERROR 0x01 +#define ALAUDA_STATUS_READY 0x40 + +/* + * Control opcodes (for request field) + */ +#define ALAUDA_GET_XD_MEDIA_STATUS 0x08 +#define ALAUDA_GET_SM_MEDIA_STATUS 0x98 +#define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a +#define ALAUDA_ACK_SM_MEDIA_CHANGE 0x9a +#define ALAUDA_GET_XD_MEDIA_SIG 0x86 +#define ALAUDA_GET_SM_MEDIA_SIG 0x96 + +/* + * Bulk command identity (byte 0) + */ +#define ALAUDA_BULK_CMD 0x40 + +/* + * Bulk opcodes (byte 1) + */ +#define ALAUDA_BULK_GET_REDU_DATA 0x85 +#define ALAUDA_BULK_READ_BLOCK 0x94 +#define ALAUDA_BULK_ERASE_BLOCK 0xa3 +#define ALAUDA_BULK_WRITE_BLOCK 0xb4 +#define ALAUDA_BULK_GET_STATUS2 0xb7 +#define ALAUDA_BULK_RESET_MEDIA 0xe0 + +/* + * Port to operate on (byte 8) + */ +#define ALAUDA_PORT_XD 0x00 +#define ALAUDA_PORT_SM 0x01 + +/* + * LBA and PBA are unsigned ints. Special values. + */ +#define UNDEF 0xffff +#define SPARE 0xfffe +#define UNUSABLE 0xfffd + +struct alauda_media_info { + unsigned long capacity; /* total media size in bytes */ + unsigned int pagesize; /* page size in bytes */ + unsigned int blocksize; /* number of pages per block */ + unsigned int uzonesize; /* number of usable blocks per zone */ + unsigned int zonesize; /* number of blocks per zone */ + unsigned int blockmask; /* mask to get page from address */ + + unsigned char pageshift; + unsigned char blockshift; + unsigned char zoneshift; + + u16 **lba_to_pba; /* logical to physical block map */ + u16 **pba_to_lba; /* physical to logical block map */ +}; + +struct alauda_info { + struct alauda_media_info port[2]; + int wr_ep; /* endpoint to write data out of */ + + unsigned char sense_key; + unsigned long sense_asc; /* additional sense code */ + unsigned long sense_ascq; /* additional sense code qualifier */ +}; #define short_pack(lsb,msb) ( ((u16)(lsb)) | ( ((u16)(msb))<<8 ) ) #define LSB_of(s) ((s)&0xFF) @@ -52,6 +122,48 @@ #define PBA_HI(pba) (pba >> 3) #define PBA_ZONE(pba) (pba >> 11) +static int init_alauda(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id alauda_usb_ids[] = { +# include "unusual_alauda.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, alauda_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev alauda_unusual_dev_list[] = { +# include "unusual_alauda.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + /* * Media handling */ @@ -998,7 +1110,7 @@ static void alauda_info_destructor(void *extra) /* * Initialize alauda_info struct and find the data-write endpoint */ -int init_alauda(struct us_data *us) +static int init_alauda(struct us_data *us) { struct alauda_info *info; struct usb_host_interface *altsetting = us->pusb_intf->cur_altsetting; @@ -1020,7 +1132,7 @@ int init_alauda(struct us_data *us) return USB_STOR_TRANSPORT_GOOD; } -int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) +static int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) { int rc; struct alauda_info *info = (struct alauda_info *) us->extra; @@ -1128,3 +1240,48 @@ int alauda_transport(struct scsi_cmnd *srb, struct us_data *us) return USB_STOR_TRANSPORT_FAILED; } +static int alauda_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - alauda_usb_ids) + alauda_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Alauda Control/Bulk"; + us->transport = alauda_transport; + us->transport_reset = usb_stor_Bulk_reset; + us->max_lun = 1; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver alauda_driver = { + .name = "ums-alauda", + .probe = alauda_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = alauda_usb_ids, + .soft_unbind = 1, +}; + +static int __init alauda_init(void) +{ + return usb_register(&alauda_driver); +} + +static void __exit alauda_exit(void) +{ + usb_deregister(&alauda_driver); +} + +module_init(alauda_init); +module_exit(alauda_exit); diff --git a/drivers/usb/storage/alauda.h b/drivers/usb/storage/alauda.h deleted file mode 100644 index a700f87d080..00000000000 --- a/drivers/usb/storage/alauda.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Driver for Alauda-based card readers - * - * Current development and maintenance by: - * (c) 2005 Daniel Drake - * - * See alauda.c for more explanation. - * - * 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, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef _USB_ALAUDA_H -#define _USB_ALAUDA_H - -/* - * Status bytes - */ -#define ALAUDA_STATUS_ERROR 0x01 -#define ALAUDA_STATUS_READY 0x40 - -/* - * Control opcodes (for request field) - */ -#define ALAUDA_GET_XD_MEDIA_STATUS 0x08 -#define ALAUDA_GET_SM_MEDIA_STATUS 0x98 -#define ALAUDA_ACK_XD_MEDIA_CHANGE 0x0a -#define ALAUDA_ACK_SM_MEDIA_CHANGE 0x9a -#define ALAUDA_GET_XD_MEDIA_SIG 0x86 -#define ALAUDA_GET_SM_MEDIA_SIG 0x96 - -/* - * Bulk command identity (byte 0) - */ -#define ALAUDA_BULK_CMD 0x40 - -/* - * Bulk opcodes (byte 1) - */ -#define ALAUDA_BULK_GET_REDU_DATA 0x85 -#define ALAUDA_BULK_READ_BLOCK 0x94 -#define ALAUDA_BULK_ERASE_BLOCK 0xa3 -#define ALAUDA_BULK_WRITE_BLOCK 0xb4 -#define ALAUDA_BULK_GET_STATUS2 0xb7 -#define ALAUDA_BULK_RESET_MEDIA 0xe0 - -/* - * Port to operate on (byte 8) - */ -#define ALAUDA_PORT_XD 0x00 -#define ALAUDA_PORT_SM 0x01 - -/* - * LBA and PBA are unsigned ints. Special values. - */ -#define UNDEF 0xffff -#define SPARE 0xfffe -#define UNUSABLE 0xfffd - -int init_alauda(struct us_data *us); -int alauda_transport(struct scsi_cmnd *srb, struct us_data *us); - -struct alauda_media_info { - unsigned long capacity; /* total media size in bytes */ - unsigned int pagesize; /* page size in bytes */ - unsigned int blocksize; /* number of pages per block */ - unsigned int uzonesize; /* number of usable blocks per zone */ - unsigned int zonesize; /* number of blocks per zone */ - unsigned int blockmask; /* mask to get page from address */ - - unsigned char pageshift; - unsigned char blockshift; - unsigned char zoneshift; - - u16 **lba_to_pba; /* logical to physical block map */ - u16 **pba_to_lba; /* physical to logical block map */ -}; - -struct alauda_info { - struct alauda_media_info port[2]; - int wr_ep; /* endpoint to write data out of */ - - unsigned char sense_key; - unsigned long sense_asc; /* additional sense code */ - unsigned long sense_ascq; /* additional sense code qualifier */ -}; - -#endif - diff --git a/drivers/usb/storage/unusual_alauda.h b/drivers/usb/storage/unusual_alauda.h new file mode 100644 index 00000000000..8c412f885dd --- /dev/null +++ b/drivers/usb/storage/unusual_alauda.h @@ -0,0 +1,31 @@ +/* Unusual Devices File for the Alauda-based card readers + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_ALAUDA) || \ + defined(CONFIG_USB_STORAGE_ALAUDA_MODULE) + +UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, + "Fujifilm", + "DPC-R1 (Alauda)", + US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0), + +UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, + "Olympus", + "MAUSB-10 (Alauda)", + US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0), + +#endif /* defined(CONFIG_USB_STORAGE_ALAUDA) || ... */ diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 24e23c29d29..bcdb74dfa3d 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -692,13 +692,6 @@ UNUSUAL_DEV( 0x057b, 0x0022, 0x0000, 0x9999, "Silicon Media R/W", US_SC_DEVICE, US_PR_DEVICE, NULL, 0), -#ifdef CONFIG_USB_STORAGE_ALAUDA -UNUSUAL_DEV( 0x0584, 0x0008, 0x0102, 0x0102, - "Fujifilm", - "DPC-R1 (Alauda)", - US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), -#endif - /* Reported by RTE */ UNUSUAL_DEV( 0x058f, 0x6387, 0x0141, 0x0141, "JetFlash", @@ -977,13 +970,6 @@ UNUSUAL_DEV( 0x07af, 0x0006, 0x0100, 0x0100, US_FL_SINGLE_LUN ), #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA -UNUSUAL_DEV( 0x07b4, 0x010a, 0x0102, 0x0102, - "Olympus", - "MAUSB-10 (Alauda)", - US_SC_SCSI, US_PR_ALAUDA, init_alauda, 0 ), -#endif - /* Datafab KECF-USB / Sagatek DCS-CF / Simpletech Flashlink UCF-100 * Only revision 1.13 tested (same for all of the above devices, * based on the Datafab DF-UG-07 chip). Needed for US_FL_FIX_INQUIRY. diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 2ea57691a7b..cd039c00846 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_ONETOUCH #include "onetouch.h" #endif -#ifdef CONFIG_USB_STORAGE_ALAUDA -#include "alauda.h" -#endif #ifdef CONFIG_USB_STORAGE_KARMA #include "karma.h" #endif @@ -598,15 +595,6 @@ static void get_transport(struct us_data *us) us->transport_reset = usb_stor_Bulk_reset; break; -#ifdef CONFIG_USB_STORAGE_ALAUDA - case US_PR_ALAUDA: - us->transport_name = "Alauda Control/Bulk"; - us->transport = alauda_transport; - us->transport_reset = usb_stor_Bulk_reset; - us->max_lun = 1; - break; -#endif - #ifdef CONFIG_USB_STORAGE_KARMA case US_PR_KARMA: us->transport_name = "Rio Karma/Bulk"; diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index 182a097e076..ad102e8e191 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -77,6 +77,7 @@ struct ignore_entry { } static struct ignore_entry ignore_ids[] = { +# include "unusual_alauda.h" # include "unusual_cypress.h" # include "unusual_datafab.h" # include "unusual_freecom.h" -- cgit v1.2.3 From c10337846c93bd914dd3003ffb001adc583b313e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:26 -0500 Subject: usb-storage: make karma a separate module This patch (as1216) converts usb-storage's karma subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/karma.c | 96 +++++++++++++++++++++++++++++++++++-- drivers/usb/storage/karma.h | 7 --- drivers/usb/storage/unusual_devs.h | 7 --- drivers/usb/storage/unusual_karma.h | 26 ++++++++++ drivers/usb/storage/usb.c | 12 ----- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 123 insertions(+), 33 deletions(-) delete mode 100644 drivers/usb/storage/karma.h create mode 100644 drivers/usb/storage/unusual_karma.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index c56c2c6d37b..8adece1dd29 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -144,7 +144,7 @@ config USB_STORAGE_ONETOUCH cuts) config USB_STORAGE_KARMA - bool "Support for Rio Karma music player" + tristate "Support for Rio Karma music player" depends on USB_STORAGE help Say Y here to include additional code to support the Rio Karma @@ -155,6 +155,8 @@ config USB_STORAGE_KARMA on the resulting scsi device node returns the Karma to normal operation. + If this driver is compiled as a module, it will be named ums-karma. + config USB_STORAGE_CYPRESS_ATACB tristate "SAT emulation on Cypress USB/ATA Bridge with ATACB" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index fea05c0b676..870680ea370 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o -usb-storage-obj-$(CONFIG_USB_STORAGE_KARMA) += karma.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) @@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_DATAFAB) += ums-datafab.o obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o +obj-$(CONFIG_USB_STORAGE_KARMA) += ums-karma.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o @@ -38,6 +38,7 @@ ums-datafab-objs := datafab.o ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-jumpshot-objs := jumpshot.o +ums-karma-objs := karma.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index 0d79ae5683f..cfb8e60866b 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -18,6 +18,8 @@ * 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include + #include #include #include @@ -25,7 +27,6 @@ #include "usb.h" #include "transport.h" #include "debug.h" -#include "karma.h" #define RIO_PREFIX "RIOP\x00" #define RIO_PREFIX_LEN 5 @@ -36,13 +37,53 @@ #define RIO_LEAVE_STORAGE 0x2 #define RIO_RESET 0xC -extern int usb_stor_Bulk_transport(struct scsi_cmnd *, struct us_data *); - struct karma_data { int in_storage; char *recv; }; +static int rio_karma_init(struct us_data *us); + + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id karma_usb_ids[] = { +# include "unusual_karma.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, karma_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev karma_unusual_dev_list[] = { +# include "unusual_karma.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + /* * Send commands to Rio Karma. * @@ -104,7 +145,7 @@ err: * Trap START_STOP and READ_10 to leave/re-enter storage mode. * Everything else is propagated to the normal bulk layer. */ -int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us) +static int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us) { int ret; struct karma_data *data = (struct karma_data *) us->extra; @@ -133,7 +174,7 @@ static void rio_karma_destructor(void *extra) kfree(data->recv); } -int rio_karma_init(struct us_data *us) +static int rio_karma_init(struct us_data *us) { int ret = 0; struct karma_data *data = kzalloc(sizeof(struct karma_data), GFP_NOIO); @@ -153,3 +194,48 @@ int rio_karma_init(struct us_data *us) out: return ret; } + +static int karma_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - karma_usb_ids) + karma_unusual_dev_list); + if (result) + return result; + + us->transport_name = "Rio Karma/Bulk"; + us->transport = rio_karma_transport; + us->transport_reset = usb_stor_Bulk_reset; + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver karma_driver = { + .name = "ums-karma", + .probe = karma_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = karma_usb_ids, + .soft_unbind = 1, +}; + +static int __init karma_init(void) +{ + return usb_register(&karma_driver); +} + +static void __exit karma_exit(void) +{ + usb_deregister(&karma_driver); +} + +module_init(karma_init); +module_exit(karma_exit); diff --git a/drivers/usb/storage/karma.h b/drivers/usb/storage/karma.h deleted file mode 100644 index 8a60972af8c..00000000000 --- a/drivers/usb/storage/karma.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef _KARMA_USB_H -#define _KARMA_USB_H - -extern int rio_karma_init(struct us_data *us); -extern int rio_karma_transport(struct scsi_cmnd *srb, struct us_data *us); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index bcdb74dfa3d..83e34a6ad59 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -276,13 +276,6 @@ UNUSUAL_DEV( 0x0457, 0x0151, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_NOT_LOCKABLE ), -#ifdef CONFIG_USB_STORAGE_KARMA -UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, - "Rio", - "Rio Karma", - US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0), -#endif - /* Reported by Tamas Kerecsen * Obviously the PROM has not been customized by the VAR; * the Vendor and Product string descriptors are: diff --git a/drivers/usb/storage/unusual_karma.h b/drivers/usb/storage/unusual_karma.h new file mode 100644 index 00000000000..12ae3a03e80 --- /dev/null +++ b/drivers/usb/storage/unusual_karma.h @@ -0,0 +1,26 @@ +/* Unusual Devices File for the Rio Karma + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_KARMA) || \ + defined(CONFIG_USB_STORAGE_KARMA_MODULE) + +UNUSUAL_DEV( 0x045a, 0x5210, 0x0101, 0x0101, + "Rio", + "Rio Karma", + US_SC_SCSI, US_PR_KARMA, rio_karma_init, 0), + +#endif /* defined(CONFIG_USB_STORAGE_KARMA) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index cd039c00846..c5abf9bbce1 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -69,9 +69,6 @@ #ifdef CONFIG_USB_STORAGE_ONETOUCH #include "onetouch.h" #endif -#ifdef CONFIG_USB_STORAGE_KARMA -#include "karma.h" -#endif #include "sierra_ms.h" #include "option_ms.h" @@ -594,15 +591,6 @@ static void get_transport(struct us_data *us) us->transport = usb_stor_Bulk_transport; us->transport_reset = usb_stor_Bulk_reset; break; - -#ifdef CONFIG_USB_STORAGE_KARMA - case US_PR_KARMA: - us->transport_name = "Rio Karma/Bulk"; - us->transport = rio_karma_transport; - us->transport_reset = usb_stor_Bulk_reset; - break; -#endif - } } diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index ad102e8e191..bce086fcef5 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -83,6 +83,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_freecom.h" # include "unusual_isd200.h" # include "unusual_jumpshot.h" +# include "unusual_karma.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" # include "unusual_usbat.h" -- cgit v1.2.3 From 9cfb95ef72c637bc9b90260e0f98a23f3f49b1bb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 12 Feb 2009 14:48:33 -0500 Subject: usb-storage: make onetouch a separate module This patch (as1217) converts usb-storage's onetouch subdriver into a separate module. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/Kconfig | 4 +- drivers/usb/storage/Makefile | 3 +- drivers/usb/storage/onetouch.c | 90 +++++++++++++++++++++++++++++++++- drivers/usb/storage/onetouch.h | 9 ---- drivers/usb/storage/unusual_devs.h | 17 ------- drivers/usb/storage/unusual_onetouch.h | 36 ++++++++++++++ drivers/usb/storage/usb.c | 3 -- drivers/usb/storage/usual-tables.c | 1 + 8 files changed, 130 insertions(+), 33 deletions(-) delete mode 100644 drivers/usb/storage/onetouch.h create mode 100644 drivers/usb/storage/unusual_onetouch.h (limited to 'drivers') diff --git a/drivers/usb/storage/Kconfig b/drivers/usb/storage/Kconfig index 8adece1dd29..8a372bac0e4 100644 --- a/drivers/usb/storage/Kconfig +++ b/drivers/usb/storage/Kconfig @@ -131,7 +131,7 @@ config USB_STORAGE_ALAUDA If this driver is compiled as a module, it will be named ums-alauda. config USB_STORAGE_ONETOUCH - bool "Support OneTouch Button on Maxtor Hard Drives" + tristate "Support OneTouch Button on Maxtor Hard Drives" depends on USB_STORAGE depends on INPUT=y || INPUT=USB_STORAGE help @@ -143,6 +143,8 @@ config USB_STORAGE_ONETOUCH this input in any keybinding software. (e.g. gnome's keyboard short- cuts) + If this driver is compiled as a module, it will be named ums-onetouch. + config USB_STORAGE_KARMA tristate "Support for Rio Karma music player" depends on USB_STORAGE diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile index 870680ea370..5be54c01966 100644 --- a/drivers/usb/storage/Makefile +++ b/drivers/usb/storage/Makefile @@ -10,7 +10,6 @@ EXTRA_CFLAGS := -Idrivers/scsi obj-$(CONFIG_USB_STORAGE) += usb-storage.o usb-storage-obj-$(CONFIG_USB_STORAGE_DEBUG) += debug.o -usb-storage-obj-$(CONFIG_USB_STORAGE_ONETOUCH) += onetouch.o usb-storage-objs := scsiglue.o protocol.o transport.o usb.o \ initializers.o sierra_ms.o option_ms.o $(usb-storage-obj-y) @@ -28,6 +27,7 @@ obj-$(CONFIG_USB_STORAGE_FREECOM) += ums-freecom.o obj-$(CONFIG_USB_STORAGE_ISD200) += ums-isd200.o obj-$(CONFIG_USB_STORAGE_JUMPSHOT) += ums-jumpshot.o obj-$(CONFIG_USB_STORAGE_KARMA) += ums-karma.o +obj-$(CONFIG_USB_STORAGE_ONETOUCH) += ums-onetouch.o obj-$(CONFIG_USB_STORAGE_SDDR09) += ums-sddr09.o obj-$(CONFIG_USB_STORAGE_SDDR55) += ums-sddr55.o obj-$(CONFIG_USB_STORAGE_USBAT) += ums-usbat.o @@ -39,6 +39,7 @@ ums-freecom-objs := freecom.o ums-isd200-objs := isd200.o ums-jumpshot-objs := jumpshot.o ums-karma-objs := karma.o +ums-onetouch-objs := onetouch.o ums-sddr09-objs := sddr09.o ums-sddr55-objs := sddr55.o ums-usbat-objs := shuttle_usbat.o diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index c7bf8954b4e..8bd095635a9 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -35,9 +35,12 @@ #include #include #include "usb.h" -#include "onetouch.h" #include "debug.h" +#define ONETOUCH_PKT_LEN 0x02 +#define ONETOUCH_BUTTON KEY_PROG1 + +static int onetouch_connect_input(struct us_data *ss); static void onetouch_release_input(void *onetouch_); struct usb_onetouch { @@ -52,6 +55,46 @@ struct usb_onetouch { unsigned int is_open:1; }; + +/* + * The table of devices + */ +#define UNUSUAL_DEV(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax, \ + vendorName, productName, useProtocol, useTransport, \ + initFunction, flags) \ +{ USB_DEVICE_VER(id_vendor, id_product, bcdDeviceMin, bcdDeviceMax), \ + .driver_info = (flags)|(USB_US_TYPE_STOR<<24) } + +struct usb_device_id onetouch_usb_ids[] = { +# include "unusual_onetouch.h" + { } /* Terminating entry */ +}; +MODULE_DEVICE_TABLE(usb, onetouch_usb_ids); + +#undef UNUSUAL_DEV + +/* + * The flags table + */ +#define UNUSUAL_DEV(idVendor, idProduct, bcdDeviceMin, bcdDeviceMax, \ + vendor_name, product_name, use_protocol, use_transport, \ + init_function, Flags) \ +{ \ + .vendorName = vendor_name, \ + .productName = product_name, \ + .useProtocol = use_protocol, \ + .useTransport = use_transport, \ + .initFunction = init_function, \ +} + +static struct us_unusual_dev onetouch_unusual_dev_list[] = { +# include "unusual_onetouch.h" + { } /* Terminating entry */ +}; + +#undef UNUSUAL_DEV + + static void usb_onetouch_irq(struct urb *urb) { struct usb_onetouch *onetouch = urb->context; @@ -127,7 +170,7 @@ static void usb_onetouch_pm_hook(struct us_data *us, int action) } #endif /* CONFIG_PM */ -int onetouch_connect_input(struct us_data *ss) +static int onetouch_connect_input(struct us_data *ss) { struct usb_device *udev = ss->pusb_dev; struct usb_host_interface *interface; @@ -236,3 +279,46 @@ static void onetouch_release_input(void *onetouch_) onetouch->data, onetouch->data_dma); } } + +static int onetouch_probe(struct usb_interface *intf, + const struct usb_device_id *id) +{ + struct us_data *us; + int result; + + result = usb_stor_probe1(&us, intf, id, + (id - onetouch_usb_ids) + onetouch_unusual_dev_list); + if (result) + return result; + + /* Use default transport and protocol */ + + result = usb_stor_probe2(us); + return result; +} + +static struct usb_driver onetouch_driver = { + .name = "ums-onetouch", + .probe = onetouch_probe, + .disconnect = usb_stor_disconnect, + .suspend = usb_stor_suspend, + .resume = usb_stor_resume, + .reset_resume = usb_stor_reset_resume, + .pre_reset = usb_stor_pre_reset, + .post_reset = usb_stor_post_reset, + .id_table = onetouch_usb_ids, + .soft_unbind = 1, +}; + +static int __init onetouch_init(void) +{ + return usb_register(&onetouch_driver); +} + +static void __exit onetouch_exit(void) +{ + usb_deregister(&onetouch_driver); +} + +module_init(onetouch_init); +module_exit(onetouch_exit); diff --git a/drivers/usb/storage/onetouch.h b/drivers/usb/storage/onetouch.h deleted file mode 100644 index 41c7aa8f044..00000000000 --- a/drivers/usb/storage/onetouch.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _ONETOUCH_H_ -#define _ONETOUCH_H_ - -#define ONETOUCH_PKT_LEN 0x02 -#define ONETOUCH_BUTTON KEY_PROG1 - -int onetouch_connect_input(struct us_data *ss); - -#endif diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 83e34a6ad59..1c1f643e8a7 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h @@ -1182,23 +1182,6 @@ UNUSUAL_DEV( 0x0c45, 0x1060, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -/* Submitted by: Nick Sillik - * Needed for OneTouch extension to usb-storage - * - */ -#ifdef CONFIG_USB_STORAGE_ONETOUCH - UNUSUAL_DEV( 0x0d49, 0x7000, 0x0000, 0x9999, - "Maxtor", - "OneTouch External Harddrive", - US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, - 0), - UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999, - "Maxtor", - "OneTouch External Harddrive", - US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, - 0), -#endif - /* Submitted by Joris Struyve */ UNUSUAL_DEV( 0x0d96, 0x410a, 0x0001, 0xffff, "Medion", diff --git a/drivers/usb/storage/unusual_onetouch.h b/drivers/usb/storage/unusual_onetouch.h new file mode 100644 index 00000000000..bd9306b637d --- /dev/null +++ b/drivers/usb/storage/unusual_onetouch.h @@ -0,0 +1,36 @@ +/* Unusual Devices File for the Maxtor OneTouch USB hard drive's button + * + * 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, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#if defined(CONFIG_USB_STORAGE_ONETOUCH) || \ + defined(CONFIG_USB_STORAGE_ONETOUCH_MODULE) + +/* Submitted by: Nick Sillik + * Needed for OneTouch extension to usb-storage + */ +UNUSUAL_DEV( 0x0d49, 0x7000, 0x0000, 0x9999, + "Maxtor", + "OneTouch External Harddrive", + US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, + 0), + +UNUSUAL_DEV( 0x0d49, 0x7010, 0x0000, 0x9999, + "Maxtor", + "OneTouch External Harddrive", + US_SC_DEVICE, US_PR_DEVICE, onetouch_connect_input, + 0), + +#endif /* defined(CONFIG_USB_STORAGE_ONETOUCH) || ... */ diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index c5abf9bbce1..8060b85fe1a 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c @@ -66,9 +66,6 @@ #include "debug.h" #include "initializers.h" -#ifdef CONFIG_USB_STORAGE_ONETOUCH -#include "onetouch.h" -#endif #include "sierra_ms.h" #include "option_ms.h" diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index bce086fcef5..468bde7d197 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c @@ -84,6 +84,7 @@ static struct ignore_entry ignore_ids[] = { # include "unusual_isd200.h" # include "unusual_jumpshot.h" # include "unusual_karma.h" +# include "unusual_onetouch.h" # include "unusual_sddr09.h" # include "unusual_sddr55.h" # include "unusual_usbat.h" -- cgit v1.2.3 From 4246b06a33ebdd6593dccaab3aa01eb0c9f8c1c8 Mon Sep 17 00:00:00 2001 From: Maciej Grela Date: Sat, 28 Feb 2009 12:39:20 -0800 Subject: USB: usb-storage: added missing MODULE_LICENSE("GPL") for usb-storage ums-* modules The lack of a MODULE_LICENSE macro in ums-* subdrivers prevented them from loading. Needs to be applied after Alan Stern's usb-storage subdriver separation patchset. Also added missing MODULE_DESCRIPTION and MODULE_AUTHOR entries. Signed-off-by: Maciej Grela Acked-by: Alan Stern Acked-by: Matthew Dharm Signed-off-by: Greg Kroah-Hartman --- drivers/usb/storage/alauda.c | 4 ++++ drivers/usb/storage/cypress_atacb.c | 3 +++ drivers/usb/storage/datafab.c | 4 ++++ drivers/usb/storage/freecom.c | 4 ++++ drivers/usb/storage/isd200.c | 3 +++ drivers/usb/storage/jumpshot.c | 4 ++++ drivers/usb/storage/karma.c | 4 ++++ drivers/usb/storage/onetouch.c | 4 ++++ drivers/usb/storage/sddr09.c | 3 +++ drivers/usb/storage/sddr55.c | 3 +++ drivers/usb/storage/shuttle_usbat.c | 3 +++ 11 files changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c index d3a88ebe690..67edc65acb8 100644 --- a/drivers/usb/storage/alauda.c +++ b/drivers/usb/storage/alauda.c @@ -42,6 +42,10 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Alauda-based card readers"); +MODULE_AUTHOR("Daniel Drake "); +MODULE_LICENSE("GPL"); + /* * Status bytes */ diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c index 19306f7b1da..c8447182118 100644 --- a/drivers/usb/storage/cypress_atacb.c +++ b/drivers/usb/storage/cypress_atacb.c @@ -30,6 +30,9 @@ #include "scsiglue.h" #include "debug.h" +MODULE_DESCRIPTION("SAT support for Cypress USB/ATA bridges with ATACB"); +MODULE_AUTHOR("Matthieu Castet "); +MODULE_LICENSE("GPL"); /* * The table of devices diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c index 2d8d8351909..2b6e565262c 100644 --- a/drivers/usb/storage/datafab.c +++ b/drivers/usb/storage/datafab.c @@ -60,6 +60,10 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Datafab USB Compact Flash reader"); +MODULE_AUTHOR("Jimmie Mayfield "); +MODULE_LICENSE("GPL"); + struct datafab_info { unsigned long sectors; /* total sector count */ unsigned long ssize; /* sector size in bytes */ diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c index 393047b3890..54cc94277ac 100644 --- a/drivers/usb/storage/freecom.c +++ b/drivers/usb/storage/freecom.c @@ -35,6 +35,10 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Freecom USB/IDE adaptor"); +MODULE_AUTHOR("David Brown "); +MODULE_LICENSE("GPL"); + #ifdef CONFIG_USB_STORAGE_DEBUG static void pdump (void *, int); #endif diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c index df943008538..882c57b399f 100644 --- a/drivers/usb/storage/isd200.c +++ b/drivers/usb/storage/isd200.c @@ -59,6 +59,9 @@ #include "debug.h" #include "scsiglue.h" +MODULE_DESCRIPTION("Driver for In-System Design, Inc. ISD200 ASIC"); +MODULE_AUTHOR("Björn Stenberg "); +MODULE_LICENSE("GPL"); static int isd200_Initialization(struct us_data *us); diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c index a50d6dc1fe6..1c69420e3ac 100644 --- a/drivers/usb/storage/jumpshot.c +++ b/drivers/usb/storage/jumpshot.c @@ -58,6 +58,10 @@ #include "debug.h" +MODULE_DESCRIPTION("Driver for Lexar \"Jumpshot\" Compact Flash reader"); +MODULE_AUTHOR("Jimmie Mayfield "); +MODULE_LICENSE("GPL"); + /* * The table of devices */ diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c index cfb8e60866b..7953d93a773 100644 --- a/drivers/usb/storage/karma.c +++ b/drivers/usb/storage/karma.c @@ -28,6 +28,10 @@ #include "transport.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for Rio Karma"); +MODULE_AUTHOR("Bob Copeland , Keith Bennett "); +MODULE_LICENSE("GPL"); + #define RIO_PREFIX "RIOP\x00" #define RIO_PREFIX_LEN 5 #define RIO_SEND_LEN 40 diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c index 8bd095635a9..380233bd6a3 100644 --- a/drivers/usb/storage/onetouch.c +++ b/drivers/usb/storage/onetouch.c @@ -37,6 +37,10 @@ #include "usb.h" #include "debug.h" +MODULE_DESCRIPTION("Maxtor USB OneTouch hard drive button driver"); +MODULE_AUTHOR("Nick Sillik "); +MODULE_LICENSE("GPL"); + #define ONETOUCH_PKT_LEN 0x02 #define ONETOUCH_BUTTON KEY_PROG1 diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c index 170ad86b2d3..ab5f9f37575 100644 --- a/drivers/usb/storage/sddr09.c +++ b/drivers/usb/storage/sddr09.c @@ -53,6 +53,9 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for SanDisk SDDR-09 SmartMedia reader"); +MODULE_AUTHOR("Andries Brouwer , Robert Baruch "); +MODULE_LICENSE("GPL"); static int usb_stor_sddr09_dpcm_init(struct us_data *us); static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us); diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c index e97716f8eb0..44dfed7754e 100644 --- a/drivers/usb/storage/sddr55.c +++ b/drivers/usb/storage/sddr55.c @@ -35,6 +35,9 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for SanDisk SDDR-55 SmartMedia reader"); +MODULE_AUTHOR("Simon Munton"); +MODULE_LICENSE("GPL"); /* * The table of devices diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c index d4fe0bb327a..b62a28814eb 100644 --- a/drivers/usb/storage/shuttle_usbat.c +++ b/drivers/usb/storage/shuttle_usbat.c @@ -54,6 +54,9 @@ #include "protocol.h" #include "debug.h" +MODULE_DESCRIPTION("Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable"); +MODULE_AUTHOR("Daniel Drake , Robert Baruch "); +MODULE_LICENSE("GPL"); /* Supported device types */ #define USBAT_DEV_HP8200 0x01 -- cgit v1.2.3 From 6da9c99059bf24fb1faae6b9613bae64ea50c05e Mon Sep 17 00:00:00 2001 From: David Vrabel Date: Wed, 18 Feb 2009 14:43:47 +0000 Subject: USB: allow libusb to talk to unauthenticated WUSB devices To permit a userspace application to associate with WUSB devices using numeric association, control transfers to unauthenticated WUSB devices must be allowed. This requires that wusbcore correctly sets the device state to UNAUTHENTICATED, DEFAULT and ADDRESS and that control transfers can be performed to UNAUTHENTICATED devices. Signed-off-by: David Vrabel Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 3 ++- drivers/usb/core/hub.c | 1 + drivers/usb/core/urb.c | 2 +- drivers/usb/wusbcore/devconnect.c | 2 ++ drivers/usb/wusbcore/security.c | 2 ++ 5 files changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 6585f527e38..8f022af2fd7 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -525,7 +525,8 @@ static int check_ctrlrecip(struct dev_state *ps, unsigned int requesttype, { int ret = 0; - if (ps->dev->state != USB_STATE_ADDRESS + if (ps->dev->state != USB_STATE_UNAUTHENTICATED + && ps->dev->state != USB_STATE_ADDRESS && ps->dev->state != USB_STATE_CONFIGURED) return -EHOSTUNREACH; if (USB_TYPE_VENDOR == (USB_TYPE_MASK & requesttype)) diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 7e33d63ab92..f17d9ebc44a 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -1305,6 +1305,7 @@ void usb_set_device_state(struct usb_device *udev, recursively_mark_NOTATTACHED(udev); spin_unlock_irqrestore(&device_state_lock, flags); } +EXPORT_SYMBOL_GPL(usb_set_device_state); /* * WUSB devices are simple: they have no hubs behind, so the mapping diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 58bc5e3c256..7025d801f23 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -295,7 +295,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) if (!urb || urb->hcpriv || !urb->complete) return -EINVAL; dev = urb->dev; - if ((!dev) || (dev->state < USB_STATE_DEFAULT)) + if ((!dev) || (dev->state < USB_STATE_UNAUTHENTICATED)) return -ENODEV; /* For now, get the endpoint from the pipe. Eventually drivers diff --git a/drivers/usb/wusbcore/devconnect.c b/drivers/usb/wusbcore/devconnect.c index 8e18141bb2e..f0aac0cf315 100644 --- a/drivers/usb/wusbcore/devconnect.c +++ b/drivers/usb/wusbcore/devconnect.c @@ -889,6 +889,8 @@ static void wusb_dev_add_ncb(struct usb_device *usb_dev) if (usb_dev->wusb == 0 || usb_dev->devnum == 1) return; /* skip non wusb and wusb RHs */ + usb_set_device_state(usb_dev, USB_STATE_UNAUTHENTICATED); + wusbhc = wusbhc_get_by_usb_dev(usb_dev); if (wusbhc == NULL) goto error_nodev; diff --git a/drivers/usb/wusbcore/security.c b/drivers/usb/wusbcore/security.c index f4aa28eca70..8118db7f1d8 100644 --- a/drivers/usb/wusbcore/security.c +++ b/drivers/usb/wusbcore/security.c @@ -312,6 +312,7 @@ int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) result = wusb_set_dev_addr(wusbhc, wusb_dev, 0); if (result < 0) goto error_addr0; + usb_set_device_state(usb_dev, USB_STATE_DEFAULT); usb_ep0_reinit(usb_dev); /* Set new (authenticated) address. */ @@ -327,6 +328,7 @@ int wusb_dev_update_address(struct wusbhc *wusbhc, struct wusb_dev *wusb_dev) result = wusb_set_dev_addr(wusbhc, wusb_dev, new_address); if (result < 0) goto error_addr; + usb_set_device_state(usb_dev, USB_STATE_ADDRESS); usb_ep0_reinit(usb_dev); usb_dev->authenticated = 1; error_addr: -- cgit v1.2.3 From b2bdf3a789162aa6ff9c6f139bee9cc7954bc5b4 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Thu, 12 Feb 2009 15:09:47 +0200 Subject: USB: composite: avoid inconsistent lock state Avoid the following INFO from lock debugging: [ 369.126112] ================================= [ 369.132063] [ INFO: inconsistent lock state ] [ 369.136457] 2.6.28-maemo1 #1 [ 369.139387] --------------------------------- [ 369.143782] inconsistent {hardirq-on-W} -> {in-hardirq-W} usage. [ 369.149855] swapper/0 [HC1[1]:SC0[0]:HE0:SE1] takes: [ 369.154890] (&cdev->lock){+-..}, at: [] composite_disconnect+0x1c/0] [ 369.163404] {hardirq-on-W} state was registered at: [ 369.168348] [] __lock_acquire+0x5d0/0x7d8 [ 369.173506] [] lock_acquire+0x64/0x78 [ 369.178266] [] _spin_lock+0x4c/0x80 [ 369.182905] [] usb_function_deactivate+0x20/0x70 [g_nokia] [ 369.189527] [] 0xbf1a0a88 [ 369.193281] [] 0xbf19f450 [ 369.197004] [] 0xbf19fa3c [ 369.200758] [] 0xbf1a03a0 [ 369.204481] [] 0xbf19f254 [ 369.208204] [] 0xbf1a0158 [ 369.211927] [] 0xbf1a130c [ 369.215650] [] usb_gadget_register_driver+0x12c/0x28c [ 369.221846] [] 0xbf1a06bc [ 369.225569] [] 0xbf1a06e8 [ 369.229322] [] __exception_text_end+0x64/0x19c [ 369.234877] [] sys_init_module+0x9c/0x194 [ 369.240004] [] ret_fast_syscall+0x0/0x2c [ 369.245039] [] 0xffffffff [ 369.248793] irq event stamp: 218356 [ 369.252302] hardirqs last enabled at (218355): [] omap3_enter_idle+8 [ 369.260420] hardirqs last disabled at (218356): [] __irq_svc+0x34/0x0 [ 369.267927] softirqs last enabled at (218348): [] __do_softirq+0x134 [ 369.275892] softirqs last disabled at (218335): [] irq_exit+0x60/0xb0 [ 369.283308] [ 369.283308] other info that might help us debug this: [ 369.289930] no locks held by swapper/0. Cc: David Brownell Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 5d11c291f1a..40f1da77a00 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -149,16 +149,17 @@ done: int usb_function_deactivate(struct usb_function *function) { struct usb_composite_dev *cdev = function->config->cdev; + unsigned long flags; int status = 0; - spin_lock(&cdev->lock); + spin_lock_irqsave(&cdev->lock, flags); if (cdev->deactivations == 0) status = usb_gadget_disconnect(cdev->gadget); if (status == 0) cdev->deactivations++; - spin_unlock(&cdev->lock); + spin_unlock_irqrestore(&cdev->lock, flags); return status; } -- cgit v1.2.3 From 5d67a851bca63d30cde0474bfc4fc4f03db1a1b8 Mon Sep 17 00:00:00 2001 From: Sergei Shtylyov Date: Tue, 24 Feb 2009 15:23:34 -0800 Subject: USB: musb: rewrite host periodic endpoint allocation The current MUSB host code doesn't make use of all the available FIFOs in for periodic transfers since it wrongly assumes the RX and TX sides of any given hw_ep always share one FIFO. Change: use 'in_qh' and 'out_qh' fields of the 'struct musb_hw_ep' to check the endpoint's business; get rid of the now-unused 'periodic' array in the 'struct musb'. Also optimize a loop induction variable in the endpoint lookup code. (Based on a previous patch from Ajay Kumar Gupta ) [ dbrownell@users.sourceforge.net: clarify description and origin of this fix; whitespace ] Signed-off-by: Sergei Shtylyov Signed-off-by: David Brownell Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.h | 1 - drivers/usb/musb/musb_host.c | 28 +++++++++++----------------- 2 files changed, 11 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index 630946a2d9f..adf1806007f 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -331,7 +331,6 @@ struct musb { struct list_head control; /* of musb_qh */ struct list_head in_bulk; /* of musb_qh */ struct list_head out_bulk; /* of musb_qh */ - struct musb_qh *periodic[32]; /* tree of interrupt+iso */ #endif /* called with IRQs blocked; ON/nonzero implies starting a session, diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 6dbbd0786a6..9489c859868 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -395,7 +395,6 @@ musb_giveback(struct musb_qh *qh, struct urb *urb, int status) * de-allocated if it's tracked and allocated; * and where we'd update the schedule tree... */ - musb->periodic[ep->epnum] = NULL; kfree(qh); qh = NULL; break; @@ -1711,31 +1710,27 @@ static int musb_schedule( /* else, periodic transfers get muxed to other endpoints */ - /* FIXME this doesn't consider direction, so it can only - * work for one half of the endpoint hardware, and assumes - * the previous cases handled all non-shared endpoints... - */ - - /* we know this qh hasn't been scheduled, so all we need to do + /* + * We know this qh hasn't been scheduled, so all we need to do * is choose which hardware endpoint to put it on ... * * REVISIT what we really want here is a regular schedule tree - * like e.g. OHCI uses, but for now musb->periodic is just an - * array of the _single_ logical endpoint associated with a - * given physical one (identity mapping logical->physical). - * - * that simplistic approach makes TT scheduling a lot simpler; - * there is none, and thus none of its complexity... + * like e.g. OHCI uses. */ best_diff = 4096; best_end = -1; - for (epnum = 1; epnum < musb->nr_endpoints; epnum++) { + for (epnum = 1, hw_ep = musb->endpoints + 1; + epnum < musb->nr_endpoints; + epnum++, hw_ep++) { int diff; - if (musb->periodic[epnum]) + if (is_in || hw_ep->is_shared_fifo) { + if (hw_ep->in_qh != NULL) + continue; + } else if (hw_ep->out_qh != NULL) continue; - hw_ep = &musb->endpoints[epnum]; + if (hw_ep == musb->bulk_ep) continue; @@ -1764,7 +1759,6 @@ static int musb_schedule( idle = 1; qh->mux = 0; hw_ep = musb->endpoints + best_end; - musb->periodic[best_end] = qh; DBG(4, "qh %p periodic slot %d\n", qh, best_end); success: if (head) { -- cgit v1.2.3 From 1e0320f0d46022d12ddc84516cbdb8865e8cd744 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 24 Feb 2009 15:26:13 -0800 Subject: USB: musb: NAK timeout scheme on bulk RX endpoint Fixes endpoint starvation issue when more than one bulk QH is multiplexed on the reserved bulk RX endpoint, which is normal for cases like serial and ethernet adapters. This patch sets the NAK timeout interval for such QHs, and when a timeout triggers the next QH will be scheduled. (This resembles the bulk scheduling done in hardware by EHCI, OHCI, and UHCI.) This scheme doesn't work for devices which are connected to a high to full speed tree (transaction translator) as there is no NAK timeout interrupt from the musb controller from such devices. Tested with PIO, Inventra DMA, CPPI DMA. [ dbrownell@users.sourceforge.net: fold in start_urb() update; clarify only for bulk RX; don't accidentally clear WZC bits ] Signed-off-by: Ajay Kumar Gupta Cc: Felipe Balbi Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_host.c | 112 ++++++++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c index 9489c859868..499c431a6d6 100644 --- a/drivers/usb/musb/musb_host.c +++ b/drivers/usb/musb/musb_host.c @@ -64,11 +64,8 @@ * * - DMA (Mentor/OMAP) ...has at least toggle update problems * - * - Still no traffic scheduling code to make NAKing for bulk or control - * transfers unable to starve other requests; or to make efficient use - * of hardware with periodic transfers. (Note that network drivers - * commonly post bulk reads that stay pending for a long time; these - * would make very visible trouble.) + * - [23-feb-2009] minimal traffic scheduling to avoid bulk RX packet + * starvation ... nothing yet for TX, interrupt, or bulk. * * - Not tested with HNP, but some SRP paths seem to behave. * @@ -88,11 +85,8 @@ * * CONTROL transfers all go through ep0. BULK ones go through dedicated IN * and OUT endpoints ... hardware is dedicated for those "async" queue(s). - * * (Yes, bulk _could_ use more of the endpoints than that, and would even - * benefit from it ... one remote device may easily be NAKing while others - * need to perform transfers in that same direction. The same thing could - * be done in software though, assuming dma cooperates.) + * benefit from it.) * * INTERUPPT and ISOCHRONOUS transfers are scheduled to the other endpoints. * So far that scheduling is both dumb and optimistic: the endpoint will be @@ -201,8 +195,9 @@ musb_start_urb(struct musb *musb, int is_in, struct musb_qh *qh) len = urb->iso_frame_desc[0].length; break; default: /* bulk, interrupt */ - buf = urb->transfer_buffer; - len = urb->transfer_buffer_length; + /* actual_length may be nonzero on retry paths */ + buf = urb->transfer_buffer + urb->actual_length; + len = urb->transfer_buffer_length - urb->actual_length; } DBG(4, "qh %p urb %p dev%d ep%d%s%s, hw_ep %d, %p/%d\n", @@ -1044,7 +1039,8 @@ irqreturn_t musb_h_ep0_irq(struct musb *musb) /* NOTE: this code path would be a good place to PAUSE a * control transfer, if another one is queued, so that - * ep0 is more likely to stay busy. + * ep0 is more likely to stay busy. That's already done + * for bulk RX transfers. * * if (qh->ring.next != &musb->control), then * we have a candidate... NAKing is *NOT* an error @@ -1196,6 +1192,7 @@ void musb_host_tx(struct musb *musb, u8 epnum) /* NOTE: this code path would be a good place to PAUSE a * transfer, if there's some other (nonperiodic) tx urb * that could use this fifo. (dma complicates it...) + * That's already done for bulk RX transfers. * * if (bulk && qh->ring.next != &musb->out_bulk), then * we have a candidate... NAKing is *NOT* an error @@ -1357,6 +1354,50 @@ finish: #endif +/* Schedule next QH from musb->in_bulk and move the current qh to + * the end; avoids starvation for other endpoints. + */ +static void musb_bulk_rx_nak_timeout(struct musb *musb, struct musb_hw_ep *ep) +{ + struct dma_channel *dma; + struct urb *urb; + void __iomem *mbase = musb->mregs; + void __iomem *epio = ep->regs; + struct musb_qh *cur_qh, *next_qh; + u16 rx_csr; + + musb_ep_select(mbase, ep->epnum); + dma = is_dma_capable() ? ep->rx_channel : NULL; + + /* clear nak timeout bit */ + rx_csr = musb_readw(epio, MUSB_RXCSR); + rx_csr |= MUSB_RXCSR_H_WZC_BITS; + rx_csr &= ~MUSB_RXCSR_DATAERROR; + musb_writew(epio, MUSB_RXCSR, rx_csr); + + cur_qh = first_qh(&musb->in_bulk); + if (cur_qh) { + urb = next_urb(cur_qh); + if (dma_channel_status(dma) == MUSB_DMA_STATUS_BUSY) { + dma->status = MUSB_DMA_STATUS_CORE_ABORT; + musb->dma_controller->channel_abort(dma); + urb->actual_length += dma->actual_len; + dma->actual_len = 0L; + } + musb_save_toggle(ep, 1, urb); + + /* move cur_qh to end of queue */ + list_move_tail(&cur_qh->ring, &musb->in_bulk); + + /* get the next qh from musb->in_bulk */ + next_qh = first_qh(&musb->in_bulk); + + /* set rx_reinit and schedule the next qh */ + ep->rx_reinit = 1; + musb_start_urb(musb, 1, next_qh); + } +} + /* * Service an RX interrupt for the given IN endpoint; docs cover bulk, iso, * and high-bandwidth IN transfer cases. @@ -1420,18 +1461,26 @@ void musb_host_rx(struct musb *musb, u8 epnum) } else if (rx_csr & MUSB_RXCSR_DATAERROR) { if (USB_ENDPOINT_XFER_ISOC != qh->type) { - /* NOTE this code path would be a good place to PAUSE a - * transfer, if there's some other (nonperiodic) rx urb - * that could use this fifo. (dma complicates it...) + DBG(6, "RX end %d NAK timeout\n", epnum); + + /* NOTE: NAKing is *NOT* an error, so we want to + * continue. Except ... if there's a request for + * another QH, use that instead of starving it. * - * if (bulk && qh->ring.next != &musb->in_bulk), then - * we have a candidate... NAKing is *NOT* an error + * Devices like Ethernet and serial adapters keep + * reads posted at all times, which will starve + * other devices without this logic. */ - DBG(6, "RX end %d NAK timeout\n", epnum); + if (usb_pipebulk(urb->pipe) + && qh->mux == 1 + && !list_is_singular(&musb->in_bulk)) { + musb_bulk_rx_nak_timeout(musb, hw_ep); + return; + } musb_ep_select(mbase, epnum); - musb_writew(epio, MUSB_RXCSR, - MUSB_RXCSR_H_WZC_BITS - | MUSB_RXCSR_H_REQPKT); + rx_csr |= MUSB_RXCSR_H_WZC_BITS; + rx_csr &= ~MUSB_RXCSR_DATAERROR; + musb_writew(epio, MUSB_RXCSR, rx_csr); goto finish; } else { @@ -1751,6 +1800,17 @@ static int musb_schedule( head = &musb->in_bulk; else head = &musb->out_bulk; + + /* Enable bulk RX NAK timeout scheme when bulk requests are + * multiplexed. This scheme doen't work in high speed to full + * speed scenario as NAK interrupts are not coming from a + * full speed device connected to a high speed device. + * NAK timeout interval is 8 (128 uframe or 16ms) for HS and + * 4 (8 frame or 8ms) for FS device. + */ + if (is_in && qh->dev) + qh->intv_reg = + (USB_SPEED_HIGH == qh->dev->speed) ? 8 : 4; goto success; } else if (best_end < 0) { return -ENOSPC; @@ -1882,13 +1942,11 @@ static int musb_urb_enqueue( * * The downside of disabling this is that transfer scheduling * gets VERY unfair for nonperiodic transfers; a misbehaving - * peripheral could make that hurt. Or for reads, one that's - * perfectly normal: network and other drivers keep reads - * posted at all times, having one pending for a week should - * be perfectly safe. + * peripheral could make that hurt. That's perfectly normal + * for reads from network or serial adapters ... so we have + * partial NAKlimit support for bulk RX. * - * The upside of disabling it is avoidng transfer scheduling - * code to put this aside for while. + * The upside of disabling it is simpler transfer scheduling. */ interval = 0; } -- cgit v1.2.3 From 322337168f22e8245aae7f38e84c5711cd4c1265 Mon Sep 17 00:00:00 2001 From: Giuseppe GORGOGLIONE Date: Tue, 24 Feb 2009 15:27:34 -0800 Subject: USB: musb: fix init oops crash with static FIFO config Correct musb_read_fifosize() and musb_configure_ep0() functions for the #ifndef BLACKFIN branch when the silicon uses static FIFO configuration. (Most current silicon configures this controller to use dynamic FIFO configuration; some parts from ST don't, like the STM STA2062.) Signed-off-by: Giuseppe GORGOGLIONE Signed-off-by: Felipe Balbi Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index adf1806007f..efb39b5e55b 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -478,10 +478,11 @@ static inline void musb_configure_ep0(struct musb *musb) static inline int musb_read_fifosize(struct musb *musb, struct musb_hw_ep *hw_ep, u8 epnum) { + void *mbase = musb->mregs; u8 reg = 0; /* read from core using indexed model */ - reg = musb_readb(hw_ep->regs, 0x10 + MUSB_FIFOSIZE); + reg = musb_readb(mbase, MUSB_EP_OFFSET(epnum, MUSB_FIFOSIZE)); /* 0's returned when no more endpoints */ if (!reg) return -ENODEV; @@ -508,6 +509,7 @@ static inline void musb_configure_ep0(struct musb *musb) { musb->endpoints[0].max_packet_sz_tx = MUSB_EP0_FIFOSIZE; musb->endpoints[0].max_packet_sz_rx = MUSB_EP0_FIFOSIZE; + musb->endpoints[0].is_shared_fifo = true; } #endif /* CONFIG_BLACKFIN */ -- cgit v1.2.3 From 743821717c611913a5a3f95010b141f0b4cb5463 Mon Sep 17 00:00:00 2001 From: Ajay Kumar Gupta Date: Tue, 24 Feb 2009 15:29:04 -0800 Subject: USB: musb: only turn off vbus in OTG hosts Except on DaVinci, VBUS is now switched off as part of idling the USB link (after a_wait_bcon) whenever a device is disconnected from host. This is correct for OTG hosts, where either SRP or an ID interrupt could turn VBUS on again. However, for non-OTG hosts there's no way to turn VBUS on again, so the host becomes unusable. And the procfs entry which once allowed a manual workaround for this is now gone. This patch adds an is_otg_enabled() check before scheduling the switch-off timer in disconnect path, supporting a "classic host" mode where SRP is unavailable. [ dbrownell@users.sourceforge.net: tweak patch description ] Signed-off-by: Ajay Kumar Gupta Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index af77e465900..338cd1611ab 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -769,7 +769,7 @@ static irqreturn_t musb_stage2_irq(struct musb *musb, u8 int_usb, case OTG_STATE_A_SUSPEND: usb_hcd_resume_root_hub(musb_to_hcd(musb)); musb_root_disconnect(musb); - if (musb->a_wait_bcon != 0) + if (musb->a_wait_bcon != 0 && is_otg_enabled(musb)) musb_platform_try_idle(musb, jiffies + msecs_to_jiffies(musb->a_wait_bcon)); break; -- cgit v1.2.3 From a227fd7db74fa05d866790a4b29ba049bb5035cc Mon Sep 17 00:00:00 2001 From: David Brownell Date: Tue, 24 Feb 2009 15:31:54 -0800 Subject: USB: musb: partial DaVinci dm355 support Partial support for DaVinci DM355, on the EVM board; peripheral mode should work, once mainline merges DM355 support. Missing: (a) renumbering the GPIO for DRVVBUS on the DM6446 EVM, when DAVINCI_N_GPIO increases; (b) disabling DM355_DEEPSLEEP.DRVVBUS_OVERRIDE so VBUS is driven according to the ID signal, if cpu_is_..._dm355() The new PHY control bits are ignored on DM6446. Signed-off-by: David Brownell Cc: Kevin Hilman Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 6 ++--- drivers/usb/musb/davinci.c | 63 ++++++++++++++++++++++++++++++++-------------- drivers/usb/musb/davinci.h | 23 +++++++++++------ 3 files changed, 62 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 9985db08e7d..b66e8544d8b 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -20,8 +20,8 @@ config USB_MUSB_HDRC it's being used with, including the USB peripheral role, or the USB host role, or both. - Texas Instruments parts using this IP include DaVinci 644x, - OMAP 243x, OMAP 343x, and TUSB 6010. + Texas Instruments familiies using this IP include DaVinci + (35x, 644x ...), OMAP 243x, OMAP 3, and TUSB 6010. Analog Devices parts using this IP include Blackfin BF54x, BF525 and BF527. @@ -40,7 +40,7 @@ config USB_MUSB_SOC default y if (BF54x && !BF544) default y if (BF52x && !BF522 && !BF523) -comment "DaVinci 644x USB support" +comment "DaVinci 35x and 644x USB support" depends on USB_MUSB_HDRC && ARCH_DAVINCI comment "OMAP 243x high speed USB support" diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c index 2dc7606f319..10d11ab113a 100644 --- a/drivers/usb/musb/davinci.c +++ b/drivers/usb/musb/davinci.c @@ -48,6 +48,9 @@ #include "cppi_dma.h" +#define USB_PHY_CTRL IO_ADDRESS(USBPHY_CTL_PADDR) +#define DM355_DEEPSLEEP IO_ADDRESS(DM355_DEEPSLEEP_PADDR) + /* REVISIT (PM) we should be able to keep the PHY in low power mode most * of the time (24 MHZ oscillator and PLL off, etc) by setting POWER.D0 * and, when in host mode, autosuspending idle root ports... PHYPLLON @@ -56,20 +59,26 @@ static inline void phy_on(void) { - /* start the on-chip PHY and its PLL */ - __raw_writel(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON, - (void __force __iomem *) IO_ADDRESS(USBPHY_CTL_PADDR)); - while ((__raw_readl((void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)) - & USBPHY_PHYCLKGD) == 0) + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + /* power everything up; start the on-chip PHY and its PLL */ + phy_ctrl &= ~(USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN); + phy_ctrl |= USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON; + __raw_writel(phy_ctrl, USB_PHY_CTRL); + + /* wait for PLL to lock before proceeding */ + while ((__raw_readl(USB_PHY_CTRL) & USBPHY_PHYCLKGD) == 0) cpu_relax(); } static inline void phy_off(void) { - /* powerdown the on-chip PHY and its oscillator */ - __raw_writel(USBPHY_OSCPDWN | USBPHY_PHYPDWN, (void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)); + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + /* powerdown the on-chip PHY, its PLL, and the OTG block */ + phy_ctrl &= ~(USBPHY_SESNDEN | USBPHY_VBDTCTEN | USBPHY_PHYPLLON); + phy_ctrl |= USBPHY_OSCPDWN | USBPHY_OTGPDWN | USBPHY_PHYPDWN; + __raw_writel(phy_ctrl, USB_PHY_CTRL); } static int dma_off = 1; @@ -126,10 +135,6 @@ void musb_platform_disable(struct musb *musb) } -/* REVISIT it's not clear whether DaVinci can support full OTG. */ - -static int vbus_state = -1; - #ifdef CONFIG_USB_MUSB_HDRC_HCD #define portstate(stmt) stmt #else @@ -137,10 +142,19 @@ static int vbus_state = -1; #endif -/* VBUS SWITCHING IS BOARD-SPECIFIC */ +/* + * VBUS SWITCHING IS BOARD-SPECIFIC ... at least for the DM6446 EVM, + * which doesn't wire DRVVBUS to the FET that switches it. Unclear + * if that's a problem with the DM6446 chip or just with that board. + * + * In either case, the DM355 EVM automates DRVVBUS the normal way, + * when J10 is out, and TI documents it as handling OTG. + */ #ifdef CONFIG_MACH_DAVINCI_EVM +static int vbus_state = -1; + /* I2C operations are always synchronous, and require a task context. * With unloaded systems, using the shared workqueue seems to suffice * to satisfy the 100msec A_WAIT_VRISE timeout... @@ -150,12 +164,12 @@ static void evm_deferred_drvvbus(struct work_struct *ignored) gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); vbus_state = !vbus_state; } -static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); #endif /* EVM */ static void davinci_source_power(struct musb *musb, int is_on, int immediate) { +#ifdef CONFIG_MACH_DAVINCI_EVM if (is_on) is_on = 1; @@ -163,16 +177,17 @@ static void davinci_source_power(struct musb *musb, int is_on, int immediate) return; vbus_state = !is_on; /* 0/1 vs "-1 == unknown/init" */ -#ifdef CONFIG_MACH_DAVINCI_EVM if (machine_is_davinci_evm()) { + static DECLARE_WORK(evm_vbus_work, evm_deferred_drvvbus); + if (immediate) gpio_set_value_cansleep(GPIO_nVBUS_DRV, vbus_state); else schedule_work(&evm_vbus_work); } -#endif if (immediate) vbus_state = is_on; +#endif } static void davinci_set_vbus(struct musb *musb, int is_on) @@ -391,6 +406,17 @@ int __init musb_platform_init(struct musb *musb) musb->board_set_vbus = davinci_set_vbus; davinci_source_power(musb, 0, 1); + /* dm355 EVM swaps D+/D- for signal integrity, and + * is clocked from the main 24 MHz crystal. + */ + if (machine_is_davinci_dm355_evm()) { + u32 phy_ctrl = __raw_readl(USB_PHY_CTRL); + + phy_ctrl &= ~(3 << 9); + phy_ctrl |= USBPHY_DATAPOL; + __raw_writel(phy_ctrl, USB_PHY_CTRL); + } + /* reset the controller */ musb_writel(tibase, DAVINCI_USB_CTRL_REG, 0x1); @@ -401,8 +427,7 @@ int __init musb_platform_init(struct musb *musb) /* NOTE: irqs are in mixed mode, not bypass to pure-musb */ pr_debug("DaVinci OTG revision %08x phy %03x control %02x\n", - revision, __raw_readl((void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)), + revision, __raw_readl(USB_PHY_CTRL), musb_readb(tibase, DAVINCI_USB_CTRL_REG)); musb->isr = davinci_interrupt; diff --git a/drivers/usb/musb/davinci.h b/drivers/usb/musb/davinci.h index 7fb6238e270..046c84433ca 100644 --- a/drivers/usb/musb/davinci.h +++ b/drivers/usb/musb/davinci.h @@ -15,14 +15,21 @@ */ /* Integrated highspeed/otg PHY */ -#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) -#define USBPHY_PHYCLKGD (1 << 8) -#define USBPHY_SESNDEN (1 << 7) /* v(sess_end) comparator */ -#define USBPHY_VBDTCTEN (1 << 6) /* v(bus) comparator */ -#define USBPHY_PHYPLLON (1 << 4) /* override pll suspend */ -#define USBPHY_CLKO1SEL (1 << 3) -#define USBPHY_OSCPDWN (1 << 2) -#define USBPHY_PHYPDWN (1 << 0) +#define USBPHY_CTL_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x34) +#define USBPHY_DATAPOL BIT(11) /* (dm355) switch D+/D- */ +#define USBPHY_PHYCLKGD BIT(8) +#define USBPHY_SESNDEN BIT(7) /* v(sess_end) comparator */ +#define USBPHY_VBDTCTEN BIT(6) /* v(bus) comparator */ +#define USBPHY_VBUSSENS BIT(5) /* (dm355,ro) is vbus > 0.5V */ +#define USBPHY_PHYPLLON BIT(4) /* override pll suspend */ +#define USBPHY_CLKO1SEL BIT(3) +#define USBPHY_OSCPDWN BIT(2) +#define USBPHY_OTGPDWN BIT(1) +#define USBPHY_PHYPDWN BIT(0) + +#define DM355_DEEPSLEEP_PADDR (DAVINCI_SYSTEM_MODULE_BASE + 0x48) +#define DRVVBUS_FORCE BIT(2) +#define DRVVBUS_OVERRIDE BIT(1) /* For now include usb OTG module registers here */ #define DAVINCI_USB_VERSION_REG 0x00 -- cgit v1.2.3 From 1ded7ea47b8829a06068c3bb5e3ebe471076617a Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 20 Feb 2009 21:23:09 +0800 Subject: USB: ch341 serial: fix port number changed after resume This patch fixes the following bug: .plug ch341 usb serial port into a hub port; .ch341 driver bound to the device and /dev/ttyUSB0 comes .open /dev/ttyUSB0 by minicom and we can use the serial successfully .suspend the ch341 usb serial device(such as: echo suspend > power/level) .resume the ch341 usb serial device (such as: echo on > power/level) .new port /dev/ttyUSB1 comes ,and the original /dev/ttyUSB0 still exists, but is no longer usable by minicom The patch adds suspend and resume callback to ch341 usb driver to prevent it from unbinding during suspend. The /dev/ttyUSB0 is not released until being closed, so /dev/ttyUSB1 comes after resume, and the original /dev/ttyUSB0 is no longer usable by minicom. It is really a mess for a minicom user. This patch also adds the reset_resume callback to make it usable after resuming from STR or hibernation, for generally STR or hibernation will make the vbus of root-hub lost. Finally enable the driver's supports_autosuspend, for the device is in working order with it. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ch341.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index d5ea679e169..ab4cc277aa6 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c @@ -529,12 +529,34 @@ static int ch341_tiocmget(struct tty_struct *tty, struct file *file) return result; } + +static int ch341_reset_resume(struct usb_interface *intf) +{ + struct usb_device *dev = interface_to_usbdev(intf); + struct usb_serial *serial = NULL; + struct ch341_private *priv; + + serial = usb_get_intfdata(intf); + priv = usb_get_serial_port_data(serial->port[0]); + + /*reconfigure ch341 serial port after bus-reset*/ + ch341_configure(dev, priv); + + usb_serial_resume(intf); + + return 0; +} + static struct usb_driver ch341_driver = { .name = "ch341", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, + .suspend = usb_serial_suspend, + .resume = usb_serial_resume, + .reset_resume = ch341_reset_resume, .id_table = id_table, .no_dynamic_id = 1, + .supports_autosuspend = 1, }; static struct usb_serial_driver ch341_device = { -- cgit v1.2.3 From 471c604daf73ff549d374ee54f9e6bfd5a54d4e8 Mon Sep 17 00:00:00 2001 From: Pete Zaitcev Date: Thu, 19 Feb 2009 22:54:45 -0700 Subject: USB: usbmon: Add binary API v1 This patch adds an extension to the binary API so it reaches parity with existing text API (so-called "1u"). The extension delivers additional data, such as ISO descriptors and the interrupt interval. Signed-Off-By: Pete Zaitcev Signed-off-by: Greg Kroah-Hartman --- drivers/usb/mon/mon_bin.c | 142 +++++++++++++++++++++++++++++++++++++--------- 1 file changed, 116 insertions(+), 26 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c index 4cf27c72423..f8d9045d668 100644 --- a/drivers/usb/mon/mon_bin.c +++ b/drivers/usb/mon/mon_bin.c @@ -37,10 +37,13 @@ #define MON_IOCX_GET _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get) #define MON_IOCX_MFETCH _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch) #define MON_IOCH_MFLUSH _IO(MON_IOC_MAGIC, 8) +/* #9 was MON_IOCT_SETAPI */ +#define MON_IOCX_GETX _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get) #ifdef CONFIG_COMPAT #define MON_IOCX_GET32 _IOW(MON_IOC_MAGIC, 6, struct mon_bin_get32) #define MON_IOCX_MFETCH32 _IOWR(MON_IOC_MAGIC, 7, struct mon_bin_mfetch32) +#define MON_IOCX_GETX32 _IOW(MON_IOC_MAGIC, 10, struct mon_bin_get32) #endif /* @@ -92,7 +95,29 @@ struct mon_bin_hdr { int status; unsigned int len_urb; /* Length of data (submitted or actual) */ unsigned int len_cap; /* Delivered length */ - unsigned char setup[SETUP_LEN]; /* Only for Control S-type */ + union { + unsigned char setup[SETUP_LEN]; /* Only for Control S-type */ + struct iso_rec { + int error_count; + int numdesc; + } iso; + } s; + int interval; + int start_frame; + unsigned int xfer_flags; + unsigned int ndesc; /* Actual number of ISO descriptors */ +}; + +/* + * ISO vector, packed into the head of data stream. + * This has to take 16 bytes to make sure that the end of buffer + * wrap is not happening in the middle of a descriptor. + */ +struct mon_bin_isodesc { + int iso_status; + unsigned int iso_off; + unsigned int iso_len; + u32 _pad; }; /* per file statistic */ @@ -102,7 +127,7 @@ struct mon_bin_stats { }; struct mon_bin_get { - struct mon_bin_hdr __user *hdr; /* Only 48 bytes, not 64. */ + struct mon_bin_hdr __user *hdr; /* Can be 48 bytes or 64. */ void __user *data; size_t alloc; /* Length of data (can be zero) */ }; @@ -131,6 +156,11 @@ struct mon_bin_mfetch32 { #define PKT_ALIGN 64 #define PKT_SIZE 64 +#define PKT_SZ_API0 48 /* API 0 (2.6.20) size */ +#define PKT_SZ_API1 64 /* API 1 size: extra fields */ + +#define ISODESC_MAX 128 /* Same number as usbfs allows, 2048 bytes. */ + /* max number of USB bus supported */ #define MON_BIN_MAX_MINOR 128 @@ -360,12 +390,8 @@ static inline char mon_bin_get_setup(unsigned char *setupb, const struct urb *urb, char ev_type) { - if (!usb_endpoint_xfer_control(&urb->ep->desc) || ev_type != 'S') - return '-'; - if (urb->setup_packet == NULL) return 'Z'; - memcpy(setupb, urb->setup_packet, SETUP_LEN); return 0; } @@ -387,6 +413,26 @@ static char mon_bin_get_data(const struct mon_reader_bin *rp, return 0; } +static void mon_bin_get_isodesc(const struct mon_reader_bin *rp, + unsigned int offset, struct urb *urb, char ev_type, unsigned int ndesc) +{ + struct mon_bin_isodesc *dp; + struct usb_iso_packet_descriptor *fp; + + fp = urb->iso_frame_desc; + while (ndesc-- != 0) { + dp = (struct mon_bin_isodesc *) + (rp->b_vec[offset / CHUNK_SIZE].ptr + offset % CHUNK_SIZE); + dp->iso_status = fp->status; + dp->iso_off = fp->offset; + dp->iso_len = (ev_type == 'S') ? fp->length : fp->actual_length; + dp->_pad = 0; + if ((offset += sizeof(struct mon_bin_isodesc)) >= rp->b_size) + offset = 0; + fp++; + } +} + static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, char ev_type, int status) { @@ -396,6 +442,7 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, unsigned int urb_length; unsigned int offset; unsigned int length; + unsigned int ndesc, lendesc; unsigned char dir; struct mon_bin_hdr *ep; char data_tag = 0; @@ -407,6 +454,19 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, /* * Find the maximum allowable length, then allocate space. */ + if (usb_endpoint_xfer_isoc(epd)) { + if (urb->number_of_packets < 0) { + ndesc = 0; + } else if (urb->number_of_packets >= ISODESC_MAX) { + ndesc = ISODESC_MAX; + } else { + ndesc = urb->number_of_packets; + } + } else { + ndesc = 0; + } + lendesc = ndesc*sizeof(struct mon_bin_isodesc); + urb_length = (ev_type == 'S') ? urb->transfer_buffer_length : urb->actual_length; length = urb_length; @@ -429,10 +489,12 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, dir = 0; } - if (rp->mmap_active) - offset = mon_buff_area_alloc_contiguous(rp, length + PKT_SIZE); - else - offset = mon_buff_area_alloc(rp, length + PKT_SIZE); + if (rp->mmap_active) { + offset = mon_buff_area_alloc_contiguous(rp, + length + PKT_SIZE + lendesc); + } else { + offset = mon_buff_area_alloc(rp, length + PKT_SIZE + lendesc); + } if (offset == ~0) { rp->cnt_lost++; spin_unlock_irqrestore(&rp->b_lock, flags); @@ -456,9 +518,31 @@ static void mon_bin_event(struct mon_reader_bin *rp, struct urb *urb, ep->ts_usec = ts.tv_usec; ep->status = status; ep->len_urb = urb_length; - ep->len_cap = length; + ep->len_cap = length + lendesc; + ep->xfer_flags = urb->transfer_flags; + + if (usb_endpoint_xfer_int(epd)) { + ep->interval = urb->interval; + } else if (usb_endpoint_xfer_isoc(epd)) { + ep->interval = urb->interval; + ep->start_frame = urb->start_frame; + ep->s.iso.error_count = urb->error_count; + ep->s.iso.numdesc = urb->number_of_packets; + } + + if (usb_endpoint_xfer_control(epd) && ev_type == 'S') { + ep->flag_setup = mon_bin_get_setup(ep->s.setup, urb, ev_type); + } else { + ep->flag_setup = '-'; + } + + if (ndesc != 0) { + ep->ndesc = ndesc; + mon_bin_get_isodesc(rp, offset, urb, ev_type, ndesc); + if ((offset += lendesc) >= rp->b_size) + offset -= rp->b_size; + } - ep->flag_setup = mon_bin_get_setup(ep->setup, urb, ev_type); if (length != 0) { ep->flag_data = mon_bin_get_data(rp, offset, urb, length); if (ep->flag_data != 0) { /* Yes, it's 0x00, not '0' */ @@ -592,7 +676,8 @@ err_alloc: * Returns zero or error. */ static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp, - struct mon_bin_hdr __user *hdr, void __user *data, unsigned int nbytes) + struct mon_bin_hdr __user *hdr, unsigned int hdrbytes, + void __user *data, unsigned int nbytes) { unsigned long flags; struct mon_bin_hdr *ep; @@ -609,7 +694,7 @@ static int mon_bin_get_event(struct file *file, struct mon_reader_bin *rp, ep = MON_OFF2HDR(rp, rp->b_out); - if (copy_to_user(hdr, ep, sizeof(struct mon_bin_hdr))) { + if (copy_to_user(hdr, ep, hdrbytes)) { mutex_unlock(&rp->fetch_lock); return -EFAULT; } @@ -657,6 +742,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) { struct mon_reader_bin *rp = file->private_data; + unsigned int hdrbytes = PKT_SZ_API0; unsigned long flags; struct mon_bin_hdr *ep; unsigned int offset; @@ -674,8 +760,8 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, ep = MON_OFF2HDR(rp, rp->b_out); - if (rp->b_read < sizeof(struct mon_bin_hdr)) { - step_len = min(nbytes, sizeof(struct mon_bin_hdr) - rp->b_read); + if (rp->b_read < hdrbytes) { + step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read)); ptr = ((char *)ep) + rp->b_read; if (step_len && copy_to_user(buf, ptr, step_len)) { mutex_unlock(&rp->fetch_lock); @@ -687,13 +773,13 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, done += step_len; } - if (rp->b_read >= sizeof(struct mon_bin_hdr)) { + if (rp->b_read >= hdrbytes) { step_len = ep->len_cap; - step_len -= rp->b_read - sizeof(struct mon_bin_hdr); + step_len -= rp->b_read - hdrbytes; if (step_len > nbytes) step_len = nbytes; offset = rp->b_out + PKT_SIZE; - offset += rp->b_read - sizeof(struct mon_bin_hdr); + offset += rp->b_read - hdrbytes; if (offset >= rp->b_size) offset -= rp->b_size; if (copy_from_buf(rp, offset, buf, step_len)) { @@ -709,7 +795,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf, /* * Check if whole packet was read, and if so, jump to the next one. */ - if (rp->b_read >= sizeof(struct mon_bin_hdr) + ep->len_cap) { + if (rp->b_read >= hdrbytes + ep->len_cap) { spin_lock_irqsave(&rp->b_lock, flags); mon_buff_area_free(rp, PKT_SIZE + ep->len_cap); spin_unlock_irqrestore(&rp->b_lock, flags); @@ -908,6 +994,7 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file, break; case MON_IOCX_GET: + case MON_IOCX_GETX: { struct mon_bin_get getb; @@ -917,8 +1004,9 @@ static int mon_bin_ioctl(struct inode *inode, struct file *file, if (getb.alloc > 0x10000000) /* Want to cast to u32 */ return -EINVAL; - ret = mon_bin_get_event(file, rp, - getb.hdr, getb.data, (unsigned int)getb.alloc); + ret = mon_bin_get_event(file, rp, getb.hdr, + (cmd == MON_IOCX_GET)? PKT_SZ_API0: PKT_SZ_API1, + getb.data, (unsigned int)getb.alloc); } break; @@ -984,16 +1072,18 @@ static long mon_bin_compat_ioctl(struct file *file, switch (cmd) { - case MON_IOCX_GET32: { + case MON_IOCX_GET32: + case MON_IOCX_GETX32: + { struct mon_bin_get32 getb; if (copy_from_user(&getb, (void __user *)arg, sizeof(struct mon_bin_get32))) return -EFAULT; - ret = mon_bin_get_event(file, rp, - compat_ptr(getb.hdr32), compat_ptr(getb.data32), - getb.alloc32); + ret = mon_bin_get_event(file, rp, compat_ptr(getb.hdr32), + (cmd == MON_IOCX_GET32)? PKT_SZ_API0: PKT_SZ_API1, + compat_ptr(getb.data32), getb.alloc32); if (ret < 0) return ret; } -- cgit v1.2.3 From 66760169492445395c530c812443f58e2cfdb3dc Mon Sep 17 00:00:00 2001 From: Jouni Hogander Date: Fri, 20 Feb 2009 14:02:31 +0200 Subject: USB: TWL: disable VUSB regulators when cable unplugged This patch disables USB regulators VUSB1V5, VUSB1V8, and VUSB3V1 when the USB cable is unplugged to reduce power consumption. Added a depencency from twl4030 usb driver to TWL_REGULATOR. Signed-off-by: Jouni Hogander Signed-off-by: Kalle Jokiniemi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/otg/Kconfig | 2 +- drivers/usb/otg/twl4030-usb.c | 73 +++++++++++++++++++++++++++++++++++++------ 2 files changed, 65 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index fc1ca03ce4d..aa884d072f0 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig @@ -43,7 +43,7 @@ config ISP1301_OMAP config TWL4030_USB tristate "TWL4030 USB Transceiver Driver" - depends on TWL4030_CORE + depends on TWL4030_CORE && REGULATOR_TWL4030 select USB_OTG_UTILS help Enable this to support the USB OTG transceiver on TWL4030 diff --git a/drivers/usb/otg/twl4030-usb.c b/drivers/usb/otg/twl4030-usb.c index 416e4410be0..d9478d0e1c8 100644 --- a/drivers/usb/otg/twl4030-usb.c +++ b/drivers/usb/otg/twl4030-usb.c @@ -34,6 +34,8 @@ #include #include #include +#include +#include /* Register defines */ @@ -246,6 +248,11 @@ struct twl4030_usb { struct otg_transceiver otg; struct device *dev; + /* TWL4030 internal USB regulator supplies */ + struct regulator *usb1v5; + struct regulator *usb1v8; + struct regulator *usb3v1; + /* for vbus reporting with irqs disabled */ spinlock_t lock; @@ -434,6 +441,18 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) pwr = twl4030_usb_read(twl, PHY_PWR_CTRL); if (on) { + regulator_enable(twl->usb3v1); + regulator_enable(twl->usb1v8); + /* + * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP + * in twl4030) resets the VUSB_DEDICATED2 register. This reset + * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to + * SLEEP. We work around this by clearing the bit after usv3v1 + * is re-activated. This ensures that VUSB3V1 is really active. + */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, + VUSB_DEDICATED2); + regulator_enable(twl->usb1v5); pwr &= ~PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); twl4030_usb_write(twl, PHY_CLK_CTRL, @@ -443,6 +462,9 @@ static void twl4030_phy_power(struct twl4030_usb *twl, int on) } else { pwr |= PHY_PWR_PHYPWD; WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); + regulator_disable(twl->usb1v5); + regulator_disable(twl->usb1v8); + regulator_disable(twl->usb3v1); } } @@ -468,7 +490,7 @@ static void twl4030_phy_resume(struct twl4030_usb *twl) twl->asleep = 0; } -static void twl4030_usb_ldo_init(struct twl4030_usb *twl) +static int twl4030_usb_ldo_init(struct twl4030_usb *twl) { /* Enable writing to power configuration registers */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0xC0, PROTECT_KEY); @@ -480,20 +502,45 @@ static void twl4030_usb_ldo_init(struct twl4030_usb *twl) /* input to VUSB3V1 LDO is from VBAT, not VBUS */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x14, VUSB_DEDICATED1); - /* turn on 3.1V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB3V1_DEV_GRP); + /* Initialize 3.1V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_DEV_GRP); + + twl->usb3v1 = regulator_get(twl->dev, "usb3v1"); + if (IS_ERR(twl->usb3v1)) + return -ENODEV; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB3V1_TYPE); - /* turn on 1.5V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V5_DEV_GRP); + /* Initialize 1.5V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_DEV_GRP); + + twl->usb1v5 = regulator_get(twl->dev, "usb1v5"); + if (IS_ERR(twl->usb1v5)) + goto fail1; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V5_TYPE); - /* turn on 1.8V regulator */ - twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0x20, VUSB1V8_DEV_GRP); + /* Initialize 1.8V regulator */ + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_DEV_GRP); + + twl->usb1v8 = regulator_get(twl->dev, "usb1v8"); + if (IS_ERR(twl->usb1v8)) + goto fail2; + twl4030_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, 0, VUSB1V8_TYPE); /* disable access to power configuration registers */ twl4030_i2c_write_u8(TWL4030_MODULE_PM_MASTER, 0, PROTECT_KEY); + + return 0; + +fail2: + regulator_put(twl->usb1v5); + twl->usb1v5 = NULL; +fail1: + regulator_put(twl->usb3v1); + twl->usb3v1 = NULL; + return -ENODEV; } static ssize_t twl4030_usb_vbus_show(struct device *dev, @@ -598,7 +645,7 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) { struct twl4030_usb_data *pdata = pdev->dev.platform_data; struct twl4030_usb *twl; - int status; + int status, err; if (!pdata) { dev_dbg(&pdev->dev, "platform_data not available\n"); @@ -622,7 +669,12 @@ static int __init twl4030_usb_probe(struct platform_device *pdev) /* init spinlock for workqueue */ spin_lock_init(&twl->lock); - twl4030_usb_ldo_init(twl); + err = twl4030_usb_ldo_init(twl); + if (err) { + dev_err(&pdev->dev, "ldo init failed\n"); + kfree(twl); + return err; + } otg_set_transceiver(&twl->otg); platform_set_drvdata(pdev, twl); @@ -688,6 +740,9 @@ static int __exit twl4030_usb_remove(struct platform_device *pdev) twl4030_usb_clear_bits(twl, POWER_CTRL, POWER_CTRL_OTG_ENAB); twl4030_phy_power(twl, 0); + regulator_put(twl->usb1v5); + regulator_put(twl->usb1v8); + regulator_put(twl->usb3v1); kfree(twl); -- cgit v1.2.3 From 7ea0a2bcfe40b1c525e63e931b7142ab22b64269 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 5 Mar 2009 11:01:11 -0500 Subject: USB: uhci: don't use pseudo negative values The code in uhci-q.c doesn't have to use pseudo-negative values. I did it that way because it was easy and because it would give the expected output during debugging. But it doesn't have to work that way. Here's another approach. Signed-off-by: Alan Stern Cc: Roel Kluin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/uhci-debug.c | 4 +++- drivers/usb/host/uhci-q.c | 11 ++++------- 2 files changed, 7 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/uhci-debug.c b/drivers/usb/host/uhci-debug.c index 20cc58b9780..e52b954dda4 100644 --- a/drivers/usb/host/uhci-debug.c +++ b/drivers/usb/host/uhci-debug.c @@ -118,7 +118,9 @@ static int uhci_show_urbp(struct urb_priv *urbp, char *buf, int len, int space) } out += sprintf(out, "%s%s", ptype, (urbp->fsbr ? " FSBR" : "")); - out += sprintf(out, " Actlen=%d", urbp->urb->actual_length); + out += sprintf(out, " Actlen=%d%s", urbp->urb->actual_length, + (urbp->qh->type == USB_ENDPOINT_XFER_CONTROL ? + "-8" : "")); if (urbp->urb->unlinked) out += sprintf(out, " Unlinked=%d", urbp->urb->unlinked); diff --git a/drivers/usb/host/uhci-q.c b/drivers/usb/host/uhci-q.c index 58f87367914..3e5807d14ff 100644 --- a/drivers/usb/host/uhci-q.c +++ b/drivers/usb/host/uhci-q.c @@ -899,8 +899,6 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, } if (qh->state != QH_STATE_ACTIVE) qh->skel = skel; - - urb->actual_length = -8; /* Account for the SETUP packet */ return 0; nomem: @@ -1494,11 +1492,10 @@ __acquires(uhci->lock) if (qh->type == USB_ENDPOINT_XFER_CONTROL) { - /* urb->actual_length < 0 means the setup transaction didn't - * complete successfully. Either it failed or the URB was - * unlinked first. Regardless, don't confuse people with a - * negative length. */ - urb->actual_length = max(urb->actual_length, 0); + /* Subtract off the length of the SETUP packet from + * urb->actual_length. + */ + urb->actual_length -= min_t(u32, 8, urb->actual_length); } /* When giving back the first URB in an Isochronous queue, -- cgit v1.2.3 From 16e2e5f634f86ccda18366967c4e592eb61bc9cc Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 3 Mar 2009 16:44:13 -0800 Subject: USB: make transfer_buffer_lengths in struct urb field u32 Roel Kluin pointed out that transfer_buffer_lengths in struct urb was declared as an 'int'. This patch changes this field to be 'u32' to prevent any potential negative conversion and comparison errors. This triggered a few compiler warning messages when these fields were being used with the min macro, so they have also been fixed up in this patch. Cc: Roel Kluin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/dummy_hcd.c | 2 +- drivers/usb/host/isp116x-hcd.c | 2 +- drivers/usb/host/r8a66597-hcd.c | 2 +- drivers/usb/host/sl811-hcd.c | 4 ++-- drivers/usb/misc/ftdi-elan.c | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 3b42888b72f..a56b24d305f 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c @@ -1437,7 +1437,7 @@ restart: } if (urb->transfer_buffer_length > 1) buf [1] = 0; - urb->actual_length = min (2, + urb->actual_length = min_t(u32, 2, urb->transfer_buffer_length); value = 0; status = 0; diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c index 4dda31b2689..a2b305477af 100644 --- a/drivers/usb/host/isp116x-hcd.c +++ b/drivers/usb/host/isp116x-hcd.c @@ -772,7 +772,7 @@ static int isp116x_urb_enqueue(struct usb_hcd *hcd, break; case PIPE_INTERRUPT: urb->interval = ep->period; - ep->length = min((int)ep->maxpacket, + ep->length = min_t(u32, ep->maxpacket, urb->transfer_buffer_length); /* urb submitted for already existing endpoint */ diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 5e942d94aeb..713f4cf0b0d 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1394,7 +1394,7 @@ static void packet_write(struct r8a66597 *r8a66597, u16 pipenum) (int)urb->iso_frame_desc[td->iso_cnt].length); } else { buf = (u16 *)(urb->transfer_buffer + urb->actual_length); - size = min((int)bufsize, + size = min_t(u32, bufsize, urb->transfer_buffer_length - urb->actual_length); } diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c index e106e9d48d4..a949259f18b 100644 --- a/drivers/usb/host/sl811-hcd.c +++ b/drivers/usb/host/sl811-hcd.c @@ -230,7 +230,7 @@ static void in_packet( writeb(usb_pipedevice(urb->pipe), data_reg); sl811_write(sl811, bank + SL11H_HOSTCTLREG, control); - ep->length = min((int)len, + ep->length = min_t(u32, len, urb->transfer_buffer_length - urb->actual_length); PACKET("IN%s/%d qh%p len%d\n", ep->nak_count ? "/retry" : "", !!usb_gettoggle(urb->dev, ep->epnum, 0), ep, len); @@ -255,7 +255,7 @@ static void out_packet( buf = urb->transfer_buffer + urb->actual_length; prefetch(buf); - len = min((int)ep->maxpacket, + len = min_t(u32, ep->maxpacket, urb->transfer_buffer_length - urb->actual_length); if (!(control & SL11H_HCTLMASK_ISOCH) diff --git a/drivers/usb/misc/ftdi-elan.c b/drivers/usb/misc/ftdi-elan.c index 79a7668ef26..9d0675ed0d4 100644 --- a/drivers/usb/misc/ftdi-elan.c +++ b/drivers/usb/misc/ftdi-elan.c @@ -1568,7 +1568,7 @@ static int ftdi_elan_edset_input(struct usb_ftdi *ftdi, u8 ed_number, struct u132_target *target = &ftdi->target[ed]; struct u132_command *command = &ftdi->command[ COMMAND_MASK & ftdi->command_next]; - int remaining_length = urb->transfer_buffer_length - + u32 remaining_length = urb->transfer_buffer_length - urb->actual_length; command->header = 0x82 | (ed << 5); if (remaining_length == 0) { @@ -1702,7 +1702,7 @@ static int ftdi_elan_edset_output(struct usb_ftdi *ftdi, u8 ed_number, | (address << 0); command->width = usb_maxpacket(urb->dev, urb->pipe, usb_pipeout(urb->pipe)); - command->follows = min(1024, + command->follows = min_t(u32, 1024, urb->transfer_buffer_length - urb->actual_length); command->value = 0; @@ -1766,7 +1766,7 @@ static int ftdi_elan_edset_single(struct usb_ftdi *ftdi, u8 ed_number, mutex_lock(&ftdi->u132_lock); command_size = ftdi->command_next - ftdi->command_head; if (command_size < COMMAND_SIZE) { - int remaining_length = urb->transfer_buffer_length - + u32 remaining_length = urb->transfer_buffer_length - urb->actual_length; struct u132_target *target = &ftdi->target[ed]; struct u132_command *command = &ftdi->command[ -- cgit v1.2.3 From 8c209e6782ca0e3046803fc04a5ac01c8c10437a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 6 Mar 2009 21:31:03 -0800 Subject: USB: make actual_length in struct urb field u32 actual_length should also be a u32 and not a signed value. This patch changes this field to be 'u32' to prevent any potential negative conversion and comparison errors. This triggered a few compiler warning messages when these fields were being used with the min macro, so they have also been fixed up in this patch. Cc: Roel Kluin Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ftdi_sio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index adeb23fb800..dcc87aaa862 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c @@ -1947,7 +1947,7 @@ static void ftdi_process_read(struct work_struct *work) priv->prev_status = new_status; } - length = min(PKTSZ, urb->actual_length-packet_offset)-2; + length = min_t(u32, PKTSZ, urb->actual_length-packet_offset)-2; if (length < 0) { dev_err(&port->dev, "%s - bad packet length: %d\n", __func__, length+2); -- cgit v1.2.3 From 77aa2b5878f48d6ab6e0c412cc9214c845483475 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 4 Mar 2009 16:23:31 -0800 Subject: USB: remove phidget drivers from kernel tree. These devices are better controlled with the LGPL userspace library found at: http://www.phidgets.com/downloads.php?os_id=3 and full documentation at: http://www.phidgets.com/documentation/web/cdoc/index.html Cc: Chester Fitchett Acked-by: Sean Young Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/Kconfig | 39 -- drivers/usb/misc/Makefile | 4 - drivers/usb/misc/phidget.c | 43 -- drivers/usb/misc/phidget.h | 12 - drivers/usb/misc/phidgetkit.c | 740 --------------------------------- drivers/usb/misc/phidgetmotorcontrol.c | 465 --------------------- drivers/usb/misc/phidgetservo.c | 375 ----------------- 7 files changed, 1678 deletions(-) delete mode 100644 drivers/usb/misc/phidget.c delete mode 100644 drivers/usb/misc/phidget.h delete mode 100644 drivers/usb/misc/phidgetkit.c delete mode 100644 drivers/usb/misc/phidgetmotorcontrol.c delete mode 100644 drivers/usb/misc/phidgetservo.c (limited to 'drivers') diff --git a/drivers/usb/misc/Kconfig b/drivers/usb/misc/Kconfig index e463db5d818..a68d91a11be 100644 --- a/drivers/usb/misc/Kconfig +++ b/drivers/usb/misc/Kconfig @@ -135,45 +135,6 @@ config USB_CYTHERM To compile this driver as a module, choose M here: the module will be called cytherm. -config USB_PHIDGET - tristate "USB Phidgets drivers" - depends on USB - help - Say Y here to enable the various drivers for devices from - Phidgets inc. - -config USB_PHIDGETKIT - tristate "USB PhidgetInterfaceKit support" - depends on USB_PHIDGET - help - Say Y here if you want to connect a PhidgetInterfaceKit USB device - from Phidgets Inc. - - To compile this driver as a module, choose M here: the - module will be called phidgetkit. - -config USB_PHIDGETMOTORCONTROL - tristate "USB PhidgetMotorControl support" - depends on USB_PHIDGET - help - Say Y here if you want to connect a PhidgetMotorControl USB device - from Phidgets Inc. - - To compile this driver as a module, choose M here: the - module will be called phidgetmotorcontrol. - -config USB_PHIDGETSERVO - tristate "USB PhidgetServo support" - depends on USB_PHIDGET - help - Say Y here if you want to connect an 1 or 4 Motor PhidgetServo - servo controller version 2.0 or 3.0. - - Phidgets Inc. has a web page at . - - To compile this driver as a module, choose M here: the - module will be called phidgetservo. - config USB_IDMOUSE tristate "Siemens ID USB Mouse Fingerprint sensor support" depends on USB diff --git a/drivers/usb/misc/Makefile b/drivers/usb/misc/Makefile index 1334f7bdd7b..0826aab8303 100644 --- a/drivers/usb/misc/Makefile +++ b/drivers/usb/misc/Makefile @@ -18,10 +18,6 @@ obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LD) += ldusb.o obj-$(CONFIG_USB_LED) += usbled.o obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o -obj-$(CONFIG_USB_PHIDGET) += phidget.o -obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o -obj-$(CONFIG_USB_PHIDGETMOTORCONTROL) += phidgetmotorcontrol.o -obj-$(CONFIG_USB_PHIDGETSERVO) += phidgetservo.o obj-$(CONFIG_USB_RIO500) += rio500.o obj-$(CONFIG_USB_TEST) += usbtest.o obj-$(CONFIG_USB_TRANCEVIBRATOR) += trancevibrator.o diff --git a/drivers/usb/misc/phidget.c b/drivers/usb/misc/phidget.c deleted file mode 100644 index 735ed33f4f7..00000000000 --- a/drivers/usb/misc/phidget.c +++ /dev/null @@ -1,43 +0,0 @@ -/* - * USB Phidgets class - * - * Copyright (C) 2006 Sean Young - * - * 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 - -struct class *phidget_class; - -static int __init init_phidget(void) -{ - phidget_class = class_create(THIS_MODULE, "phidget"); - - if (IS_ERR(phidget_class)) - return PTR_ERR(phidget_class); - - return 0; -} - -static void __exit cleanup_phidget(void) -{ - class_destroy(phidget_class); -} - -EXPORT_SYMBOL_GPL(phidget_class); - -module_init(init_phidget); -module_exit(cleanup_phidget); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Sean Young "); -MODULE_DESCRIPTION("Container module for phidget class"); - diff --git a/drivers/usb/misc/phidget.h b/drivers/usb/misc/phidget.h deleted file mode 100644 index c4011907d43..00000000000 --- a/drivers/usb/misc/phidget.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * USB Phidgets class - * - * Copyright (C) 2006 Sean Young - * - * 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. - */ - -extern struct class *phidget_class; diff --git a/drivers/usb/misc/phidgetkit.c b/drivers/usb/misc/phidgetkit.c deleted file mode 100644 index cc8e0a926f9..00000000000 --- a/drivers/usb/misc/phidgetkit.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * USB PhidgetInterfaceKit driver 1.0 - * - * Copyright (C) 2004, 2006 Sean Young - * Copyright (C) 2005 Daniel Saakes - * Copyright (C) 2004 Greg Kroah-Hartman - * - * 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. - * - * This is a driver for the USB PhidgetInterfaceKit. - */ - -#include -#include -#include -#include -#include -#include - -#include "phidget.h" - -#define DRIVER_AUTHOR "Sean Young " -#define DRIVER_DESC "USB PhidgetInterfaceKit Driver" - -#define USB_VENDOR_ID_GLAB 0x06c2 -#define USB_DEVICE_ID_INTERFACEKIT004 0x0040 -#define USB_DEVICE_ID_INTERFACEKIT01616 0x0044 -#define USB_DEVICE_ID_INTERFACEKIT888 0x0045 -#define USB_DEVICE_ID_INTERFACEKIT047 0x0051 -#define USB_DEVICE_ID_INTERFACEKIT088 0x0053 - -#define USB_VENDOR_ID_WISEGROUP 0x0925 -#define USB_DEVICE_ID_INTERFACEKIT884 0x8201 - -#define MAX_INTERFACES 16 - -#define URB_INT_SIZE 8 - -struct driver_interfacekit { - int sensors; - int inputs; - int outputs; - int has_lcd; - int amnesiac; -}; - -#define ifkit(_sensors, _inputs, _outputs, _lcd, _amnesiac) \ -{ \ - .sensors = _sensors, \ - .inputs = _inputs, \ - .outputs = _outputs, \ - .has_lcd = _lcd, \ - .amnesiac = _amnesiac \ -}; - -static const struct driver_interfacekit ph_004 = ifkit(0, 0, 4, 0, 0); -static const struct driver_interfacekit ph_888n = ifkit(8, 8, 8, 0, 1); -static const struct driver_interfacekit ph_888o = ifkit(8, 8, 8, 0, 0); -static const struct driver_interfacekit ph_047 = ifkit(0, 4, 7, 1, 0); -static const struct driver_interfacekit ph_884 = ifkit(8, 8, 4, 0, 0); -static const struct driver_interfacekit ph_088 = ifkit(0, 8, 8, 1, 0); -static const struct driver_interfacekit ph_01616 = ifkit(0, 16, 16, 0, 0); - -static unsigned long device_no; - -struct interfacekit { - struct usb_device *udev; - struct usb_interface *intf; - struct driver_interfacekit *ifkit; - struct device *dev; - unsigned long outputs; - int dev_no; - u8 inputs[MAX_INTERFACES]; - u16 sensors[MAX_INTERFACES]; - u8 lcd_files_on; - - struct urb *irq; - unsigned char *data; - dma_addr_t data_dma; - - struct delayed_work do_notify; - struct delayed_work do_resubmit; - unsigned long input_events; - unsigned long sensor_events; -}; - -static struct usb_device_id id_table[] = { - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT004), - .driver_info = (kernel_ulong_t)&ph_004}, - {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0, 0x814), - .driver_info = (kernel_ulong_t)&ph_888o}, - {USB_DEVICE_VER(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT888, 0x0815, 0xffff), - .driver_info = (kernel_ulong_t)&ph_888n}, - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT047), - .driver_info = (kernel_ulong_t)&ph_047}, - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT088), - .driver_info = (kernel_ulong_t)&ph_088}, - {USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_INTERFACEKIT01616), - .driver_info = (kernel_ulong_t)&ph_01616}, - {USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_INTERFACEKIT884), - .driver_info = (kernel_ulong_t)&ph_884}, - {} -}; -MODULE_DEVICE_TABLE(usb, id_table); - -static int set_outputs(struct interfacekit *kit) -{ - u8 *buffer; - int retval; - - buffer = kzalloc(4, GFP_KERNEL); - if (!buffer) { - dev_err(&kit->udev->dev, "%s - out of memory\n", __func__); - return -ENOMEM; - } - buffer[0] = (u8)kit->outputs; - buffer[1] = (u8)(kit->outputs >> 8); - - dev_dbg(&kit->udev->dev, "sending data: 0x%04x\n", (u16)kit->outputs); - - retval = usb_control_msg(kit->udev, - usb_sndctrlpipe(kit->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 4, 2000); - - if (retval != 4) - dev_err(&kit->udev->dev, "usb_control_msg returned %d\n", - retval); - kfree(buffer); - - if (kit->ifkit->amnesiac) - schedule_delayed_work(&kit->do_resubmit, HZ / 2); - - return retval < 0 ? retval : 0; -} - -static int change_string(struct interfacekit *kit, const char *display, unsigned char row) -{ - unsigned char *buffer; - unsigned char *form_buffer; - int retval = -ENOMEM; - int i,j, len, buf_ptr; - - buffer = kmalloc(8, GFP_KERNEL); - form_buffer = kmalloc(30, GFP_KERNEL); - if ((!buffer) || (!form_buffer)) { - dev_err(&kit->udev->dev, "%s - out of memory\n", __func__); - goto exit; - } - - len = strlen(display); - if (len > 20) - len = 20; - - dev_dbg(&kit->udev->dev, "Setting LCD line %d to %s\n", row, display); - - form_buffer[0] = row * 0x40 + 0x80; - form_buffer[1] = 0x02; - buf_ptr = 2; - for (i = 0; i 7) - len = 7; - else - len = (buf_ptr - i); - for (j = 0; j < len; j++) - buffer[j] = form_buffer[i + j]; - buffer[7] = len; - - retval = usb_control_msg(kit->udev, - usb_sndctrlpipe(kit->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000); - if (retval < 0) - goto exit; - } - - retval = 0; -exit: - kfree(buffer); - kfree(form_buffer); - - return retval; -} - -#define set_lcd_line(number) \ -static ssize_t lcd_line_##number(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - change_string(kit, buf, number - 1); \ - return count; \ -} - -#define lcd_line_attr(number) \ - __ATTR(lcd_line_##number, S_IWUGO, NULL, lcd_line_##number) - -set_lcd_line(1); -set_lcd_line(2); - -static ssize_t set_backlight(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct interfacekit *kit = dev_get_drvdata(dev); - int enabled; - unsigned char *buffer; - int retval = -ENOMEM; - - buffer = kzalloc(8, GFP_KERNEL); - if (!buffer) { - dev_err(&kit->udev->dev, "%s - out of memory\n", __func__); - goto exit; - } - - if (sscanf(buf, "%d", &enabled) < 1) { - retval = -EINVAL; - goto exit; - } - if (enabled) - buffer[0] = 0x01; - buffer[7] = 0x11; - - dev_dbg(&kit->udev->dev, "Setting backlight to %s\n", enabled ? "on" : "off"); - - retval = usb_control_msg(kit->udev, - usb_sndctrlpipe(kit->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000); - if (retval < 0) - goto exit; - - retval = count; -exit: - kfree(buffer); - return retval; -} - -static struct device_attribute dev_lcd_line_attrs[] = { - lcd_line_attr(1), - lcd_line_attr(2), - __ATTR(backlight, S_IWUGO, NULL, set_backlight) -}; - -static void remove_lcd_files(struct interfacekit *kit) -{ - int i; - - if (kit->lcd_files_on) { - dev_dbg(&kit->udev->dev, "Removing lcd files\n"); - - for (i=0; idev, &dev_lcd_line_attrs[i]); - } -} - -static ssize_t enable_lcd_files(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct interfacekit *kit = dev_get_drvdata(dev); - int enable; - int i, rc; - - if (kit->ifkit->has_lcd == 0) - return -ENODEV; - - if (sscanf(buf, "%d", &enable) < 1) - return -EINVAL; - - if (enable) { - if (!kit->lcd_files_on) { - dev_dbg(&kit->udev->dev, "Adding lcd files\n"); - for (i=0; idev, - &dev_lcd_line_attrs[i]); - if (rc) - goto out; - } - kit->lcd_files_on = 1; - } - } else { - if (kit->lcd_files_on) { - remove_lcd_files(kit); - kit->lcd_files_on = 0; - } - } - - return count; -out: - while (i-- > 0) - device_remove_file(kit->dev, &dev_lcd_line_attrs[i]); - - return rc; -} - -static DEVICE_ATTR(lcd, S_IWUGO, NULL, enable_lcd_files); - -static void interfacekit_irq(struct urb *urb) -{ - struct interfacekit *kit = urb->context; - unsigned char *buffer = kit->data; - int i, level, sensor; - int retval; - int status = urb->status; - - switch (status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - /* digital inputs */ - if (kit->ifkit->inputs == 16) { - for (i=0; i < 8; i++) { - level = (buffer[0] >> i) & 1; - if (kit->inputs[i] != level) { - kit->inputs[i] = level; - set_bit(i, &kit->input_events); - } - level = (buffer[1] >> i) & 1; - if (kit->inputs[8 + i] != level) { - kit->inputs[8 + i] = level; - set_bit(8 + i, &kit->input_events); - } - } - } - else if (kit->ifkit->inputs == 8) { - for (i=0; i < 8; i++) { - level = (buffer[1] >> i) & 1; - if (kit->inputs[i] != level) { - kit->inputs[i] = level; - set_bit(i, &kit->input_events); - } - } - } - - /* analog inputs */ - if (kit->ifkit->sensors) { - sensor = (buffer[0] & 1) ? 4 : 0; - - level = buffer[2] + (buffer[3] & 0x0f) * 256; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - sensor++; - level = buffer[4] + (buffer[3] & 0xf0) * 16; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - sensor++; - level = buffer[5] + (buffer[6] & 0x0f) * 256; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - sensor++; - level = buffer[7] + (buffer[6] & 0xf0) * 16; - if (level != kit->sensors[sensor]) { - kit->sensors[sensor] = level; - set_bit(sensor, &kit->sensor_events); - } - } - - if (kit->input_events || kit->sensor_events) - schedule_delayed_work(&kit->do_notify, 0); - -resubmit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - err("can't resubmit intr, %s-%s/interfacekit0, retval %d", - kit->udev->bus->bus_name, - kit->udev->devpath, retval); -} - -static void do_notify(struct work_struct *work) -{ - struct interfacekit *kit = - container_of(work, struct interfacekit, do_notify.work); - int i; - char sysfs_file[8]; - - for (i=0; iifkit->inputs; i++) { - if (test_and_clear_bit(i, &kit->input_events)) { - sprintf(sysfs_file, "input%d", i + 1); - sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); - } - } - - for (i=0; iifkit->sensors; i++) { - if (test_and_clear_bit(i, &kit->sensor_events)) { - sprintf(sysfs_file, "sensor%d", i + 1); - sysfs_notify(&kit->dev->kobj, NULL, sysfs_file); - } - } -} - -static void do_resubmit(struct work_struct *work) -{ - struct interfacekit *kit = - container_of(work, struct interfacekit, do_resubmit.work); - set_outputs(kit); -} - -#define show_set_output(value) \ -static ssize_t set_output##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - int enable; \ - int retval; \ - \ - if (sscanf(buf, "%d", &enable) < 1) \ - return -EINVAL; \ - \ - if (enable) \ - set_bit(value - 1, &kit->outputs); \ - else \ - clear_bit(value - 1, &kit->outputs); \ - \ - retval = set_outputs(kit); \ - \ - return retval ? retval : count; \ -} \ - \ -static ssize_t show_output##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", !!test_bit(value - 1, &kit->outputs));\ -} - -#define output_attr(value) \ - __ATTR(output##value, S_IWUGO | S_IRUGO, \ - show_output##value, set_output##value) - -show_set_output(1); -show_set_output(2); -show_set_output(3); -show_set_output(4); -show_set_output(5); -show_set_output(6); -show_set_output(7); -show_set_output(8); -show_set_output(9); -show_set_output(10); -show_set_output(11); -show_set_output(12); -show_set_output(13); -show_set_output(14); -show_set_output(15); -show_set_output(16); - -static struct device_attribute dev_output_attrs[] = { - output_attr(1), output_attr(2), output_attr(3), output_attr(4), - output_attr(5), output_attr(6), output_attr(7), output_attr(8), - output_attr(9), output_attr(10), output_attr(11), output_attr(12), - output_attr(13), output_attr(14), output_attr(15), output_attr(16) -}; - -#define show_input(value) \ -static ssize_t show_input##value(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", (int)kit->inputs[value - 1]); \ -} - -#define input_attr(value) \ - __ATTR(input##value, S_IRUGO, show_input##value, NULL) - -show_input(1); -show_input(2); -show_input(3); -show_input(4); -show_input(5); -show_input(6); -show_input(7); -show_input(8); -show_input(9); -show_input(10); -show_input(11); -show_input(12); -show_input(13); -show_input(14); -show_input(15); -show_input(16); - -static struct device_attribute dev_input_attrs[] = { - input_attr(1), input_attr(2), input_attr(3), input_attr(4), - input_attr(5), input_attr(6), input_attr(7), input_attr(8), - input_attr(9), input_attr(10), input_attr(11), input_attr(12), - input_attr(13), input_attr(14), input_attr(15), input_attr(16) -}; - -#define show_sensor(value) \ -static ssize_t show_sensor##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct interfacekit *kit = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", (int)kit->sensors[value - 1]); \ -} - -#define sensor_attr(value) \ - __ATTR(sensor##value, S_IRUGO, show_sensor##value, NULL) - -show_sensor(1); -show_sensor(2); -show_sensor(3); -show_sensor(4); -show_sensor(5); -show_sensor(6); -show_sensor(7); -show_sensor(8); - -static struct device_attribute dev_sensor_attrs[] = { - sensor_attr(1), sensor_attr(2), sensor_attr(3), sensor_attr(4), - sensor_attr(5), sensor_attr(6), sensor_attr(7), sensor_attr(8) -}; - -static int interfacekit_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct interfacekit *kit; - struct driver_interfacekit *ifkit; - int pipe, maxp, rc = -ENOMEM; - int bit, value, i; - - ifkit = (struct driver_interfacekit *)id->driver_info; - if (!ifkit) - return -ENODEV; - - interface = intf->cur_altsetting; - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_dir_in(endpoint)) - return -ENODEV; - /* - * bmAttributes - */ - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - kit = kzalloc(sizeof(*kit), GFP_KERNEL); - if (!kit) - goto out; - - kit->dev_no = -1; - kit->ifkit = ifkit; - kit->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &kit->data_dma); - if (!kit->data) - goto out; - - kit->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!kit->irq) - goto out; - - kit->udev = usb_get_dev(dev); - kit->intf = intf; - INIT_DELAYED_WORK(&kit->do_notify, do_notify); - INIT_DELAYED_WORK(&kit->do_resubmit, do_resubmit); - usb_fill_int_urb(kit->irq, kit->udev, pipe, kit->data, - maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, - interfacekit_irq, kit, endpoint->bInterval); - kit->irq->transfer_dma = kit->data_dma; - kit->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_set_intfdata(intf, kit); - - do { - bit = find_first_zero_bit(&device_no, sizeof(device_no)); - value = test_and_set_bit(bit, &device_no); - } while(value); - kit->dev_no = bit; - - kit->dev = device_create(phidget_class, &kit->udev->dev, MKDEV(0, 0), - kit, "interfacekit%d", kit->dev_no); - if (IS_ERR(kit->dev)) { - rc = PTR_ERR(kit->dev); - kit->dev = NULL; - goto out; - } - - if (usb_submit_urb(kit->irq, GFP_KERNEL)) { - rc = -EIO; - goto out; - } - - for (i=0; ioutputs; i++ ) { - rc = device_create_file(kit->dev, &dev_output_attrs[i]); - if (rc) - goto out2; - } - - for (i=0; iinputs; i++ ) { - rc = device_create_file(kit->dev, &dev_input_attrs[i]); - if (rc) - goto out3; - } - - for (i=0; isensors; i++ ) { - rc = device_create_file(kit->dev, &dev_sensor_attrs[i]); - if (rc) - goto out4; - } - - if (ifkit->has_lcd) { - rc = device_create_file(kit->dev, &dev_attr_lcd); - if (rc) - goto out4; - - } - - dev_info(&intf->dev, "USB PhidgetInterfaceKit %d/%d/%d attached\n", - ifkit->sensors, ifkit->inputs, ifkit->outputs); - - return 0; - -out4: - while (i-- > 0) - device_remove_file(kit->dev, &dev_sensor_attrs[i]); - - i = ifkit->inputs; -out3: - while (i-- > 0) - device_remove_file(kit->dev, &dev_input_attrs[i]); - - i = ifkit->outputs; -out2: - while (i-- > 0) - device_remove_file(kit->dev, &dev_output_attrs[i]); -out: - if (kit) { - usb_free_urb(kit->irq); - if (kit->data) - usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); - if (kit->dev) - device_unregister(kit->dev); - if (kit->dev_no >= 0) - clear_bit(kit->dev_no, &device_no); - - kfree(kit); - } - - return rc; -} - -static void interfacekit_disconnect(struct usb_interface *interface) -{ - struct interfacekit *kit; - int i; - - kit = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - if (!kit) - return; - - usb_kill_urb(kit->irq); - usb_free_urb(kit->irq); - usb_buffer_free(kit->udev, URB_INT_SIZE, kit->data, kit->data_dma); - - cancel_delayed_work(&kit->do_notify); - cancel_delayed_work(&kit->do_resubmit); - - for (i=0; iifkit->outputs; i++) - device_remove_file(kit->dev, &dev_output_attrs[i]); - - for (i=0; iifkit->inputs; i++) - device_remove_file(kit->dev, &dev_input_attrs[i]); - - for (i=0; iifkit->sensors; i++) - device_remove_file(kit->dev, &dev_sensor_attrs[i]); - - if (kit->ifkit->has_lcd) { - device_remove_file(kit->dev, &dev_attr_lcd); - remove_lcd_files(kit); - } - - device_unregister(kit->dev); - - dev_info(&interface->dev, "USB PhidgetInterfaceKit %d/%d/%d detached\n", - kit->ifkit->sensors, kit->ifkit->inputs, kit->ifkit->outputs); - - usb_put_dev(kit->udev); - clear_bit(kit->dev_no, &device_no); - - kfree(kit); -} - -static struct usb_driver interfacekit_driver = { - .name = "phidgetkit", - .probe = interfacekit_probe, - .disconnect = interfacekit_disconnect, - .id_table = id_table -}; - -static int __init interfacekit_init(void) -{ - int retval = 0; - - retval = usb_register(&interfacekit_driver); - if (retval) - err("usb_register failed. Error number %d", retval); - - return retval; -} - -static void __exit interfacekit_exit(void) -{ - usb_deregister(&interfacekit_driver); -} - -module_init(interfacekit_init); -module_exit(interfacekit_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/phidgetmotorcontrol.c b/drivers/usb/misc/phidgetmotorcontrol.c deleted file mode 100644 index 38088b44349..00000000000 --- a/drivers/usb/misc/phidgetmotorcontrol.c +++ /dev/null @@ -1,465 +0,0 @@ -/* - * USB Phidget MotorControl driver - * - * Copyright (C) 2006 Sean Young - * - * 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 "phidget.h" - -#define DRIVER_AUTHOR "Sean Young " -#define DRIVER_DESC "USB PhidgetMotorControl Driver" - -#define USB_VENDOR_ID_GLAB 0x06c2 -#define USB_DEVICE_ID_MOTORCONTROL 0x0058 - -#define URB_INT_SIZE 8 - -static unsigned long device_no; - -struct motorcontrol { - struct usb_device *udev; - struct usb_interface *intf; - struct device *dev; - int dev_no; - u8 inputs[4]; - s8 desired_speed[2]; - s8 speed[2]; - s16 _current[2]; - s8 acceleration[2]; - struct urb *irq; - unsigned char *data; - dma_addr_t data_dma; - - struct delayed_work do_notify; - unsigned long input_events; - unsigned long speed_events; - unsigned long exceed_events; -}; - -static struct usb_device_id id_table[] = { - { USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_MOTORCONTROL) }, - {} -}; -MODULE_DEVICE_TABLE(usb, id_table); - -static int set_motor(struct motorcontrol *mc, int motor) -{ - u8 *buffer; - int speed, speed2, acceleration; - int retval; - - buffer = kzalloc(8, GFP_KERNEL); - if (!buffer) { - dev_err(&mc->intf->dev, "%s - out of memory\n", __func__); - return -ENOMEM; - } - - acceleration = mc->acceleration[motor] * 10; - /* -127 <= speed <= 127 */ - speed = (mc->desired_speed[motor] * 127) / 100; - /* -0x7300 <= speed2 <= 0x7300 */ - speed2 = (mc->desired_speed[motor] * 230 * 128) / 100; - - buffer[0] = motor; - buffer[1] = speed; - buffer[2] = acceleration >> 8; - buffer[3] = acceleration; - buffer[4] = speed2 >> 8; - buffer[5] = speed2; - - retval = usb_control_msg(mc->udev, - usb_sndctrlpipe(mc->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 8, 2000); - - if (retval != 8) - dev_err(&mc->intf->dev, "usb_control_msg returned %d\n", - retval); - kfree(buffer); - - return retval < 0 ? retval : 0; -} - -static void motorcontrol_irq(struct urb *urb) -{ - struct motorcontrol *mc = urb->context; - unsigned char *buffer = mc->data; - int i, level; - int retval; - int status = urb->status;; - - switch (status) { - case 0: /* success */ - break; - case -ECONNRESET: /* unlink */ - case -ENOENT: - case -ESHUTDOWN: - return; - /* -EPIPE: should clear the halt */ - default: /* error */ - goto resubmit; - } - - /* digital inputs */ - for (i=0; i<4; i++) { - level = (buffer[0] >> i) & 1; - if (mc->inputs[i] != level) { - mc->inputs[i] = level; - set_bit(i, &mc->input_events); - } - } - - /* motor speed */ - if (buffer[2] == 0) { - for (i=0; i<2; i++) { - level = ((s8)buffer[4+i]) * 100 / 127; - if (mc->speed[i] != level) { - mc->speed[i] = level; - set_bit(i, &mc->speed_events); - } - } - } else { - int index = buffer[3] & 1; - - level = ((s8)buffer[4] << 8) | buffer[5]; - level = level * 100 / 29440; - if (mc->speed[index] != level) { - mc->speed[index] = level; - set_bit(index, &mc->speed_events); - } - - level = ((s8)buffer[6] << 8) | buffer[7]; - mc->_current[index] = level * 100 / 1572; - } - - if (buffer[1] & 1) - set_bit(0, &mc->exceed_events); - - if (buffer[1] & 2) - set_bit(1, &mc->exceed_events); - - if (mc->input_events || mc->exceed_events || mc->speed_events) - schedule_delayed_work(&mc->do_notify, 0); - -resubmit: - retval = usb_submit_urb(urb, GFP_ATOMIC); - if (retval) - dev_err(&mc->intf->dev, - "can't resubmit intr, %s-%s/motorcontrol0, retval %d\n", - mc->udev->bus->bus_name, - mc->udev->devpath, retval); -} - -static void do_notify(struct work_struct *work) -{ - struct motorcontrol *mc = - container_of(work, struct motorcontrol, do_notify.work); - int i; - char sysfs_file[8]; - - for (i=0; i<4; i++) { - if (test_and_clear_bit(i, &mc->input_events)) { - sprintf(sysfs_file, "input%d", i); - sysfs_notify(&mc->dev->kobj, NULL, sysfs_file); - } - } - - for (i=0; i<2; i++) { - if (test_and_clear_bit(i, &mc->speed_events)) { - sprintf(sysfs_file, "speed%d", i); - sysfs_notify(&mc->dev->kobj, NULL, sysfs_file); - } - } - - for (i=0; i<2; i++) { - if (test_and_clear_bit(i, &mc->exceed_events)) - dev_warn(&mc->intf->dev, - "motor #%d exceeds 1.5 Amp current limit\n", i); - } -} - -#define show_set_speed(value) \ -static ssize_t set_speed##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - int speed; \ - int retval; \ - \ - if (sscanf(buf, "%d", &speed) < 1) \ - return -EINVAL; \ - \ - if (speed < -100 || speed > 100) \ - return -EINVAL; \ - \ - mc->desired_speed[value] = speed; \ - \ - retval = set_motor(mc, value); \ - \ - return retval ? retval : count; \ -} \ - \ -static ssize_t show_speed##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", mc->speed[value]); \ -} - -#define speed_attr(value) \ - __ATTR(speed##value, S_IWUGO | S_IRUGO, \ - show_speed##value, set_speed##value) - -show_set_speed(0); -show_set_speed(1); - -#define show_set_acceleration(value) \ -static ssize_t set_acceleration##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - int acceleration; \ - int retval; \ - \ - if (sscanf(buf, "%d", &acceleration) < 1) \ - return -EINVAL; \ - \ - if (acceleration < 0 || acceleration > 100) \ - return -EINVAL; \ - \ - mc->acceleration[value] = acceleration; \ - \ - retval = set_motor(mc, value); \ - \ - return retval ? retval : count; \ -} \ - \ -static ssize_t show_acceleration##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", mc->acceleration[value]); \ -} - -#define acceleration_attr(value) \ - __ATTR(acceleration##value, S_IWUGO | S_IRUGO, \ - show_acceleration##value, set_acceleration##value) - -show_set_acceleration(0); -show_set_acceleration(1); - -#define show_current(value) \ -static ssize_t show_current##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%dmA\n", (int)mc->_current[value]); \ -} - -#define current_attr(value) \ - __ATTR(current##value, S_IRUGO, show_current##value, NULL) - -show_current(0); -show_current(1); - -#define show_input(value) \ -static ssize_t show_input##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct motorcontrol *mc = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d\n", (int)mc->inputs[value]); \ -} - -#define input_attr(value) \ - __ATTR(input##value, S_IRUGO, show_input##value, NULL) - -show_input(0); -show_input(1); -show_input(2); -show_input(3); - -static struct device_attribute dev_attrs[] = { - input_attr(0), - input_attr(1), - input_attr(2), - input_attr(3), - speed_attr(0), - speed_attr(1), - acceleration_attr(0), - acceleration_attr(1), - current_attr(0), - current_attr(1) -}; - -static int motorcontrol_probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct usb_host_interface *interface; - struct usb_endpoint_descriptor *endpoint; - struct motorcontrol *mc; - int pipe, maxp, rc = -ENOMEM; - int bit, value, i; - - interface = intf->cur_altsetting; - if (interface->desc.bNumEndpoints != 1) - return -ENODEV; - - endpoint = &interface->endpoint[0].desc; - if (!usb_endpoint_dir_in(endpoint)) - return -ENODEV; - - /* - * bmAttributes - */ - pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); - maxp = usb_maxpacket(dev, pipe, usb_pipeout(pipe)); - - mc = kzalloc(sizeof(*mc), GFP_KERNEL); - if (!mc) - goto out; - - mc->dev_no = -1; - mc->data = usb_buffer_alloc(dev, URB_INT_SIZE, GFP_ATOMIC, &mc->data_dma); - if (!mc->data) - goto out; - - mc->irq = usb_alloc_urb(0, GFP_KERNEL); - if (!mc->irq) - goto out; - - mc->udev = usb_get_dev(dev); - mc->intf = intf; - mc->acceleration[0] = mc->acceleration[1] = 10; - INIT_DELAYED_WORK(&mc->do_notify, do_notify); - usb_fill_int_urb(mc->irq, mc->udev, pipe, mc->data, - maxp > URB_INT_SIZE ? URB_INT_SIZE : maxp, - motorcontrol_irq, mc, endpoint->bInterval); - mc->irq->transfer_dma = mc->data_dma; - mc->irq->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_set_intfdata(intf, mc); - - do { - bit = find_first_zero_bit(&device_no, sizeof(device_no)); - value = test_and_set_bit(bit, &device_no); - } while(value); - mc->dev_no = bit; - - mc->dev = device_create(phidget_class, &mc->udev->dev, MKDEV(0, 0), mc, - "motorcontrol%d", mc->dev_no); - if (IS_ERR(mc->dev)) { - rc = PTR_ERR(mc->dev); - mc->dev = NULL; - goto out; - } - - if (usb_submit_urb(mc->irq, GFP_KERNEL)) { - rc = -EIO; - goto out; - } - - for (i=0; idev, &dev_attrs[i]); - if (rc) - goto out2; - } - - dev_info(&intf->dev, "USB PhidgetMotorControl attached\n"); - - return 0; -out2: - while (i-- > 0) - device_remove_file(mc->dev, &dev_attrs[i]); -out: - if (mc) { - usb_free_urb(mc->irq); - if (mc->data) - usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma); - if (mc->dev) - device_unregister(mc->dev); - if (mc->dev_no >= 0) - clear_bit(mc->dev_no, &device_no); - - kfree(mc); - } - - return rc; -} - -static void motorcontrol_disconnect(struct usb_interface *interface) -{ - struct motorcontrol *mc; - int i; - - mc = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - if (!mc) - return; - - usb_kill_urb(mc->irq); - usb_free_urb(mc->irq); - usb_buffer_free(mc->udev, URB_INT_SIZE, mc->data, mc->data_dma); - - cancel_delayed_work(&mc->do_notify); - - for (i=0; idev, &dev_attrs[i]); - - device_unregister(mc->dev); - - usb_put_dev(mc->udev); - clear_bit(mc->dev_no, &device_no); - kfree(mc); - - dev_info(&interface->dev, "USB PhidgetMotorControl detached\n"); -} - -static struct usb_driver motorcontrol_driver = { - .name = "phidgetmotorcontrol", - .probe = motorcontrol_probe, - .disconnect = motorcontrol_disconnect, - .id_table = id_table -}; - -static int __init motorcontrol_init(void) -{ - int retval = 0; - - retval = usb_register(&motorcontrol_driver); - if (retval) - err("usb_register failed. Error number %d", retval); - - return retval; -} - -static void __exit motorcontrol_exit(void) -{ - usb_deregister(&motorcontrol_driver); -} - -module_init(motorcontrol_init); -module_exit(motorcontrol_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/usb/misc/phidgetservo.c b/drivers/usb/misc/phidgetservo.c deleted file mode 100644 index bef6fe16364..00000000000 --- a/drivers/usb/misc/phidgetservo.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * USB PhidgetServo driver 1.0 - * - * Copyright (C) 2004, 2006 Sean Young - * - * 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. - * - * This is a driver for the USB PhidgetServo version 2.0 and 3.0 servo - * controllers available at: http://www.phidgets.com/ - * - * Note that the driver takes input as: degrees.minutes - * - * CAUTION: Generally you should use 0 < degrees < 180 as anything else - * is probably beyond the range of your servo and may damage it. - */ - -#include -#include -#include -#include -#include -#include - -#include "phidget.h" - -#define DRIVER_AUTHOR "Sean Young " -#define DRIVER_DESC "USB PhidgetServo Driver" - -#define VENDOR_ID_GLAB 0x06c2 -#define DEVICE_ID_GLAB_PHIDGETSERVO_QUAD 0x0038 -#define DEVICE_ID_GLAB_PHIDGETSERVO_UNI 0x0039 - -#define VENDOR_ID_WISEGROUP 0x0925 -#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD 0x8101 -#define VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI 0x8104 - -#define SERVO_VERSION_30 0x01 -#define SERVO_COUNT_QUAD 0x02 - -static struct usb_device_id id_table[] = { - { - USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_QUAD), - .driver_info = SERVO_VERSION_30 | SERVO_COUNT_QUAD - }, - { - USB_DEVICE(VENDOR_ID_GLAB, DEVICE_ID_GLAB_PHIDGETSERVO_UNI), - .driver_info = SERVO_VERSION_30 - }, - { - USB_DEVICE(VENDOR_ID_WISEGROUP, - VENDOR_ID_WISEGROUP_PHIDGETSERVO_QUAD), - .driver_info = SERVO_COUNT_QUAD - }, - { - USB_DEVICE(VENDOR_ID_WISEGROUP, - VENDOR_ID_WISEGROUP_PHIDGETSERVO_UNI), - .driver_info = 0 - }, - {} -}; - -MODULE_DEVICE_TABLE(usb, id_table); - -static int unsigned long device_no; - -struct phidget_servo { - struct usb_device *udev; - struct device *dev; - int dev_no; - ulong type; - int pulse[4]; - int degrees[4]; - int minutes[4]; -}; - -static int -change_position_v30(struct phidget_servo *servo, int servo_no, int degrees, - int minutes) -{ - int retval; - unsigned char *buffer; - - if (degrees < -23 || degrees > 362) - return -EINVAL; - - buffer = kmalloc(6, GFP_KERNEL); - if (!buffer) { - dev_err(&servo->udev->dev, "%s - out of memory\n", - __func__); - return -ENOMEM; - } - - /* - * pulse = 0 - 4095 - * angle = 0 - 180 degrees - * - * pulse = angle * 10.6 + 243.8 - */ - servo->pulse[servo_no] = ((degrees*60 + minutes)*106 + 2438*60)/600; - servo->degrees[servo_no]= degrees; - servo->minutes[servo_no]= minutes; - - /* - * The PhidgetServo v3.0 is controlled by sending 6 bytes, - * 4 * 12 bits for each servo. - * - * low = lower 8 bits pulse - * high = higher 4 bits pulse - * - * offset bits - * +---+-----------------+ - * | 0 | low 0 | - * +---+--------+--------+ - * | 1 | high 1 | high 0 | - * +---+--------+--------+ - * | 2 | low 1 | - * +---+-----------------+ - * | 3 | low 2 | - * +---+--------+--------+ - * | 4 | high 3 | high 2 | - * +---+--------+--------+ - * | 5 | low 3 | - * +---+-----------------+ - */ - - buffer[0] = servo->pulse[0] & 0xff; - buffer[1] = (servo->pulse[0] >> 8 & 0x0f) - | (servo->pulse[1] >> 4 & 0xf0); - buffer[2] = servo->pulse[1] & 0xff; - buffer[3] = servo->pulse[2] & 0xff; - buffer[4] = (servo->pulse[2] >> 8 & 0x0f) - | (servo->pulse[3] >> 4 & 0xf0); - buffer[5] = servo->pulse[3] & 0xff; - - dev_dbg(&servo->udev->dev, - "data: %02x %02x %02x %02x %02x %02x\n", - buffer[0], buffer[1], buffer[2], - buffer[3], buffer[4], buffer[5]); - - retval = usb_control_msg(servo->udev, - usb_sndctrlpipe(servo->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 6, 2000); - - kfree(buffer); - - return retval; -} - -static int -change_position_v20(struct phidget_servo *servo, int servo_no, int degrees, - int minutes) -{ - int retval; - unsigned char *buffer; - - if (degrees < -23 || degrees > 278) - return -EINVAL; - - buffer = kmalloc(2, GFP_KERNEL); - if (!buffer) { - dev_err(&servo->udev->dev, "%s - out of memory\n", - __func__); - return -ENOMEM; - } - - /* - * angle = 0 - 180 degrees - * pulse = angle + 23 - */ - servo->pulse[servo_no]= degrees + 23; - servo->degrees[servo_no]= degrees; - servo->minutes[servo_no]= 0; - - /* - * The PhidgetServo v2.0 is controlled by sending two bytes. The - * first byte is the servo number xor'ed with 2: - * - * servo 0 = 2 - * servo 1 = 3 - * servo 2 = 0 - * servo 3 = 1 - * - * The second byte is the position. - */ - - buffer[0] = servo_no ^ 2; - buffer[1] = servo->pulse[servo_no]; - - dev_dbg(&servo->udev->dev, "data: %02x %02x\n", buffer[0], buffer[1]); - - retval = usb_control_msg(servo->udev, - usb_sndctrlpipe(servo->udev, 0), - 0x09, 0x21, 0x0200, 0x0000, buffer, 2, 2000); - - kfree(buffer); - - return retval; -} - -#define show_set(value) \ -static ssize_t set_servo##value (struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - int degrees, minutes, retval; \ - struct phidget_servo *servo = dev_get_drvdata(dev); \ - \ - minutes = 0; \ - /* must at least convert degrees */ \ - if (sscanf(buf, "%d.%d", °rees, &minutes) < 1) { \ - return -EINVAL; \ - } \ - \ - if (minutes < 0 || minutes > 59) \ - return -EINVAL; \ - \ - if (servo->type & SERVO_VERSION_30) \ - retval = change_position_v30(servo, value, degrees, \ - minutes); \ - else \ - retval = change_position_v20(servo, value, degrees, \ - minutes); \ - \ - return retval < 0 ? retval : count; \ -} \ - \ -static ssize_t show_servo##value (struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct phidget_servo *servo = dev_get_drvdata(dev); \ - \ - return sprintf(buf, "%d.%02d\n", servo->degrees[value], \ - servo->minutes[value]); \ -} - -#define servo_attr(value) \ - __ATTR(servo##value, S_IWUGO | S_IRUGO, \ - show_servo##value, set_servo##value) -show_set(0); -show_set(1); -show_set(2); -show_set(3); - -static struct device_attribute dev_attrs[] = { - servo_attr(0), servo_attr(1), servo_attr(2), servo_attr(3) -}; - -static int -servo_probe(struct usb_interface *interface, const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(interface); - struct phidget_servo *dev; - int bit, value, rc; - int servo_count, i; - - dev = kzalloc(sizeof (struct phidget_servo), GFP_KERNEL); - if (dev == NULL) { - dev_err(&interface->dev, "%s - out of memory\n", __func__); - rc = -ENOMEM; - goto out; - } - - dev->udev = usb_get_dev(udev); - dev->type = id->driver_info; - dev->dev_no = -1; - usb_set_intfdata(interface, dev); - - do { - bit = find_first_zero_bit(&device_no, sizeof(device_no)); - value = test_and_set_bit(bit, &device_no); - } while (value); - dev->dev_no = bit; - - dev->dev = device_create(phidget_class, &dev->udev->dev, MKDEV(0, 0), - dev, "servo%d", dev->dev_no); - if (IS_ERR(dev->dev)) { - rc = PTR_ERR(dev->dev); - dev->dev = NULL; - goto out; - } - - servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; - - for (i=0; idev, &dev_attrs[i]); - if (rc) - goto out2; - } - - dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 attached\n", - servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2); - - if (!(dev->type & SERVO_VERSION_30)) - dev_info(&interface->dev, - "WARNING: v2.0 not tested! Please report if it works.\n"); - - return 0; -out2: - while (i-- > 0) - device_remove_file(dev->dev, &dev_attrs[i]); -out: - if (dev) { - if (dev->dev) - device_unregister(dev->dev); - if (dev->dev_no >= 0) - clear_bit(dev->dev_no, &device_no); - - kfree(dev); - } - - return rc; -} - -static void -servo_disconnect(struct usb_interface *interface) -{ - struct phidget_servo *dev; - int servo_count, i; - - dev = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - if (!dev) - return; - - servo_count = dev->type & SERVO_COUNT_QUAD ? 4 : 1; - - for (i=0; idev, &dev_attrs[i]); - - device_unregister(dev->dev); - usb_put_dev(dev->udev); - - dev_info(&interface->dev, "USB %d-Motor PhidgetServo v%d.0 detached\n", - servo_count, dev->type & SERVO_VERSION_30 ? 3 : 2); - - clear_bit(dev->dev_no, &device_no); - kfree(dev); -} - -static struct usb_driver servo_driver = { - .name = "phidgetservo", - .probe = servo_probe, - .disconnect = servo_disconnect, - .id_table = id_table -}; - -static int __init -phidget_servo_init(void) -{ - int retval; - - retval = usb_register(&servo_driver); - if (retval) - err("usb_register failed. Error number %d", retval); - - return retval; -} - -static void __exit -phidget_servo_exit(void) -{ - usb_deregister(&servo_driver); -} - -module_init(phidget_servo_init); -module_exit(phidget_servo_exit); - -MODULE_AUTHOR(DRIVER_AUTHOR); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); -- cgit v1.2.3 From 4fe0387afa893b44c5a21b9bfbb0888354ef4656 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 26 Feb 2009 10:21:02 -0500 Subject: USB: don't send Set-Interface after reset This patch (as1221) changes the way usbcore reinitializes a device following a reset or a reset-resume. Currently we call usb_set_interface() for every interface in the active configuration; this is to put the interface into the same altsetting as before the reset and to make sure that the host's endpoint state matches the device's endpoint state. However, sending a Set-Interface request is a waste of time if an interface was already in altsetting 0 before the reset, since it is certainly in altsetting 0 afterward. In addition, many devices can't handle Set-Interface requests -- they crash when they receive them. So instead, the patch adds code to check each interface. If the interface wasn't in altsetting 0 before the reset, we go head with the Set-Interface request as before. But if it was then we skip sending the Set-Interface request, and we clear out the host-side endpoint state by calling usb_disable_interface() followed by usb_enable_interface(). The patch also adds a couple of new comments to explain what's going on. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hub.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index f17d9ebc44a..81eb3e6b659 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3393,10 +3393,10 @@ static int usb_reset_and_verify_device(struct usb_device *udev) udev->descriptor = descriptor; /* for disconnect() calls */ goto re_enumerate; } - + + /* Restore the device's previous configuration */ if (!udev->actconfig) goto done; - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), USB_REQ_SET_CONFIGURATION, 0, udev->actconfig->desc.bConfigurationValue, 0, @@ -3409,16 +3409,25 @@ static int usb_reset_and_verify_device(struct usb_device *udev) } usb_set_device_state(udev, USB_STATE_CONFIGURED); + /* Put interfaces back into the same altsettings as before. + * Don't bother to send the Set-Interface request for interfaces + * that were already in altsetting 0; besides being unnecessary, + * many devices can't handle it. Instead just reset the host-side + * endpoint state. + */ for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *intf = udev->actconfig->interface[i]; struct usb_interface_descriptor *desc; - /* set_interface resets host side toggle even - * for altsetting zero. the interface may have no driver. - */ desc = &intf->cur_altsetting->desc; - ret = usb_set_interface(udev, desc->bInterfaceNumber, - desc->bAlternateSetting); + if (desc->bAlternateSetting == 0) { + usb_disable_interface(udev, intf, true); + usb_enable_interface(udev, intf, true); + ret = 0; + } else { + ret = usb_set_interface(udev, desc->bInterfaceNumber, + desc->bAlternateSetting); + } if (ret < 0) { dev_err(&udev->dev, "failed to restore interface %d " "altsetting %d (error=%d)\n", -- cgit v1.2.3 From d34d9721a559fd11ec682bd9ef17220de0162060 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 9 Mar 2009 13:44:48 -0400 Subject: USB: usbfs: remove unneeded "inline" annotations This patch (as1223) removes a bunch of unnecessary "inline" annotations from the usbfs driver. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index 8f022af2fd7..d3883f63960 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -104,7 +104,7 @@ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic"); #define MAX_USBFS_BUFFER_SIZE 16384 -static inline int connected(struct dev_state *ps) +static int connected(struct dev_state *ps) { return (!list_empty(&ps->list) && ps->dev->state != USB_STATE_NOTATTACHED); @@ -248,7 +248,7 @@ static void free_async(struct async *as) kfree(as); } -static inline void async_newpending(struct async *as) +static void async_newpending(struct async *as) { struct dev_state *ps = as->ps; unsigned long flags; @@ -258,7 +258,7 @@ static inline void async_newpending(struct async *as) spin_unlock_irqrestore(&ps->lock, flags); } -static inline void async_removepending(struct async *as) +static void async_removepending(struct async *as) { struct dev_state *ps = as->ps; unsigned long flags; @@ -268,7 +268,7 @@ static inline void async_removepending(struct async *as) spin_unlock_irqrestore(&ps->lock, flags); } -static inline struct async *async_getcompleted(struct dev_state *ps) +static struct async *async_getcompleted(struct dev_state *ps) { unsigned long flags; struct async *as = NULL; @@ -283,7 +283,7 @@ static inline struct async *async_getcompleted(struct dev_state *ps) return as; } -static inline struct async *async_getpending(struct dev_state *ps, +static struct async *async_getpending(struct dev_state *ps, void __user *userurb) { unsigned long flags; @@ -376,7 +376,7 @@ static void destroy_async_on_interface(struct dev_state *ps, destroy_async(ps, &hitlist); } -static inline void destroy_all_async(struct dev_state *ps) +static void destroy_all_async(struct dev_state *ps) { destroy_async(ps, &ps->async_pending); } -- cgit v1.2.3 From 31dbb803464d75b96212cce9052dfeaeac0819de Mon Sep 17 00:00:00 2001 From: Johannes Weiner Date: Wed, 4 Mar 2009 12:06:15 -0800 Subject: USB: use kzfree() Use kzfree() instead of memset() + kfree(). Signed-off-by: Johannes Weiner Reviewed-by: Pekka Enberg Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/hwa-hc.c | 3 +-- drivers/usb/wusbcore/cbaf.c | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c index 8582236e4ca..cbf30e515f2 100644 --- a/drivers/usb/host/hwa-hc.c +++ b/drivers/usb/host/hwa-hc.c @@ -464,8 +464,7 @@ static int __hwahc_dev_set_key(struct wusbhc *wusbhc, u8 port_idx, u32 tkid, port_idx << 8 | iface_no, keyd, keyd_len, 1000 /* FIXME: arbitrary */); - memset(keyd, 0, sizeof(*keyd)); /* clear keys etc. */ - kfree(keyd); + kzfree(keyd); /* clear keys etc. */ return result; } diff --git a/drivers/usb/wusbcore/cbaf.c b/drivers/usb/wusbcore/cbaf.c index 1335cbe1191..25eae405f62 100644 --- a/drivers/usb/wusbcore/cbaf.c +++ b/drivers/usb/wusbcore/cbaf.c @@ -638,8 +638,7 @@ static void cbaf_disconnect(struct usb_interface *iface) usb_put_intf(iface); kfree(cbaf->buffer); /* paranoia: clean up crypto keys */ - memset(cbaf, 0, sizeof(*cbaf)); - kfree(cbaf); + kzfree(cbaf); } static struct usb_device_id cbaf_id_table[] = { -- cgit v1.2.3 From ef8b6bcb39559d956f897acf7ebe600d5105d479 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Thu, 26 Feb 2009 22:19:22 +0000 Subject: USB: CP2101 Support AN205 baud rates This patch adds support for the extended range of baud rates supported by CP2102 and CP2103 devices described in SiLabs AN205. An additional function cp2101_quantise_baudrate rounds the baud rate as per AN205 Table 1. A modification to the baud rate calculation removes a rounding error, allowing the full range of baud rates to be used. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 92 +++++++++++++++++++++++++-------------------- 1 file changed, 52 insertions(+), 40 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 9b4082b58c5..9b56e35aee4 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -31,7 +31,7 @@ /* * Version Information */ -#define DRIVER_VERSION "v0.07" +#define DRIVER_VERSION "v0.08" #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" /* @@ -301,6 +301,47 @@ static inline int cp2101_set_config_single(struct usb_serial_port *port, return cp2101_set_config(port, request, &data, 2); } +/* + * cp2101_quantise_baudrate + * Quantises the baud rate as per AN205 Table 1 + */ +static unsigned int cp2101_quantise_baudrate(unsigned int baud) { + if (baud <= 56) baud = 0; + else if (baud <= 300) baud = 300; + else if (baud <= 600) baud = 600; + else if (baud <= 1200) baud = 1200; + else if (baud <= 1800) baud = 1800; + else if (baud <= 2400) baud = 2400; + else if (baud <= 4000) baud = 4000; + else if (baud <= 4803) baud = 4800; + else if (baud <= 7207) baud = 7200; + else if (baud <= 9612) baud = 9600; + else if (baud <= 14428) baud = 14400; + else if (baud <= 16062) baud = 16000; + else if (baud <= 19250) baud = 19200; + else if (baud <= 28912) baud = 28800; + else if (baud <= 38601) baud = 38400; + else if (baud <= 51558) baud = 51200; + else if (baud <= 56280) baud = 56000; + else if (baud <= 58053) baud = 57600; + else if (baud <= 64111) baud = 64000; + else if (baud <= 77608) baud = 76800; + else if (baud <= 117028) baud = 115200; + else if (baud <= 129347) baud = 128000; + else if (baud <= 156868) baud = 153600; + else if (baud <= 237832) baud = 230400; + else if (baud <= 254234) baud = 250000; + else if (baud <= 273066) baud = 256000; + else if (baud <= 491520) baud = 460800; + else if (baud <= 567138) baud = 500000; + else if (baud <= 670254) baud = 576000; + else if (baud <= 1053257) baud = 921600; + else if (baud <= 1474560) baud = 1228800; + else if (baud <= 2457600) baud = 1843200; + else baud = 3686400; + return baud; +} + static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp) { @@ -388,7 +429,7 @@ static void cp2101_get_termios (struct tty_struct *tty) cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); /* Convert to baudrate */ if (baud) - baud = BAUD_RATE_GEN_FREQ / baud; + baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); dbg("%s - baud rate = %d", __func__, baud); @@ -517,46 +558,17 @@ static void cp2101_set_termios(struct tty_struct *tty, tty->termios->c_cflag &= ~CMSPAR; cflag = tty->termios->c_cflag; old_cflag = old_termios->c_cflag; - baud = tty_get_baud_rate(tty); + baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty)); /* If the baud rate is to be updated*/ - if (baud != tty_termios_baud_rate(old_termios)) { - switch (baud) { - case 0: - case 600: - case 1200: - case 1800: - case 2400: - case 4800: - case 7200: - case 9600: - case 14400: - case 19200: - case 28800: - case 38400: - case 55854: - case 57600: - case 115200: - case 127117: - case 230400: - case 460800: - case 921600: - case 3686400: - break; - default: - baud = 9600; - break; - } - - if (baud) { - dbg("%s - Setting baud rate to %d baud", __func__, - baud); - if (cp2101_set_config_single(port, CP2101_BAUDRATE, - (BAUD_RATE_GEN_FREQ / baud))) { - dev_err(&port->dev, "Baud rate requested not " - "supported by device\n"); - baud = tty_termios_baud_rate(old_termios); - } + if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { + dbg("%s - Setting baud rate to %d baud", __func__, + baud); + if (cp2101_set_config_single(port, CP2101_BAUDRATE, + ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { + dev_err(&port->dev, "Baud rate requested not " + "supported by device\n"); + baud = tty_termios_baud_rate(old_termios); } } /* Report back the resulting baud rate */ -- cgit v1.2.3 From 97324955c62aaa104edea2ef4370dc8882a5ab82 Mon Sep 17 00:00:00 2001 From: Craig Shelley Date: Thu, 26 Feb 2009 22:21:51 +0000 Subject: USB: CP2101 Reduce Error Logging This patch lowers the logging priority of certain messages to prevent users from flooding the log files. Signed-off-by: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp2101.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c index 9b56e35aee4..2f23d064362 100644 --- a/drivers/usb/serial/cp2101.c +++ b/drivers/usb/serial/cp2101.c @@ -11,10 +11,6 @@ * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow * control thanks to Munir Nassar nassarmu@real-time.com * - * Outstanding Issues: - * Buffers are not flushed when the port is opened. - * Multiple calls to write() may fail with "Resource temporarily unavailable" - * */ #include @@ -225,7 +221,7 @@ static int cp2101_get_config(struct usb_serial_port *port, u8 request, kfree(buf); if (result != size) { - dev_err(&port->dev, "%s - Unable to send config request, " + dbg("%s - Unable to send config request, " "request=0x%x size=%d result=%d\n", __func__, request, size, result); return -EPROTO; @@ -276,7 +272,7 @@ static int cp2101_set_config(struct usb_serial_port *port, u8 request, kfree(buf); if ((size > 2 && result != size) || result < 0) { - dev_err(&port->dev, "%s - Unable to send request, " + dbg("%s - Unable to send request, " "request=0x%x size=%d result=%d\n", __func__, request, size, result); return -EPROTO; @@ -566,8 +562,7 @@ static void cp2101_set_termios(struct tty_struct *tty, baud); if (cp2101_set_config_single(port, CP2101_BAUDRATE, ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { - dev_err(&port->dev, "Baud rate requested not " - "supported by device\n"); + dbg("Baud rate requested not supported by device\n"); baud = tty_termios_baud_rate(old_termios); } } @@ -600,14 +595,14 @@ static void cp2101_set_termios(struct tty_struct *tty, dbg("%s - data bits = 9", __func__); break;*/ default: - dev_err(&port->dev, "cp2101 driver does not " + dbg("cp2101 driver does not " "support the number of bits requested," " using 8 bit mode\n"); bits |= BITS_DATA_8; break; } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dev_err(&port->dev, "Number of data bits requested " + dbg("Number of data bits requested " "not supported by device\n"); } @@ -624,7 +619,7 @@ static void cp2101_set_termios(struct tty_struct *tty, } } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dev_err(&port->dev, "Parity mode not supported " + dbg("Parity mode not supported " "by device\n"); } @@ -639,7 +634,7 @@ static void cp2101_set_termios(struct tty_struct *tty, dbg("%s - stop bits = 1", __func__); } if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dev_err(&port->dev, "Number of stop bits requested " + dbg("Number of stop bits requested " "not supported by device\n"); } -- cgit v1.2.3 From 03ee251546a9360cbb4c27c250d128dcbcfd9931 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 11 Mar 2009 11:03:49 -0700 Subject: USB: serial: rename cp2101 driver to cp210x Lots of users are getting confused about the cp2101 driver. It really does support more than just the cp2101 device, so rename it to cp210x to try to prevent confusion. Cc: Craig Shelley Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/Kconfig | 10 +- drivers/usb/serial/Makefile | 2 +- drivers/usb/serial/cp2101.c | 788 -------------------------------------------- drivers/usb/serial/cp210x.c | 788 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 794 insertions(+), 794 deletions(-) delete mode 100644 drivers/usb/serial/cp2101.c create mode 100644 drivers/usb/serial/cp210x.c (limited to 'drivers') diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig index 4afe73e8ec4..a65f9196b0a 100644 --- a/drivers/usb/serial/Kconfig +++ b/drivers/usb/serial/Kconfig @@ -116,14 +116,14 @@ config USB_SERIAL_DIGI_ACCELEPORT To compile this driver as a module, choose M here: the module will be called digi_acceleport. -config USB_SERIAL_CP2101 - tristate "USB CP2101 UART Bridge Controller" +config USB_SERIAL_CP210X + tristate "USB CP210x family of UART Bridge Controllers" help - Say Y here if you want to use a CP2101/CP2102 based USB to RS232 - converter. + Say Y here if you want to use a CP2101/CP2102/CP2103 based USB + to RS232 converters. To compile this driver as a module, choose M here: the - module will be called cp2101. + module will be called cp210x. config USB_SERIAL_CYPRESS_M8 tristate "USB Cypress M8 USB Serial Driver" diff --git a/drivers/usb/serial/Makefile b/drivers/usb/serial/Makefile index 94043babe1d..66619beb6cc 100644 --- a/drivers/usb/serial/Makefile +++ b/drivers/usb/serial/Makefile @@ -15,7 +15,7 @@ obj-$(CONFIG_USB_SERIAL_AIRCABLE) += aircable.o obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o -obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o +obj-$(CONFIG_USB_SERIAL_CP210X) += cp210x.o obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o obj-$(CONFIG_USB_SERIAL_DEBUG) += usb_debug.o diff --git a/drivers/usb/serial/cp2101.c b/drivers/usb/serial/cp2101.c deleted file mode 100644 index 2f23d064362..00000000000 --- a/drivers/usb/serial/cp2101.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * Silicon Laboratories CP2101/CP2102 USB to RS232 serial adaptor driver - * - * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk) - * - * 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. - * - * Support to set flow control line levels using TIOCMGET and TIOCMSET - * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow - * control thanks to Munir Nassar nassarmu@real-time.com - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Version Information - */ -#define DRIVER_VERSION "v0.08" -#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" - -/* - * Function Prototypes - */ -static int cp2101_open(struct tty_struct *, struct usb_serial_port *, - struct file *); -static void cp2101_cleanup(struct usb_serial_port *); -static void cp2101_close(struct tty_struct *, struct usb_serial_port *, - struct file*); -static void cp2101_get_termios(struct tty_struct *); -static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, - struct ktermios*); -static int cp2101_tiocmget(struct tty_struct *, struct file *); -static int cp2101_tiocmset(struct tty_struct *, struct file *, - unsigned int, unsigned int); -static void cp2101_break_ctl(struct tty_struct *, int); -static int cp2101_startup(struct usb_serial *); -static void cp2101_shutdown(struct usb_serial *); - - -static int debug; - -static struct usb_device_id id_table [] = { - { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ - { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ - { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ - { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ - { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ - { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ - { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ - { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ - { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ - { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ - { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ - { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ - { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */ - { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ - { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ - { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ - { USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */ - { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ - { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ - { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ - { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ - { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ - { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ - { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ - { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ - { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ - { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ - { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ - { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ - { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ - { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ - { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */ - { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ - { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ - { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ - { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ - { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ - { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ - { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */ - { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */ - { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ - { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ - { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ - { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ - { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ - { } /* Terminating Entry */ -}; - -MODULE_DEVICE_TABLE(usb, id_table); - -static struct usb_driver cp2101_driver = { - .name = "cp2101", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, - .no_dynamic_id = 1, -}; - -static struct usb_serial_driver cp2101_device = { - .driver = { - .owner = THIS_MODULE, - .name = "cp2101", - }, - .usb_driver = &cp2101_driver, - .id_table = id_table, - .num_ports = 1, - .open = cp2101_open, - .close = cp2101_close, - .break_ctl = cp2101_break_ctl, - .set_termios = cp2101_set_termios, - .tiocmget = cp2101_tiocmget, - .tiocmset = cp2101_tiocmset, - .attach = cp2101_startup, - .shutdown = cp2101_shutdown, -}; - -/* Config request types */ -#define REQTYPE_HOST_TO_DEVICE 0x41 -#define REQTYPE_DEVICE_TO_HOST 0xc1 - -/* Config SET requests. To GET, add 1 to the request number */ -#define CP2101_UART 0x00 /* Enable / Disable */ -#define CP2101_BAUDRATE 0x01 /* (BAUD_RATE_GEN_FREQ / baudrate) */ -#define CP2101_BITS 0x03 /* 0x(0)(databits)(parity)(stopbits) */ -#define CP2101_BREAK 0x05 /* On / Off */ -#define CP2101_CONTROL 0x07 /* Flow control line states */ -#define CP2101_MODEMCTL 0x13 /* Modem controls */ -#define CP2101_CONFIG_6 0x19 /* 6 bytes of config data ??? */ - -/* CP2101_UART */ -#define UART_ENABLE 0x0001 -#define UART_DISABLE 0x0000 - -/* CP2101_BAUDRATE */ -#define BAUD_RATE_GEN_FREQ 0x384000 - -/* CP2101_BITS */ -#define BITS_DATA_MASK 0X0f00 -#define BITS_DATA_5 0X0500 -#define BITS_DATA_6 0X0600 -#define BITS_DATA_7 0X0700 -#define BITS_DATA_8 0X0800 -#define BITS_DATA_9 0X0900 - -#define BITS_PARITY_MASK 0x00f0 -#define BITS_PARITY_NONE 0x0000 -#define BITS_PARITY_ODD 0x0010 -#define BITS_PARITY_EVEN 0x0020 -#define BITS_PARITY_MARK 0x0030 -#define BITS_PARITY_SPACE 0x0040 - -#define BITS_STOP_MASK 0x000f -#define BITS_STOP_1 0x0000 -#define BITS_STOP_1_5 0x0001 -#define BITS_STOP_2 0x0002 - -/* CP2101_BREAK */ -#define BREAK_ON 0x0000 -#define BREAK_OFF 0x0001 - -/* CP2101_CONTROL */ -#define CONTROL_DTR 0x0001 -#define CONTROL_RTS 0x0002 -#define CONTROL_CTS 0x0010 -#define CONTROL_DSR 0x0020 -#define CONTROL_RING 0x0040 -#define CONTROL_DCD 0x0080 -#define CONTROL_WRITE_DTR 0x0100 -#define CONTROL_WRITE_RTS 0x0200 - -/* - * cp2101_get_config - * Reads from the CP2101 configuration registers - * 'size' is specified in bytes. - * 'data' is a pointer to a pre-allocated array of integers large - * enough to hold 'size' bytes (with 4 bytes to each integer) - */ -static int cp2101_get_config(struct usb_serial_port *port, u8 request, - unsigned int *data, int size) -{ - struct usb_serial *serial = port->serial; - __le32 *buf; - int result, i, length; - - /* Number of integers required to contain the array */ - length = (((size - 1) | 3) + 1)/4; - - buf = kcalloc(length, sizeof(__le32), GFP_KERNEL); - if (!buf) { - dev_err(&port->dev, "%s - out of memory.\n", __func__); - return -ENOMEM; - } - - /* For get requests, the request number must be incremented */ - request++; - - /* Issue the request, attempting to read 'size' bytes */ - result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), - request, REQTYPE_DEVICE_TO_HOST, 0x0000, - 0, buf, size, 300); - - /* Convert data into an array of integers */ - for (i = 0; i < length; i++) - data[i] = le32_to_cpu(buf[i]); - - kfree(buf); - - if (result != size) { - dbg("%s - Unable to send config request, " - "request=0x%x size=%d result=%d\n", - __func__, request, size, result); - return -EPROTO; - } - - return 0; -} - -/* - * cp2101_set_config - * Writes to the CP2101 configuration registers - * Values less than 16 bits wide are sent directly - * 'size' is specified in bytes. - */ -static int cp2101_set_config(struct usb_serial_port *port, u8 request, - unsigned int *data, int size) -{ - struct usb_serial *serial = port->serial; - __le32 *buf; - int result, i, length; - - /* Number of integers required to contain the array */ - length = (((size - 1) | 3) + 1)/4; - - buf = kmalloc(length * sizeof(__le32), GFP_KERNEL); - if (!buf) { - dev_err(&port->dev, "%s - out of memory.\n", - __func__); - return -ENOMEM; - } - - /* Array of integers into bytes */ - for (i = 0; i < length; i++) - buf[i] = cpu_to_le32(data[i]); - - if (size > 2) { - result = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, REQTYPE_HOST_TO_DEVICE, 0x0000, - 0, buf, size, 300); - } else { - result = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, REQTYPE_HOST_TO_DEVICE, data[0], - 0, NULL, 0, 300); - } - - kfree(buf); - - if ((size > 2 && result != size) || result < 0) { - dbg("%s - Unable to send request, " - "request=0x%x size=%d result=%d\n", - __func__, request, size, result); - return -EPROTO; - } - - /* Single data value */ - result = usb_control_msg(serial->dev, - usb_sndctrlpipe(serial->dev, 0), - request, REQTYPE_HOST_TO_DEVICE, data[0], - 0, NULL, 0, 300); - return 0; -} - -/* - * cp2101_set_config_single - * Convenience function for calling cp2101_set_config on single data values - * without requiring an integer pointer - */ -static inline int cp2101_set_config_single(struct usb_serial_port *port, - u8 request, unsigned int data) -{ - return cp2101_set_config(port, request, &data, 2); -} - -/* - * cp2101_quantise_baudrate - * Quantises the baud rate as per AN205 Table 1 - */ -static unsigned int cp2101_quantise_baudrate(unsigned int baud) { - if (baud <= 56) baud = 0; - else if (baud <= 300) baud = 300; - else if (baud <= 600) baud = 600; - else if (baud <= 1200) baud = 1200; - else if (baud <= 1800) baud = 1800; - else if (baud <= 2400) baud = 2400; - else if (baud <= 4000) baud = 4000; - else if (baud <= 4803) baud = 4800; - else if (baud <= 7207) baud = 7200; - else if (baud <= 9612) baud = 9600; - else if (baud <= 14428) baud = 14400; - else if (baud <= 16062) baud = 16000; - else if (baud <= 19250) baud = 19200; - else if (baud <= 28912) baud = 28800; - else if (baud <= 38601) baud = 38400; - else if (baud <= 51558) baud = 51200; - else if (baud <= 56280) baud = 56000; - else if (baud <= 58053) baud = 57600; - else if (baud <= 64111) baud = 64000; - else if (baud <= 77608) baud = 76800; - else if (baud <= 117028) baud = 115200; - else if (baud <= 129347) baud = 128000; - else if (baud <= 156868) baud = 153600; - else if (baud <= 237832) baud = 230400; - else if (baud <= 254234) baud = 250000; - else if (baud <= 273066) baud = 256000; - else if (baud <= 491520) baud = 460800; - else if (baud <= 567138) baud = 500000; - else if (baud <= 670254) baud = 576000; - else if (baud <= 1053257) baud = 921600; - else if (baud <= 1474560) baud = 1228800; - else if (baud <= 2457600) baud = 1843200; - else baud = 3686400; - return baud; -} - -static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, - struct file *filp) -{ - struct usb_serial *serial = port->serial; - int result; - - dbg("%s - port %d", __func__, port->number); - - if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) { - dev_err(&port->dev, "%s - Unable to enable UART\n", - __func__); - return -EPROTO; - } - - /* Start reading from the device */ - usb_fill_bulk_urb(port->read_urb, serial->dev, - usb_rcvbulkpipe(serial->dev, - port->bulk_in_endpointAddress), - port->read_urb->transfer_buffer, - port->read_urb->transfer_buffer_length, - serial->type->read_bulk_callback, - port); - result = usb_submit_urb(port->read_urb, GFP_KERNEL); - if (result) { - dev_err(&port->dev, "%s - failed resubmitting read urb, " - "error %d\n", __func__, result); - return result; - } - - /* Configure the termios structure */ - cp2101_get_termios(tty); - - /* Set the DTR and RTS pins low */ - cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0); - - return 0; -} - -static void cp2101_cleanup(struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - - dbg("%s - port %d", __func__, port->number); - - if (serial->dev) { - /* shutdown any bulk reads that might be going on */ - if (serial->num_bulk_out) - usb_kill_urb(port->write_urb); - if (serial->num_bulk_in) - usb_kill_urb(port->read_urb); - } -} - -static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, - struct file *filp) -{ - dbg("%s - port %d", __func__, port->number); - - /* shutdown our urbs */ - dbg("%s - shutting down urbs", __func__); - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - - mutex_lock(&port->serial->disc_mutex); - if (!port->serial->disconnected) - cp2101_set_config_single(port, CP2101_UART, UART_DISABLE); - mutex_unlock(&port->serial->disc_mutex); -} - -/* - * cp2101_get_termios - * Reads the baud rate, data bits, parity, stop bits and flow control mode - * from the device, corrects any unsupported values, and configures the - * termios structure to reflect the state of the device - */ -static void cp2101_get_termios (struct tty_struct *tty) -{ - struct usb_serial_port *port = tty->driver_data; - unsigned int cflag, modem_ctl[4]; - unsigned int baud; - unsigned int bits; - - dbg("%s - port %d", __func__, port->number); - - cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); - /* Convert to baudrate */ - if (baud) - baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); - - dbg("%s - baud rate = %d", __func__, baud); - - tty_encode_baud_rate(tty, baud, baud); - cflag = tty->termios->c_cflag; - - cp2101_get_config(port, CP2101_BITS, &bits, 2); - cflag &= ~CSIZE; - switch (bits & BITS_DATA_MASK) { - case BITS_DATA_5: - dbg("%s - data bits = 5", __func__); - cflag |= CS5; - break; - case BITS_DATA_6: - dbg("%s - data bits = 6", __func__); - cflag |= CS6; - break; - case BITS_DATA_7: - dbg("%s - data bits = 7", __func__); - cflag |= CS7; - break; - case BITS_DATA_8: - dbg("%s - data bits = 8", __func__); - cflag |= CS8; - break; - case BITS_DATA_9: - dbg("%s - data bits = 9 (not supported, using 8 data bits)", - __func__); - cflag |= CS8; - bits &= ~BITS_DATA_MASK; - bits |= BITS_DATA_8; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - default: - dbg("%s - Unknown number of data bits, using 8", __func__); - cflag |= CS8; - bits &= ~BITS_DATA_MASK; - bits |= BITS_DATA_8; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - } - - switch (bits & BITS_PARITY_MASK) { - case BITS_PARITY_NONE: - dbg("%s - parity = NONE", __func__); - cflag &= ~PARENB; - break; - case BITS_PARITY_ODD: - dbg("%s - parity = ODD", __func__); - cflag |= (PARENB|PARODD); - break; - case BITS_PARITY_EVEN: - dbg("%s - parity = EVEN", __func__); - cflag &= ~PARODD; - cflag |= PARENB; - break; - case BITS_PARITY_MARK: - dbg("%s - parity = MARK (not supported, disabling parity)", - __func__); - cflag &= ~PARENB; - bits &= ~BITS_PARITY_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - case BITS_PARITY_SPACE: - dbg("%s - parity = SPACE (not supported, disabling parity)", - __func__); - cflag &= ~PARENB; - bits &= ~BITS_PARITY_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - default: - dbg("%s - Unknown parity mode, disabling parity", __func__); - cflag &= ~PARENB; - bits &= ~BITS_PARITY_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - } - - cflag &= ~CSTOPB; - switch (bits & BITS_STOP_MASK) { - case BITS_STOP_1: - dbg("%s - stop bits = 1", __func__); - break; - case BITS_STOP_1_5: - dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)", - __func__); - bits &= ~BITS_STOP_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - case BITS_STOP_2: - dbg("%s - stop bits = 2", __func__); - cflag |= CSTOPB; - break; - default: - dbg("%s - Unknown number of stop bits, using 1 stop bit", - __func__); - bits &= ~BITS_STOP_MASK; - cp2101_set_config(port, CP2101_BITS, &bits, 2); - break; - } - - cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); - if (modem_ctl[0] & 0x0008) { - dbg("%s - flow control = CRTSCTS", __func__); - cflag |= CRTSCTS; - } else { - dbg("%s - flow control = NONE", __func__); - cflag &= ~CRTSCTS; - } - - tty->termios->c_cflag = cflag; -} - -static void cp2101_set_termios(struct tty_struct *tty, - struct usb_serial_port *port, struct ktermios *old_termios) -{ - unsigned int cflag, old_cflag; - unsigned int baud = 0, bits; - unsigned int modem_ctl[4]; - - dbg("%s - port %d", __func__, port->number); - - if (!tty) - return; - - tty->termios->c_cflag &= ~CMSPAR; - cflag = tty->termios->c_cflag; - old_cflag = old_termios->c_cflag; - baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty)); - - /* If the baud rate is to be updated*/ - if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { - dbg("%s - Setting baud rate to %d baud", __func__, - baud); - if (cp2101_set_config_single(port, CP2101_BAUDRATE, - ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { - dbg("Baud rate requested not supported by device\n"); - baud = tty_termios_baud_rate(old_termios); - } - } - /* Report back the resulting baud rate */ - tty_encode_baud_rate(tty, baud, baud); - - /* If the number of data bits is to be updated */ - if ((cflag & CSIZE) != (old_cflag & CSIZE)) { - cp2101_get_config(port, CP2101_BITS, &bits, 2); - bits &= ~BITS_DATA_MASK; - switch (cflag & CSIZE) { - case CS5: - bits |= BITS_DATA_5; - dbg("%s - data bits = 5", __func__); - break; - case CS6: - bits |= BITS_DATA_6; - dbg("%s - data bits = 6", __func__); - break; - case CS7: - bits |= BITS_DATA_7; - dbg("%s - data bits = 7", __func__); - break; - case CS8: - bits |= BITS_DATA_8; - dbg("%s - data bits = 8", __func__); - break; - /*case CS9: - bits |= BITS_DATA_9; - dbg("%s - data bits = 9", __func__); - break;*/ - default: - dbg("cp2101 driver does not " - "support the number of bits requested," - " using 8 bit mode\n"); - bits |= BITS_DATA_8; - break; - } - if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dbg("Number of data bits requested " - "not supported by device\n"); - } - - if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) { - cp2101_get_config(port, CP2101_BITS, &bits, 2); - bits &= ~BITS_PARITY_MASK; - if (cflag & PARENB) { - if (cflag & PARODD) { - bits |= BITS_PARITY_ODD; - dbg("%s - parity = ODD", __func__); - } else { - bits |= BITS_PARITY_EVEN; - dbg("%s - parity = EVEN", __func__); - } - } - if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dbg("Parity mode not supported " - "by device\n"); - } - - if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { - cp2101_get_config(port, CP2101_BITS, &bits, 2); - bits &= ~BITS_STOP_MASK; - if (cflag & CSTOPB) { - bits |= BITS_STOP_2; - dbg("%s - stop bits = 2", __func__); - } else { - bits |= BITS_STOP_1; - dbg("%s - stop bits = 1", __func__); - } - if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) - dbg("Number of stop bits requested " - "not supported by device\n"); - } - - if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { - cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); - dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", - __func__, modem_ctl[0], modem_ctl[1], - modem_ctl[2], modem_ctl[3]); - - if (cflag & CRTSCTS) { - modem_ctl[0] &= ~0x7B; - modem_ctl[0] |= 0x09; - modem_ctl[1] = 0x80; - dbg("%s - flow control = CRTSCTS", __func__); - } else { - modem_ctl[0] &= ~0x7B; - modem_ctl[0] |= 0x01; - modem_ctl[1] |= 0x40; - dbg("%s - flow control = NONE", __func__); - } - - dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", - __func__, modem_ctl[0], modem_ctl[1], - modem_ctl[2], modem_ctl[3]); - cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16); - } - -} - -static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, - unsigned int set, unsigned int clear) -{ - struct usb_serial_port *port = tty->driver_data; - unsigned int control = 0; - - dbg("%s - port %d", __func__, port->number); - - if (set & TIOCM_RTS) { - control |= CONTROL_RTS; - control |= CONTROL_WRITE_RTS; - } - if (set & TIOCM_DTR) { - control |= CONTROL_DTR; - control |= CONTROL_WRITE_DTR; - } - if (clear & TIOCM_RTS) { - control &= ~CONTROL_RTS; - control |= CONTROL_WRITE_RTS; - } - if (clear & TIOCM_DTR) { - control &= ~CONTROL_DTR; - control |= CONTROL_WRITE_DTR; - } - - dbg("%s - control = 0x%.4x", __func__, control); - - return cp2101_set_config(port, CP2101_CONTROL, &control, 2); - -} - -static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) -{ - struct usb_serial_port *port = tty->driver_data; - unsigned int control; - int result; - - dbg("%s - port %d", __func__, port->number); - - cp2101_get_config(port, CP2101_CONTROL, &control, 1); - - result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0) - |((control & CONTROL_RTS) ? TIOCM_RTS : 0) - |((control & CONTROL_CTS) ? TIOCM_CTS : 0) - |((control & CONTROL_DSR) ? TIOCM_DSR : 0) - |((control & CONTROL_RING)? TIOCM_RI : 0) - |((control & CONTROL_DCD) ? TIOCM_CD : 0); - - dbg("%s - control = 0x%.2x", __func__, control); - - return result; -} - -static void cp2101_break_ctl (struct tty_struct *tty, int break_state) -{ - struct usb_serial_port *port = tty->driver_data; - unsigned int state; - - dbg("%s - port %d", __func__, port->number); - if (break_state == 0) - state = BREAK_OFF; - else - state = BREAK_ON; - dbg("%s - turning break %s", __func__, - state == BREAK_OFF ? "off" : "on"); - cp2101_set_config(port, CP2101_BREAK, &state, 2); -} - -static int cp2101_startup(struct usb_serial *serial) -{ - /* CP2101 buffers behave strangely unless device is reset */ - usb_reset_device(serial->dev); - return 0; -} - -static void cp2101_shutdown(struct usb_serial *serial) -{ - int i; - - dbg("%s", __func__); - - /* Stop reads and writes on all ports */ - for (i = 0; i < serial->num_ports; ++i) - cp2101_cleanup(serial->port[i]); -} - -static int __init cp2101_init(void) -{ - int retval; - - retval = usb_serial_register(&cp2101_device); - if (retval) - return retval; /* Failed to register */ - - retval = usb_register(&cp2101_driver); - if (retval) { - /* Failed to register */ - usb_serial_deregister(&cp2101_device); - return retval; - } - - /* Success */ - printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" - DRIVER_DESC "\n"); - return 0; -} - -static void __exit cp2101_exit(void) -{ - usb_deregister(&cp2101_driver); - usb_serial_deregister(&cp2101_device); -} - -module_init(cp2101_init); -module_exit(cp2101_exit); - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_VERSION(DRIVER_VERSION); -MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Enable verbose debugging messages"); diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c new file mode 100644 index 00000000000..2f23d064362 --- /dev/null +++ b/drivers/usb/serial/cp210x.c @@ -0,0 +1,788 @@ +/* + * Silicon Laboratories CP2101/CP2102 USB to RS232 serial adaptor driver + * + * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk) + * + * 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. + * + * Support to set flow control line levels using TIOCMGET and TIOCMSET + * thanks to Karl Hiramoto karl@hiramoto.org. RTSCTS hardware flow + * control thanks to Munir Nassar nassarmu@real-time.com + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Version Information + */ +#define DRIVER_VERSION "v0.08" +#define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" + +/* + * Function Prototypes + */ +static int cp2101_open(struct tty_struct *, struct usb_serial_port *, + struct file *); +static void cp2101_cleanup(struct usb_serial_port *); +static void cp2101_close(struct tty_struct *, struct usb_serial_port *, + struct file*); +static void cp2101_get_termios(struct tty_struct *); +static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, + struct ktermios*); +static int cp2101_tiocmget(struct tty_struct *, struct file *); +static int cp2101_tiocmset(struct tty_struct *, struct file *, + unsigned int, unsigned int); +static void cp2101_break_ctl(struct tty_struct *, int); +static int cp2101_startup(struct usb_serial *); +static void cp2101_shutdown(struct usb_serial *); + + +static int debug; + +static struct usb_device_id id_table [] = { + { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ + { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ + { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ + { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ + { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ + { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ + { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ + { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ + { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ + { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ + { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ + { USB_DEVICE(0x10C4, 0x8054) }, /* Enfora GSM2228 */ + { USB_DEVICE(0x10C4, 0x8066) }, /* Argussoft In-System Programmer */ + { USB_DEVICE(0x10C4, 0x807A) }, /* Crumb128 board */ + { USB_DEVICE(0x10C4, 0x80CA) }, /* Degree Controls Inc */ + { USB_DEVICE(0x10C4, 0x80DD) }, /* Tracient RFID */ + { USB_DEVICE(0x10C4, 0x80F6) }, /* Suunto sports instrument */ + { USB_DEVICE(0x10C4, 0x8115) }, /* Arygon NFC/Mifare Reader */ + { USB_DEVICE(0x10C4, 0x813D) }, /* Burnside Telecom Deskmobile */ + { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ + { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ + { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ + { USB_DEVICE(0x10C4, 0x819F) }, /* MJS USB Toslink Switcher */ + { USB_DEVICE(0x10C4, 0x81A6) }, /* ThinkOptics WavIt */ + { USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */ + { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ + { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ + { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ + { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ + { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ + { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */ + { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ + { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ + { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ + { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ + { USB_DEVICE(0x10C4, 0xF002) }, /* Elan Digital Systems USBwave12 */ + { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */ + { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */ + { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ + { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ + { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ + { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ + { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ + { } /* Terminating Entry */ +}; + +MODULE_DEVICE_TABLE(usb, id_table); + +static struct usb_driver cp2101_driver = { + .name = "cp2101", + .probe = usb_serial_probe, + .disconnect = usb_serial_disconnect, + .id_table = id_table, + .no_dynamic_id = 1, +}; + +static struct usb_serial_driver cp2101_device = { + .driver = { + .owner = THIS_MODULE, + .name = "cp2101", + }, + .usb_driver = &cp2101_driver, + .id_table = id_table, + .num_ports = 1, + .open = cp2101_open, + .close = cp2101_close, + .break_ctl = cp2101_break_ctl, + .set_termios = cp2101_set_termios, + .tiocmget = cp2101_tiocmget, + .tiocmset = cp2101_tiocmset, + .attach = cp2101_startup, + .shutdown = cp2101_shutdown, +}; + +/* Config request types */ +#define REQTYPE_HOST_TO_DEVICE 0x41 +#define REQTYPE_DEVICE_TO_HOST 0xc1 + +/* Config SET requests. To GET, add 1 to the request number */ +#define CP2101_UART 0x00 /* Enable / Disable */ +#define CP2101_BAUDRATE 0x01 /* (BAUD_RATE_GEN_FREQ / baudrate) */ +#define CP2101_BITS 0x03 /* 0x(0)(databits)(parity)(stopbits) */ +#define CP2101_BREAK 0x05 /* On / Off */ +#define CP2101_CONTROL 0x07 /* Flow control line states */ +#define CP2101_MODEMCTL 0x13 /* Modem controls */ +#define CP2101_CONFIG_6 0x19 /* 6 bytes of config data ??? */ + +/* CP2101_UART */ +#define UART_ENABLE 0x0001 +#define UART_DISABLE 0x0000 + +/* CP2101_BAUDRATE */ +#define BAUD_RATE_GEN_FREQ 0x384000 + +/* CP2101_BITS */ +#define BITS_DATA_MASK 0X0f00 +#define BITS_DATA_5 0X0500 +#define BITS_DATA_6 0X0600 +#define BITS_DATA_7 0X0700 +#define BITS_DATA_8 0X0800 +#define BITS_DATA_9 0X0900 + +#define BITS_PARITY_MASK 0x00f0 +#define BITS_PARITY_NONE 0x0000 +#define BITS_PARITY_ODD 0x0010 +#define BITS_PARITY_EVEN 0x0020 +#define BITS_PARITY_MARK 0x0030 +#define BITS_PARITY_SPACE 0x0040 + +#define BITS_STOP_MASK 0x000f +#define BITS_STOP_1 0x0000 +#define BITS_STOP_1_5 0x0001 +#define BITS_STOP_2 0x0002 + +/* CP2101_BREAK */ +#define BREAK_ON 0x0000 +#define BREAK_OFF 0x0001 + +/* CP2101_CONTROL */ +#define CONTROL_DTR 0x0001 +#define CONTROL_RTS 0x0002 +#define CONTROL_CTS 0x0010 +#define CONTROL_DSR 0x0020 +#define CONTROL_RING 0x0040 +#define CONTROL_DCD 0x0080 +#define CONTROL_WRITE_DTR 0x0100 +#define CONTROL_WRITE_RTS 0x0200 + +/* + * cp2101_get_config + * Reads from the CP2101 configuration registers + * 'size' is specified in bytes. + * 'data' is a pointer to a pre-allocated array of integers large + * enough to hold 'size' bytes (with 4 bytes to each integer) + */ +static int cp2101_get_config(struct usb_serial_port *port, u8 request, + unsigned int *data, int size) +{ + struct usb_serial *serial = port->serial; + __le32 *buf; + int result, i, length; + + /* Number of integers required to contain the array */ + length = (((size - 1) | 3) + 1)/4; + + buf = kcalloc(length, sizeof(__le32), GFP_KERNEL); + if (!buf) { + dev_err(&port->dev, "%s - out of memory.\n", __func__); + return -ENOMEM; + } + + /* For get requests, the request number must be incremented */ + request++; + + /* Issue the request, attempting to read 'size' bytes */ + result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), + request, REQTYPE_DEVICE_TO_HOST, 0x0000, + 0, buf, size, 300); + + /* Convert data into an array of integers */ + for (i = 0; i < length; i++) + data[i] = le32_to_cpu(buf[i]); + + kfree(buf); + + if (result != size) { + dbg("%s - Unable to send config request, " + "request=0x%x size=%d result=%d\n", + __func__, request, size, result); + return -EPROTO; + } + + return 0; +} + +/* + * cp2101_set_config + * Writes to the CP2101 configuration registers + * Values less than 16 bits wide are sent directly + * 'size' is specified in bytes. + */ +static int cp2101_set_config(struct usb_serial_port *port, u8 request, + unsigned int *data, int size) +{ + struct usb_serial *serial = port->serial; + __le32 *buf; + int result, i, length; + + /* Number of integers required to contain the array */ + length = (((size - 1) | 3) + 1)/4; + + buf = kmalloc(length * sizeof(__le32), GFP_KERNEL); + if (!buf) { + dev_err(&port->dev, "%s - out of memory.\n", + __func__); + return -ENOMEM; + } + + /* Array of integers into bytes */ + for (i = 0; i < length; i++) + buf[i] = cpu_to_le32(data[i]); + + if (size > 2) { + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, 0x0000, + 0, buf, size, 300); + } else { + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, data[0], + 0, NULL, 0, 300); + } + + kfree(buf); + + if ((size > 2 && result != size) || result < 0) { + dbg("%s - Unable to send request, " + "request=0x%x size=%d result=%d\n", + __func__, request, size, result); + return -EPROTO; + } + + /* Single data value */ + result = usb_control_msg(serial->dev, + usb_sndctrlpipe(serial->dev, 0), + request, REQTYPE_HOST_TO_DEVICE, data[0], + 0, NULL, 0, 300); + return 0; +} + +/* + * cp2101_set_config_single + * Convenience function for calling cp2101_set_config on single data values + * without requiring an integer pointer + */ +static inline int cp2101_set_config_single(struct usb_serial_port *port, + u8 request, unsigned int data) +{ + return cp2101_set_config(port, request, &data, 2); +} + +/* + * cp2101_quantise_baudrate + * Quantises the baud rate as per AN205 Table 1 + */ +static unsigned int cp2101_quantise_baudrate(unsigned int baud) { + if (baud <= 56) baud = 0; + else if (baud <= 300) baud = 300; + else if (baud <= 600) baud = 600; + else if (baud <= 1200) baud = 1200; + else if (baud <= 1800) baud = 1800; + else if (baud <= 2400) baud = 2400; + else if (baud <= 4000) baud = 4000; + else if (baud <= 4803) baud = 4800; + else if (baud <= 7207) baud = 7200; + else if (baud <= 9612) baud = 9600; + else if (baud <= 14428) baud = 14400; + else if (baud <= 16062) baud = 16000; + else if (baud <= 19250) baud = 19200; + else if (baud <= 28912) baud = 28800; + else if (baud <= 38601) baud = 38400; + else if (baud <= 51558) baud = 51200; + else if (baud <= 56280) baud = 56000; + else if (baud <= 58053) baud = 57600; + else if (baud <= 64111) baud = 64000; + else if (baud <= 77608) baud = 76800; + else if (baud <= 117028) baud = 115200; + else if (baud <= 129347) baud = 128000; + else if (baud <= 156868) baud = 153600; + else if (baud <= 237832) baud = 230400; + else if (baud <= 254234) baud = 250000; + else if (baud <= 273066) baud = 256000; + else if (baud <= 491520) baud = 460800; + else if (baud <= 567138) baud = 500000; + else if (baud <= 670254) baud = 576000; + else if (baud <= 1053257) baud = 921600; + else if (baud <= 1474560) baud = 1228800; + else if (baud <= 2457600) baud = 1843200; + else baud = 3686400; + return baud; +} + +static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + struct usb_serial *serial = port->serial; + int result; + + dbg("%s - port %d", __func__, port->number); + + if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) { + dev_err(&port->dev, "%s - Unable to enable UART\n", + __func__); + return -EPROTO; + } + + /* Start reading from the device */ + usb_fill_bulk_urb(port->read_urb, serial->dev, + usb_rcvbulkpipe(serial->dev, + port->bulk_in_endpointAddress), + port->read_urb->transfer_buffer, + port->read_urb->transfer_buffer_length, + serial->type->read_bulk_callback, + port); + result = usb_submit_urb(port->read_urb, GFP_KERNEL); + if (result) { + dev_err(&port->dev, "%s - failed resubmitting read urb, " + "error %d\n", __func__, result); + return result; + } + + /* Configure the termios structure */ + cp2101_get_termios(tty); + + /* Set the DTR and RTS pins low */ + cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0); + + return 0; +} + +static void cp2101_cleanup(struct usb_serial_port *port) +{ + struct usb_serial *serial = port->serial; + + dbg("%s - port %d", __func__, port->number); + + if (serial->dev) { + /* shutdown any bulk reads that might be going on */ + if (serial->num_bulk_out) + usb_kill_urb(port->write_urb); + if (serial->num_bulk_in) + usb_kill_urb(port->read_urb); + } +} + +static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, + struct file *filp) +{ + dbg("%s - port %d", __func__, port->number); + + /* shutdown our urbs */ + dbg("%s - shutting down urbs", __func__); + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); + + mutex_lock(&port->serial->disc_mutex); + if (!port->serial->disconnected) + cp2101_set_config_single(port, CP2101_UART, UART_DISABLE); + mutex_unlock(&port->serial->disc_mutex); +} + +/* + * cp2101_get_termios + * Reads the baud rate, data bits, parity, stop bits and flow control mode + * from the device, corrects any unsupported values, and configures the + * termios structure to reflect the state of the device + */ +static void cp2101_get_termios (struct tty_struct *tty) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned int cflag, modem_ctl[4]; + unsigned int baud; + unsigned int bits; + + dbg("%s - port %d", __func__, port->number); + + cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); + /* Convert to baudrate */ + if (baud) + baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); + + dbg("%s - baud rate = %d", __func__, baud); + + tty_encode_baud_rate(tty, baud, baud); + cflag = tty->termios->c_cflag; + + cp2101_get_config(port, CP2101_BITS, &bits, 2); + cflag &= ~CSIZE; + switch (bits & BITS_DATA_MASK) { + case BITS_DATA_5: + dbg("%s - data bits = 5", __func__); + cflag |= CS5; + break; + case BITS_DATA_6: + dbg("%s - data bits = 6", __func__); + cflag |= CS6; + break; + case BITS_DATA_7: + dbg("%s - data bits = 7", __func__); + cflag |= CS7; + break; + case BITS_DATA_8: + dbg("%s - data bits = 8", __func__); + cflag |= CS8; + break; + case BITS_DATA_9: + dbg("%s - data bits = 9 (not supported, using 8 data bits)", + __func__); + cflag |= CS8; + bits &= ~BITS_DATA_MASK; + bits |= BITS_DATA_8; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + default: + dbg("%s - Unknown number of data bits, using 8", __func__); + cflag |= CS8; + bits &= ~BITS_DATA_MASK; + bits |= BITS_DATA_8; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + } + + switch (bits & BITS_PARITY_MASK) { + case BITS_PARITY_NONE: + dbg("%s - parity = NONE", __func__); + cflag &= ~PARENB; + break; + case BITS_PARITY_ODD: + dbg("%s - parity = ODD", __func__); + cflag |= (PARENB|PARODD); + break; + case BITS_PARITY_EVEN: + dbg("%s - parity = EVEN", __func__); + cflag &= ~PARODD; + cflag |= PARENB; + break; + case BITS_PARITY_MARK: + dbg("%s - parity = MARK (not supported, disabling parity)", + __func__); + cflag &= ~PARENB; + bits &= ~BITS_PARITY_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + case BITS_PARITY_SPACE: + dbg("%s - parity = SPACE (not supported, disabling parity)", + __func__); + cflag &= ~PARENB; + bits &= ~BITS_PARITY_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + default: + dbg("%s - Unknown parity mode, disabling parity", __func__); + cflag &= ~PARENB; + bits &= ~BITS_PARITY_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + } + + cflag &= ~CSTOPB; + switch (bits & BITS_STOP_MASK) { + case BITS_STOP_1: + dbg("%s - stop bits = 1", __func__); + break; + case BITS_STOP_1_5: + dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)", + __func__); + bits &= ~BITS_STOP_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + case BITS_STOP_2: + dbg("%s - stop bits = 2", __func__); + cflag |= CSTOPB; + break; + default: + dbg("%s - Unknown number of stop bits, using 1 stop bit", + __func__); + bits &= ~BITS_STOP_MASK; + cp2101_set_config(port, CP2101_BITS, &bits, 2); + break; + } + + cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); + if (modem_ctl[0] & 0x0008) { + dbg("%s - flow control = CRTSCTS", __func__); + cflag |= CRTSCTS; + } else { + dbg("%s - flow control = NONE", __func__); + cflag &= ~CRTSCTS; + } + + tty->termios->c_cflag = cflag; +} + +static void cp2101_set_termios(struct tty_struct *tty, + struct usb_serial_port *port, struct ktermios *old_termios) +{ + unsigned int cflag, old_cflag; + unsigned int baud = 0, bits; + unsigned int modem_ctl[4]; + + dbg("%s - port %d", __func__, port->number); + + if (!tty) + return; + + tty->termios->c_cflag &= ~CMSPAR; + cflag = tty->termios->c_cflag; + old_cflag = old_termios->c_cflag; + baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty)); + + /* If the baud rate is to be updated*/ + if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { + dbg("%s - Setting baud rate to %d baud", __func__, + baud); + if (cp2101_set_config_single(port, CP2101_BAUDRATE, + ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { + dbg("Baud rate requested not supported by device\n"); + baud = tty_termios_baud_rate(old_termios); + } + } + /* Report back the resulting baud rate */ + tty_encode_baud_rate(tty, baud, baud); + + /* If the number of data bits is to be updated */ + if ((cflag & CSIZE) != (old_cflag & CSIZE)) { + cp2101_get_config(port, CP2101_BITS, &bits, 2); + bits &= ~BITS_DATA_MASK; + switch (cflag & CSIZE) { + case CS5: + bits |= BITS_DATA_5; + dbg("%s - data bits = 5", __func__); + break; + case CS6: + bits |= BITS_DATA_6; + dbg("%s - data bits = 6", __func__); + break; + case CS7: + bits |= BITS_DATA_7; + dbg("%s - data bits = 7", __func__); + break; + case CS8: + bits |= BITS_DATA_8; + dbg("%s - data bits = 8", __func__); + break; + /*case CS9: + bits |= BITS_DATA_9; + dbg("%s - data bits = 9", __func__); + break;*/ + default: + dbg("cp2101 driver does not " + "support the number of bits requested," + " using 8 bit mode\n"); + bits |= BITS_DATA_8; + break; + } + if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) + dbg("Number of data bits requested " + "not supported by device\n"); + } + + if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) { + cp2101_get_config(port, CP2101_BITS, &bits, 2); + bits &= ~BITS_PARITY_MASK; + if (cflag & PARENB) { + if (cflag & PARODD) { + bits |= BITS_PARITY_ODD; + dbg("%s - parity = ODD", __func__); + } else { + bits |= BITS_PARITY_EVEN; + dbg("%s - parity = EVEN", __func__); + } + } + if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) + dbg("Parity mode not supported " + "by device\n"); + } + + if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { + cp2101_get_config(port, CP2101_BITS, &bits, 2); + bits &= ~BITS_STOP_MASK; + if (cflag & CSTOPB) { + bits |= BITS_STOP_2; + dbg("%s - stop bits = 2", __func__); + } else { + bits |= BITS_STOP_1; + dbg("%s - stop bits = 1", __func__); + } + if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) + dbg("Number of stop bits requested " + "not supported by device\n"); + } + + if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { + cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); + dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", + __func__, modem_ctl[0], modem_ctl[1], + modem_ctl[2], modem_ctl[3]); + + if (cflag & CRTSCTS) { + modem_ctl[0] &= ~0x7B; + modem_ctl[0] |= 0x09; + modem_ctl[1] = 0x80; + dbg("%s - flow control = CRTSCTS", __func__); + } else { + modem_ctl[0] &= ~0x7B; + modem_ctl[0] |= 0x01; + modem_ctl[1] |= 0x40; + dbg("%s - flow control = NONE", __func__); + } + + dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", + __func__, modem_ctl[0], modem_ctl[1], + modem_ctl[2], modem_ctl[3]); + cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16); + } + +} + +static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, + unsigned int set, unsigned int clear) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned int control = 0; + + dbg("%s - port %d", __func__, port->number); + + if (set & TIOCM_RTS) { + control |= CONTROL_RTS; + control |= CONTROL_WRITE_RTS; + } + if (set & TIOCM_DTR) { + control |= CONTROL_DTR; + control |= CONTROL_WRITE_DTR; + } + if (clear & TIOCM_RTS) { + control &= ~CONTROL_RTS; + control |= CONTROL_WRITE_RTS; + } + if (clear & TIOCM_DTR) { + control &= ~CONTROL_DTR; + control |= CONTROL_WRITE_DTR; + } + + dbg("%s - control = 0x%.4x", __func__, control); + + return cp2101_set_config(port, CP2101_CONTROL, &control, 2); + +} + +static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned int control; + int result; + + dbg("%s - port %d", __func__, port->number); + + cp2101_get_config(port, CP2101_CONTROL, &control, 1); + + result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0) + |((control & CONTROL_RTS) ? TIOCM_RTS : 0) + |((control & CONTROL_CTS) ? TIOCM_CTS : 0) + |((control & CONTROL_DSR) ? TIOCM_DSR : 0) + |((control & CONTROL_RING)? TIOCM_RI : 0) + |((control & CONTROL_DCD) ? TIOCM_CD : 0); + + dbg("%s - control = 0x%.2x", __func__, control); + + return result; +} + +static void cp2101_break_ctl (struct tty_struct *tty, int break_state) +{ + struct usb_serial_port *port = tty->driver_data; + unsigned int state; + + dbg("%s - port %d", __func__, port->number); + if (break_state == 0) + state = BREAK_OFF; + else + state = BREAK_ON; + dbg("%s - turning break %s", __func__, + state == BREAK_OFF ? "off" : "on"); + cp2101_set_config(port, CP2101_BREAK, &state, 2); +} + +static int cp2101_startup(struct usb_serial *serial) +{ + /* CP2101 buffers behave strangely unless device is reset */ + usb_reset_device(serial->dev); + return 0; +} + +static void cp2101_shutdown(struct usb_serial *serial) +{ + int i; + + dbg("%s", __func__); + + /* Stop reads and writes on all ports */ + for (i = 0; i < serial->num_ports; ++i) + cp2101_cleanup(serial->port[i]); +} + +static int __init cp2101_init(void) +{ + int retval; + + retval = usb_serial_register(&cp2101_device); + if (retval) + return retval; /* Failed to register */ + + retval = usb_register(&cp2101_driver); + if (retval) { + /* Failed to register */ + usb_serial_deregister(&cp2101_device); + return retval; + } + + /* Success */ + printk(KERN_INFO KBUILD_MODNAME ": " DRIVER_VERSION ":" + DRIVER_DESC "\n"); + return 0; +} + +static void __exit cp2101_exit(void) +{ + usb_deregister(&cp2101_driver); + usb_serial_deregister(&cp2101_device); +} + +module_init(cp2101_init); +module_exit(cp2101_exit); + +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL"); + +module_param(debug, bool, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Enable verbose debugging messages"); -- cgit v1.2.3 From 3edb8a208b5be90c829f7b19058cb63e947b1d18 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 26 Feb 2009 23:02:19 +0000 Subject: USB: ohci-s3c2410: remove include Remove the include of , as no definitions from it are used by the OHCI driver. Signed-off-by: Ben Dooks Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-s3c2410.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index f46af7a718d..0e62d2044f7 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -22,7 +22,6 @@ #include #include -#include #include #define valid_port(idx) ((idx) == 1 || (idx) == 2) -- cgit v1.2.3 From 2dfa319a649b9de029777994b6af201c1fe81d53 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 26 Feb 2009 23:03:15 +0000 Subject: USB: ohci-s3c2410: fix name of bus clock The USB bus clock is usb-bus-host, so print the correct name in the dev_err() statement if we cannot find it. Signed-off-by: Ben Dooks Acked-by: David Brownell --- drivers/usb/host/ohci-s3c2410.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 0e62d2044f7..a7ddd5d14a5 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -371,7 +371,7 @@ static int usb_hcd_s3c2410_probe (const struct hc_driver *driver, usb_clk = clk_get(&dev->dev, "usb-bus-host"); if (IS_ERR(usb_clk)) { - dev_err(&dev->dev, "cannot get usb-host clock\n"); + dev_err(&dev->dev, "cannot get usb-bus-host clock\n"); retval = -ENOENT; goto err_clk; } -- cgit v1.2.3 From a9f8ec4db1d308643e13ec7638ccb5ace4d34982 Mon Sep 17 00:00:00 2001 From: Hannes Eder Date: Fri, 27 Feb 2009 02:04:31 +0100 Subject: USB: host: fix sparse warning: Using plain integer as NULL pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix this sparse warning:  drivers/usb/host/oxu210hp-hcd.c:2687:42: warning: Using plain integer as NULL pointer Signed-off-by: Hannes Eder Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/oxu210hp-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c index 2947c69b347..5ac489ee3da 100644 --- a/drivers/usb/host/oxu210hp-hcd.c +++ b/drivers/usb/host/oxu210hp-hcd.c @@ -2684,7 +2684,7 @@ static int oxu_reset(struct usb_hcd *hcd) oxu->urb_len = 0; /* FIMXE */ - hcd->self.controller->dma_mask = 0UL; + hcd->self.controller->dma_mask = NULL; if (oxu->is_otg) { oxu->caps = hcd->regs + OXU_OTG_CAP_OFFSET; -- cgit v1.2.3 From 3ba5f38f3d5143a879de132a9df71814d1f3cff0 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sat, 7 Mar 2009 11:44:10 +0000 Subject: USB: ohci-hcd: Add ARCH_S3C24XX to the ohci-s3c2410.c glue The ohci-s3c2410.c glue supports both CONFIG_ARCH_S3C2410 and CONFIG_ARCH_S3C64XX so add it to the build of ohci-s3c2410.c Signed-off-by: Ben Dooks Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 5cf5f1eca4f..d052955439c 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -997,7 +997,7 @@ MODULE_LICENSE ("GPL"); #define SA1111_DRIVER ohci_hcd_sa1111_driver #endif -#ifdef CONFIG_ARCH_S3C2410 +#if defined(CONFIG_ARCH_S3C2410) || defined(CONFIG_ARCH_S3C64XX) #include "ohci-s3c2410.c" #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver #endif -- cgit v1.2.3 From 49121aa14c2a372a5fd01982df900257784be63d Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sat, 7 Mar 2009 11:44:21 +0000 Subject: USB: S3C: Move usb-control.h to platform include The usb-control.h is needed by ohci-s3c2410.c for both S3C24XX and S3C64XX architectures, so move it to Signed-off-by: Ben Dooks Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/ohci-s3c2410.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index a7ddd5d14a5..a68af2dd55c 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -21,8 +21,7 @@ #include #include - -#include +#include #define valid_port(idx) ((idx) == 1 || (idx) == 2) -- cgit v1.2.3 From 1b8fb4141eb52f4aace9f152dad3e4c1609b76fe Mon Sep 17 00:00:00 2001 From: Mark Ellis Date: Mon, 9 Mar 2009 22:24:29 +0000 Subject: USB: ipaq: handle 4 endpoint devices The ipaq driver currently enforces one port on all devices. This is correct for 2 and 3 endpoint devices, but with 4 endpoint devices meaningful communication occurs on the second pair. This patch allows 2 ports for 4 endpoint devices. Signed-off-by: Mark Ellis Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/ipaq.c | 43 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 37 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index 132be74d2b8..ef92095b073 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c @@ -78,6 +78,7 @@ static int ipaq_open(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); static void ipaq_close(struct tty_struct *tty, struct usb_serial_port *port, struct file *filp); +static int ipaq_calc_num_ports(struct usb_serial *serial); static int ipaq_startup(struct usb_serial *serial); static void ipaq_shutdown(struct usb_serial *serial); static int ipaq_write(struct tty_struct *tty, struct usb_serial_port *port, @@ -572,15 +573,10 @@ static struct usb_serial_driver ipaq_device = { .description = "PocketPC PDA", .usb_driver = &ipaq_driver, .id_table = ipaq_id_table, - /* - * some devices have an extra endpoint, which - * must be ignored as it would make the core - * create a second port which oopses when used - */ - .num_ports = 1, .open = ipaq_open, .close = ipaq_close, .attach = ipaq_startup, + .calc_num_ports = ipaq_calc_num_ports, .shutdown = ipaq_shutdown, .write = ipaq_write, .write_room = ipaq_write_room, @@ -956,14 +952,49 @@ static void ipaq_destroy_lists(struct usb_serial_port *port) } +static int ipaq_calc_num_ports(struct usb_serial *serial) +{ + /* + * some devices have 3 endpoints, the 3rd of which + * must be ignored as it would make the core + * create a second port which oopses when used + */ + int ipaq_num_ports = 1; + + dbg("%s - numberofendpoints: %d", __FUNCTION__, + (int)serial->interface->cur_altsetting->desc.bNumEndpoints); + + /* + * a few devices have 4 endpoints, seemingly Yakuma devices, + * and we need the second pair, so let them have 2 ports + * + * TODO: can we drop port 1 ? + */ + if (serial->interface->cur_altsetting->desc.bNumEndpoints > 3) { + ipaq_num_ports = 2; + } + + return ipaq_num_ports; +} + + static int ipaq_startup(struct usb_serial *serial) { dbg("%s", __func__); if (serial->dev->actconfig->desc.bConfigurationValue != 1) { + /* + * FIXME: HP iPaq rx3715, possibly others, have 1 config that + * is labeled as 2 + */ + dev_err(&serial->dev->dev, "active config #%d != 1 ??\n", serial->dev->actconfig->desc.bConfigurationValue); return -ENODEV; } + + dbg("%s - iPAQ module configured for %d ports", + __FUNCTION__, serial->num_ports); + return usb_reset_configuration(serial->dev); } -- cgit v1.2.3 From d23bac9f8b3cf1ad674d6390364d559103013213 Mon Sep 17 00:00:00 2001 From: Alex Stephens Date: Tue, 17 Mar 2009 00:06:19 +0000 Subject: USB: CP2101 New Device ID One new device ID for CP2101 driver. Signed-off-by: Alex Stephens alex@miranova.com --- drivers/usb/serial/cp210x.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 2f23d064362..292f0163b92 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -87,6 +87,7 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ + { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ { USB_DEVICE(0x10C4, 0xEA60) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xEA61) }, /* Silicon Labs factory default */ { USB_DEVICE(0x10C4, 0xF001) }, /* Elan Digital Systems USBscope50 */ -- cgit v1.2.3 From d2ad67b3fa61eed52b22491210c668a94c7bf17e Mon Sep 17 00:00:00 2001 From: VomLehn Date: Thu, 12 Mar 2009 14:37:42 -0700 Subject: USB: Fix cp2101 USB serial device driver termios functions for console use This is really a follow up to the modifications Alan Cox made for commit 95da310e66ee8090119596c70ca8432e57f9a97f to pass a tty_struct to various interface functions, which broke the serial configuration (termios) functions when the device is being used as a console. These changes restore the configuration to proper functioning both as a tty and as a console. As Alan notes in that commit, these changes will need to be tweaked when we have a proper console abstraction. Signed-off-by: David VomLehn Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/cp210x.c | 53 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 43 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index 292f0163b92..e8d5133ce9c 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c @@ -38,17 +38,21 @@ static int cp2101_open(struct tty_struct *, struct usb_serial_port *, static void cp2101_cleanup(struct usb_serial_port *); static void cp2101_close(struct tty_struct *, struct usb_serial_port *, struct file*); -static void cp2101_get_termios(struct tty_struct *); +static void cp2101_get_termios(struct tty_struct *, + struct usb_serial_port *port); +static void cp2101_get_termios_port(struct usb_serial_port *port, + unsigned int *cflagp, unsigned int *baudp); static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, struct ktermios*); static int cp2101_tiocmget(struct tty_struct *, struct file *); static int cp2101_tiocmset(struct tty_struct *, struct file *, unsigned int, unsigned int); +static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *, + unsigned int, unsigned int); static void cp2101_break_ctl(struct tty_struct *, int); static int cp2101_startup(struct usb_serial *); static void cp2101_shutdown(struct usb_serial *); - static int debug; static struct usb_device_id id_table [] = { @@ -369,10 +373,12 @@ static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, } /* Configure the termios structure */ - cp2101_get_termios(tty); + cp2101_get_termios(tty, port); /* Set the DTR and RTS pins low */ - cp2101_tiocmset(tty, NULL, TIOCM_DTR | TIOCM_RTS, 0); + cp2101_tiocmset_port(tty ? (struct usb_serial_port *) tty->driver_data + : port, + NULL, TIOCM_DTR | TIOCM_RTS, 0); return 0; } @@ -414,9 +420,31 @@ static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, * from the device, corrects any unsupported values, and configures the * termios structure to reflect the state of the device */ -static void cp2101_get_termios (struct tty_struct *tty) +static void cp2101_get_termios(struct tty_struct *tty, + struct usb_serial_port *port) +{ + unsigned int baud; + + if (tty) { + cp2101_get_termios_port(tty->driver_data, + &tty->termios->c_cflag, &baud); + tty_encode_baud_rate(tty, baud, baud); + } + + else { + unsigned int cflag; + cflag = 0; + cp2101_get_termios_port(port, &cflag, &baud); + } +} + +/* + * cp2101_get_termios_port + * This is the heart of cp2101_get_termios which always uses a &usb_serial_port. + */ +static void cp2101_get_termios_port(struct usb_serial_port *port, + unsigned int *cflagp, unsigned int *baudp) { - struct usb_serial_port *port = tty->driver_data; unsigned int cflag, modem_ctl[4]; unsigned int baud; unsigned int bits; @@ -429,9 +457,9 @@ static void cp2101_get_termios (struct tty_struct *tty) baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); dbg("%s - baud rate = %d", __func__, baud); + *baudp = baud; - tty_encode_baud_rate(tty, baud, baud); - cflag = tty->termios->c_cflag; + cflag = *cflagp; cp2101_get_config(port, CP2101_BITS, &bits, 2); cflag &= ~CSIZE; @@ -537,7 +565,7 @@ static void cp2101_get_termios (struct tty_struct *tty) cflag &= ~CRTSCTS; } - tty->termios->c_cflag = cflag; + *cflagp = cflag; } static void cp2101_set_termios(struct tty_struct *tty, @@ -669,6 +697,12 @@ static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; + return cp2101_tiocmset_port(port, file, set, clear); +} + +static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *file, + unsigned int set, unsigned int clear) +{ unsigned int control = 0; dbg("%s - port %d", __func__, port->number); @@ -693,7 +727,6 @@ static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, dbg("%s - control = 0x%.4x", __func__, control); return cp2101_set_config(port, CP2101_CONTROL, &control, 2); - } static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) -- cgit v1.2.3 From 71d2718f2507dc17501d04e2bdca7b8e694ce365 Mon Sep 17 00:00:00 2001 From: Roel Kluin Date: Fri, 13 Mar 2009 12:19:18 +0100 Subject: USB: more u32 conversion after transfer_buffer_length and actual_length transfer_buffer_length and actual_length have become unsigned, therefore some additional conversion of local variables, function arguments and print specifications is desired. A test for a negative urb->transfer_buffer_length became obsolete; instead we ensure that it does not exceed INT_MAX. Also, urb->actual_length is always less than urb->transfer_buffer_length. rh_string() does no longer return -EPIPE in the case of an unsupported ID. Instead its only caller, rh_call_control() does the check. Signed-off-by: Roel Kluin Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/devio.c | 6 +++--- drivers/usb/core/hcd.c | 31 ++++++++++++------------------- drivers/usb/core/hub.c | 2 +- drivers/usb/core/message.c | 2 +- drivers/usb/core/urb.c | 2 +- 5 files changed, 18 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c index d3883f63960..df3c539f652 100644 --- a/drivers/usb/core/devio.c +++ b/drivers/usb/core/devio.c @@ -302,7 +302,7 @@ static struct async *async_getpending(struct dev_state *ps, static void snoop_urb(struct urb *urb, void __user *userurb) { - int j; + unsigned j; unsigned char *data = urb->transfer_buffer; if (!usbfs_snoop) @@ -311,9 +311,9 @@ static void snoop_urb(struct urb *urb, void __user *userurb) dev_info(&urb->dev->dev, "direction=%s\n", usb_urb_dir_in(urb) ? "IN" : "OUT"); dev_info(&urb->dev->dev, "userurb=%p\n", userurb); - dev_info(&urb->dev->dev, "transfer_buffer_length=%d\n", + dev_info(&urb->dev->dev, "transfer_buffer_length=%u\n", urb->transfer_buffer_length); - dev_info(&urb->dev->dev, "actual_length=%d\n", urb->actual_length); + dev_info(&urb->dev->dev, "actual_length=%u\n", urb->actual_length); dev_info(&urb->dev->dev, "data: "); for (j = 0; j < urb->transfer_buffer_length; ++j) printk("%02x ", data[j]); diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 0eee32a65e2..81fa8506825 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -279,9 +279,9 @@ static const u8 hs_rh_config_descriptor [] = { * helper routine for returning string descriptors in UTF-16LE * input can actually be ISO-8859-1; ASCII is its 7-bit subset */ -static int ascii2utf (char *s, u8 *utf, int utfmax) +static unsigned ascii2utf(char *s, u8 *utf, int utfmax) { - int retval; + unsigned retval; for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) { *utf++ = *s++; @@ -304,19 +304,15 @@ static int ascii2utf (char *s, u8 *utf, int utfmax) * Produces either a manufacturer, product or serial number string for the * virtual root hub device. */ -static int rh_string ( - int id, - struct usb_hcd *hcd, - u8 *data, - int len -) { +static unsigned rh_string(int id, struct usb_hcd *hcd, u8 *data, unsigned len) +{ char buf [100]; // language ids if (id == 0) { buf[0] = 4; buf[1] = 3; /* 4 bytes string data */ buf[2] = 0x09; buf[3] = 0x04; /* MSFT-speak for "en-us" */ - len = min (len, 4); + len = min_t(unsigned, len, 4); memcpy (data, buf, len); return len; @@ -332,10 +328,7 @@ static int rh_string ( } else if (id == 3) { snprintf (buf, sizeof buf, "%s %s %s", init_utsname()->sysname, init_utsname()->release, hcd->driver->description); - - // unsupported IDs --> "protocol stall" - } else - return -EPIPE; + } switch (len) { /* All cases fall through */ default: @@ -360,9 +353,8 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) u8 tbuf [sizeof (struct usb_hub_descriptor)] __attribute__((aligned(4))); const u8 *bufp = tbuf; - int len = 0; + unsigned len = 0; int status; - int n; u8 patch_wakeup = 0; u8 patch_protocol = 0; @@ -456,10 +448,11 @@ static int rh_call_control (struct usb_hcd *hcd, struct urb *urb) patch_wakeup = 1; break; case USB_DT_STRING << 8: - n = rh_string (wValue & 0xff, hcd, ubuf, wLength); - if (n < 0) + if ((wValue & 0xff) < 4) + urb->actual_length = rh_string(wValue & 0xff, + hcd, ubuf, wLength); + else /* unsupported IDs --> "protocol stall" */ goto error; - urb->actual_length = n; break; default: goto error; @@ -629,7 +622,7 @@ static int rh_queue_status (struct usb_hcd *hcd, struct urb *urb) { int retval; unsigned long flags; - int len = 1 + (urb->dev->maxchild / 8); + unsigned len = 1 + (urb->dev->maxchild / 8); spin_lock_irqsave (&hcd_root_hub_lock, flags); if (hcd->status_urb || urb->transfer_buffer_length < len) { diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 81eb3e6b659..be86ae3f408 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -392,7 +392,7 @@ static void hub_irq(struct urb *urb) { struct usb_hub *hub = urb->context; int status = urb->status; - int i; + unsigned i; unsigned long bits; switch (status) { diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 3922fa915ed..293a30d78d2 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -59,7 +59,7 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status); dev_dbg(&urb->dev->dev, - "%s timed out on ep%d%s len=%d/%d\n", + "%s timed out on ep%d%s len=%u/%u\n", current->comm, usb_endpoint_num(&urb->ep->desc), usb_urb_dir_in(urb) ? "in" : "out", diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index 7025d801f23..3376055f36e 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -370,7 +370,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags) } /* the I/O buffer must be mapped/unmapped, except when length=0 */ - if (urb->transfer_buffer_length < 0) + if (urb->transfer_buffer_length > INT_MAX) return -EMSGSIZE; #ifdef DEBUG -- cgit v1.2.3 From e1e609be49c9d345e8b67a122a7cdae48ad27c7e Mon Sep 17 00:00:00 2001 From: Yoshihiro Shimoda Date: Thu, 19 Mar 2009 14:18:15 +0900 Subject: USB: r8a66597-hcd: suspend/resume support Fix the problem that system cannot suspend. Signed-off-by: Yoshihiro Shimoda Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/r8a66597-hcd.c | 101 +++++++++++++++++++++++++++++++++++++++- drivers/usb/host/r8a66597.h | 2 + 2 files changed, 102 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c index 713f4cf0b0d..f1626e58c14 100644 --- a/drivers/usb/host/r8a66597-hcd.c +++ b/drivers/usb/host/r8a66597-hcd.c @@ -1013,6 +1013,9 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port, r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port)); r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port)); + + if (r8a66597->bus_suspended) + usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); } /* this function must be called with interrupt disabled */ @@ -1614,6 +1617,11 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) r8a66597_bclr(r8a66597, DTCHE, INTENB2); r8a66597_usb_disconnect(r8a66597, 1); } + if (mask2 & BCHG) { + r8a66597_write(r8a66597, ~BCHG, INTSTS2); + r8a66597_bclr(r8a66597, BCHGE, INTENB2); + usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); + } } if (mask1) { @@ -1629,6 +1637,12 @@ static irqreturn_t r8a66597_irq(struct usb_hcd *hcd) r8a66597_bclr(r8a66597, DTCHE, INTENB1); r8a66597_usb_disconnect(r8a66597, 0); } + if (mask1 & BCHG) { + r8a66597_write(r8a66597, ~BCHG, INTSTS1); + r8a66597_bclr(r8a66597, BCHGE, INTENB1); + usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597)); + } + if (mask1 & SIGN) { r8a66597_write(r8a66597, ~SIGN, INTSTS1); status = get_urb_error(r8a66597, 0); @@ -2140,7 +2154,7 @@ static int r8a66597_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, switch (wValue) { case USB_PORT_FEAT_ENABLE: - rh->port &= (1 << USB_PORT_FEAT_POWER); + rh->port &= ~(1 << USB_PORT_FEAT_POWER); break; case USB_PORT_FEAT_SUSPEND: break; @@ -2212,6 +2226,68 @@ error: return ret; } +#if defined(CONFIG_PM) +static int r8a66597_bus_suspend(struct usb_hcd *hcd) +{ + struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); + int port; + + dbg("%s", __func__); + + for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { + struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; + unsigned long dvstctr_reg = get_dvstctr_reg(port); + + if (!(rh->port & (1 << USB_PORT_FEAT_ENABLE))) + continue; + + dbg("suspend port = %d", port); + r8a66597_bclr(r8a66597, UACT, dvstctr_reg); /* suspend */ + rh->port |= 1 << USB_PORT_FEAT_SUSPEND; + + if (rh->dev->udev->do_remote_wakeup) { + msleep(3); /* waiting last SOF */ + r8a66597_bset(r8a66597, RWUPE, dvstctr_reg); + r8a66597_write(r8a66597, ~BCHG, get_intsts_reg(port)); + r8a66597_bset(r8a66597, BCHGE, get_intenb_reg(port)); + } + } + + r8a66597->bus_suspended = 1; + + return 0; +} + +static int r8a66597_bus_resume(struct usb_hcd *hcd) +{ + struct r8a66597 *r8a66597 = hcd_to_r8a66597(hcd); + int port; + + dbg("%s", __func__); + + for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { + struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; + unsigned long dvstctr_reg = get_dvstctr_reg(port); + + if (!(rh->port & (1 << USB_PORT_FEAT_SUSPEND))) + continue; + + dbg("resume port = %d", port); + rh->port &= ~(1 << USB_PORT_FEAT_SUSPEND); + rh->port |= 1 << USB_PORT_FEAT_C_SUSPEND; + r8a66597_mdfy(r8a66597, RESUME, RESUME | UACT, dvstctr_reg); + msleep(50); + r8a66597_mdfy(r8a66597, UACT, RESUME | UACT, dvstctr_reg); + } + + return 0; + +} +#else +#define r8a66597_bus_suspend NULL +#define r8a66597_bus_resume NULL +#endif + static struct hc_driver r8a66597_hc_driver = { .description = hcd_name, .hcd_priv_size = sizeof(struct r8a66597), @@ -2242,16 +2318,39 @@ static struct hc_driver r8a66597_hc_driver = { */ .hub_status_data = r8a66597_hub_status_data, .hub_control = r8a66597_hub_control, + .bus_suspend = r8a66597_bus_suspend, + .bus_resume = r8a66597_bus_resume, }; #if defined(CONFIG_PM) static int r8a66597_suspend(struct platform_device *pdev, pm_message_t state) { + struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); + int port; + + dbg("%s", __func__); + + disable_controller(r8a66597); + + for (port = 0; port < R8A66597_MAX_ROOT_HUB; port++) { + struct r8a66597_root_hub *rh = &r8a66597->root_hub[port]; + + rh->port = 0x00000000; + } + return 0; } static int r8a66597_resume(struct platform_device *pdev) { + struct r8a66597 *r8a66597 = dev_get_drvdata(&pdev->dev); + struct usb_hcd *hcd = r8a66597_to_hcd(r8a66597); + + dbg("%s", __func__); + + enable_controller(r8a66597); + usb_root_hub_lost_power(hcd->self.root_hub); + return 0; } #else /* if defined(CONFIG_PM) */ diff --git a/drivers/usb/host/r8a66597.h b/drivers/usb/host/r8a66597.h index ecacde4d69b..f49208f1bb7 100644 --- a/drivers/usb/host/r8a66597.h +++ b/drivers/usb/host/r8a66597.h @@ -504,6 +504,8 @@ struct r8a66597 { struct list_head child_device; unsigned long child_connect_map[4]; + + unsigned bus_suspended:1; }; static inline struct r8a66597 *hcd_to_r8a66597(struct usb_hcd *hcd) -- cgit v1.2.3 From 8942939a6c83f34615de5ae041cc9ca846923f94 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 19 Mar 2009 14:14:17 -0700 Subject: USB: gadget: composite device-level suspend/resume hooks Address one open question in the composite gadget framework: Yes, we should have device-level suspend/resume callbacks in addition to the function-level ones. We have at least one scenario (with gadget zero in OTG test mode) that's awkward to handle without it. Signed-off-by: David Brownell Cc: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/composite.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 40f1da77a00..59e85234fa0 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -1014,7 +1014,7 @@ composite_suspend(struct usb_gadget *gadget) struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; - /* REVISIT: should we have config and device level + /* REVISIT: should we have config level * suspend/resume callbacks? */ DBG(cdev, "suspend\n"); @@ -1024,6 +1024,8 @@ composite_suspend(struct usb_gadget *gadget) f->suspend(f); } } + if (composite->suspend) + composite->suspend(cdev); } static void @@ -1032,10 +1034,12 @@ composite_resume(struct usb_gadget *gadget) struct usb_composite_dev *cdev = get_gadget_data(gadget); struct usb_function *f; - /* REVISIT: should we have config and device level + /* REVISIT: should we have config level * suspend/resume callbacks? */ DBG(cdev, "resume\n"); + if (composite->resume) + composite->resume(cdev); if (cdev->config) { list_for_each_entry(f, &cdev->config->functions, list) { if (f->resume) -- cgit v1.2.3 From ab943a2e125b098489ccaa0166c2c52f8266d9ed Mon Sep 17 00:00:00 2001 From: David Brownell Date: Thu, 19 Mar 2009 14:16:09 -0700 Subject: USB: gadget: gadget zero uses new suspend/resume hooks Use the new device-level suspend/resume hooks for Gadget Zero; always enable them with the OTG test mode; and support remote wakeup on both configurations even in non-OTG mode. This ensures that both configurations can pass the USBCV remote wakeup tests when the OTG test mode is enabled. This changes behavior by adding autoresume support to the loopback config even in non-OTG mode; the test failure was that it didn't work in OTG mode. Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/f_loopback.c | 6 +++- drivers/usb/gadget/f_sourcesink.c | 52 +---------------------------- drivers/usb/gadget/g_zero.h | 4 +-- drivers/usb/gadget/zero.c | 70 ++++++++++++++++++++++++++++++++++++--- 4 files changed, 74 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/f_loopback.c b/drivers/usb/gadget/f_loopback.c index 83301bdcdd1..eb6ddfc2085 100644 --- a/drivers/usb/gadget/f_loopback.c +++ b/drivers/usb/gadget/f_loopback.c @@ -359,7 +359,7 @@ static struct usb_configuration loopback_driver = { * loopback_add - add a loopback testing configuration to a device * @cdev: the device to support the loopback configuration */ -int __init loopback_add(struct usb_composite_dev *cdev) +int __init loopback_add(struct usb_composite_dev *cdev, bool autoresume) { int id; @@ -372,6 +372,10 @@ int __init loopback_add(struct usb_composite_dev *cdev) loopback_intf.iInterface = id; loopback_driver.iConfiguration = id; + /* support autoresume for remote wakeup testing */ + if (autoresume) + sourcesink_driver.bmAttributes |= USB_CONFIG_ATT_WAKEUP; + /* support OTG systems */ if (gadget_is_otg(cdev->gadget)) { loopback_driver.descriptors = otg_desc; diff --git a/drivers/usb/gadget/f_sourcesink.c b/drivers/usb/gadget/f_sourcesink.c index 6aca5c81414..bffe91d525f 100644 --- a/drivers/usb/gadget/f_sourcesink.c +++ b/drivers/usb/gadget/f_sourcesink.c @@ -59,7 +59,6 @@ struct f_sourcesink { struct usb_ep *in_ep; struct usb_ep *out_ep; - struct timer_list resume; }; static inline struct f_sourcesink *func_to_ss(struct usb_function *f) @@ -67,10 +66,6 @@ static inline struct f_sourcesink *func_to_ss(struct usb_function *f) return container_of(f, struct f_sourcesink, function); } -static unsigned autoresume; -module_param(autoresume, uint, 0); -MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); - static unsigned pattern; module_param(pattern, uint, 0); MODULE_PARM_DESC(pattern, "0 = all zeroes, 1 = mod63 "); @@ -155,21 +150,6 @@ static struct usb_gadget_strings *sourcesink_strings[] = { /*-------------------------------------------------------------------------*/ -static void sourcesink_autoresume(unsigned long _c) -{ - struct usb_composite_dev *cdev = (void *)_c; - struct usb_gadget *g = cdev->gadget; - - /* Normally the host would be woken up for something - * more significant than just a timer firing; likely - * because of some direct user request. - */ - if (g->speed != USB_SPEED_UNKNOWN) { - int status = usb_gadget_wakeup(g); - DBG(cdev, "%s --> %d\n", __func__, status); - } -} - static int __init sourcesink_bind(struct usb_configuration *c, struct usb_function *f) { @@ -198,9 +178,6 @@ autoconf_fail: goto autoconf_fail; ss->out_ep->driver_data = cdev; /* claim */ - setup_timer(&ss->resume, sourcesink_autoresume, - (unsigned long) c->cdev); - /* support high speed hardware */ if (gadget_is_dualspeed(c->cdev->gadget)) { hs_source_desc.bEndpointAddress = @@ -359,7 +336,6 @@ static void disable_source_sink(struct f_sourcesink *ss) cdev = ss->function.config->cdev; disable_endpoints(cdev, ss->in_ep, ss->out_ep); - del_timer(&ss->resume); VDBG(cdev, "%s disabled\n", ss->function.name); } @@ -426,30 +402,6 @@ static void sourcesink_disable(struct usb_function *f) disable_source_sink(ss); } -static void sourcesink_suspend(struct usb_function *f) -{ - struct f_sourcesink *ss = func_to_ss(f); - struct usb_composite_dev *cdev = f->config->cdev; - - if (cdev->gadget->speed == USB_SPEED_UNKNOWN) - return; - - if (autoresume) { - mod_timer(&ss->resume, jiffies + (HZ * autoresume)); - DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume); - } else - DBG(cdev, "%s\n", __func__); -} - -static void sourcesink_resume(struct usb_function *f) -{ - struct f_sourcesink *ss = func_to_ss(f); - struct usb_composite_dev *cdev = f->config->cdev; - - DBG(cdev, "%s\n", __func__); - del_timer(&ss->resume); -} - /*-------------------------------------------------------------------------*/ static int __init sourcesink_bind_config(struct usb_configuration *c) @@ -467,8 +419,6 @@ static int __init sourcesink_bind_config(struct usb_configuration *c) ss->function.unbind = sourcesink_unbind; ss->function.set_alt = sourcesink_set_alt; ss->function.disable = sourcesink_disable; - ss->function.suspend = sourcesink_suspend; - ss->function.resume = sourcesink_resume; status = usb_add_function(c, &ss->function); if (status) @@ -559,7 +509,7 @@ static struct usb_configuration sourcesink_driver = { * sourcesink_add - add a source/sink testing configuration to a device * @cdev: the device to support the configuration */ -int __init sourcesink_add(struct usb_composite_dev *cdev) +int __init sourcesink_add(struct usb_composite_dev *cdev, bool autoresume) { int id; diff --git a/drivers/usb/gadget/g_zero.h b/drivers/usb/gadget/g_zero.h index dd2f16ad5a8..e84b3c47ed3 100644 --- a/drivers/usb/gadget/g_zero.h +++ b/drivers/usb/gadget/g_zero.h @@ -19,7 +19,7 @@ void disable_endpoints(struct usb_composite_dev *cdev, struct usb_ep *in, struct usb_ep *out); /* configuration-specific linkup */ -int sourcesink_add(struct usb_composite_dev *cdev); -int loopback_add(struct usb_composite_dev *cdev); +int sourcesink_add(struct usb_composite_dev *cdev, bool autoresume); +int loopback_add(struct usb_composite_dev *cdev, bool autoresume); #endif /* __G_ZERO_H */ diff --git a/drivers/usb/gadget/zero.c b/drivers/usb/gadget/zero.c index 20614dce8db..2d772401b7a 100644 --- a/drivers/usb/gadget/zero.c +++ b/drivers/usb/gadget/zero.c @@ -102,11 +102,21 @@ module_param(loopdefault, bool, S_IRUGO|S_IWUSR); #ifndef CONFIG_USB_ZERO_HNPTEST #define DRIVER_VENDOR_NUM 0x0525 /* NetChip */ #define DRIVER_PRODUCT_NUM 0xa4a0 /* Linux-USB "Gadget Zero" */ +#define DEFAULT_AUTORESUME 0 #else #define DRIVER_VENDOR_NUM 0x1a0a /* OTG test device IDs */ #define DRIVER_PRODUCT_NUM 0xbadd +#define DEFAULT_AUTORESUME 5 #endif +/* If the optional "autoresume" mode is enabled, it provides good + * functional coverage for the "USBCV" test harness from USB-IF. + * It's always set if OTG mode is enabled. + */ +unsigned autoresume = DEFAULT_AUTORESUME; +module_param(autoresume, uint, S_IRUGO); +MODULE_PARM_DESC(autoresume, "zero, or seconds before remote wakeup"); + /*-------------------------------------------------------------------------*/ static struct usb_device_descriptor device_desc = { @@ -212,6 +222,47 @@ void disable_endpoints(struct usb_composite_dev *cdev, /*-------------------------------------------------------------------------*/ +static struct timer_list autoresume_timer; + +static void zero_autoresume(unsigned long _c) +{ + struct usb_composite_dev *cdev = (void *)_c; + struct usb_gadget *g = cdev->gadget; + + /* unconfigured devices can't issue wakeups */ + if (!cdev->config) + return; + + /* Normally the host would be woken up for something + * more significant than just a timer firing; likely + * because of some direct user request. + */ + if (g->speed != USB_SPEED_UNKNOWN) { + int status = usb_gadget_wakeup(g); + INFO(cdev, "%s --> %d\n", __func__, status); + } +} + +static void zero_suspend(struct usb_composite_dev *cdev) +{ + if (cdev->gadget->speed == USB_SPEED_UNKNOWN) + return; + + if (autoresume) { + mod_timer(&autoresume_timer, jiffies + (HZ * autoresume)); + DBG(cdev, "suspend, wakeup in %d seconds\n", autoresume); + } else + DBG(cdev, "%s\n", __func__); +} + +static void zero_resume(struct usb_composite_dev *cdev) +{ + DBG(cdev, "%s\n", __func__); + del_timer(&autoresume_timer); +} + +/*-------------------------------------------------------------------------*/ + static int __init zero_bind(struct usb_composite_dev *cdev) { int gcnum; @@ -239,17 +290,19 @@ static int __init zero_bind(struct usb_composite_dev *cdev) strings_dev[STRING_SERIAL_IDX].id = id; device_desc.iSerialNumber = id; + setup_timer(&autoresume_timer, zero_autoresume, (unsigned long) cdev); + /* Register primary, then secondary configuration. Note that * SH3 only allows one config... */ if (loopdefault) { - loopback_add(cdev); + loopback_add(cdev, autoresume != 0); if (!gadget_is_sh(gadget)) - sourcesink_add(cdev); + sourcesink_add(cdev, autoresume != 0); } else { - sourcesink_add(cdev); + sourcesink_add(cdev, autoresume != 0); if (!gadget_is_sh(gadget)) - loopback_add(cdev); + loopback_add(cdev, autoresume != 0); } gcnum = usb_gadget_controller_number(gadget); @@ -278,11 +331,20 @@ static int __init zero_bind(struct usb_composite_dev *cdev) return 0; } +static int zero_unbind(struct usb_composite_dev *cdev) +{ + del_timer_sync(&autoresume_timer); + return 0; +} + static struct usb_composite_driver zero_driver = { .name = "zero", .dev = &device_desc, .strings = dev_strings, .bind = zero_bind, + .unbind = zero_unbind, + .suspend = zero_suspend, + .resume = zero_resume, }; MODULE_AUTHOR("David Brownell"); -- cgit v1.2.3 From 4c24b6d045a9d355c95ca4e6beb10ce2fd263390 Mon Sep 17 00:00:00 2001 From: Vernon Sauder Date: Fri, 20 Mar 2009 01:44:50 -0700 Subject: USB: pxa27x_udc: typo fixes and code cleanups This patch is a merge of patches : - fix function doc and debug - cleanup loop count - optimize code to remove local variable and extra check - init 'req' before use - add missing iounmap call [dbrownell@users.sourceforge.net: capitalize IN/OUT directions in doc] Signed-off-by: Vernon Sauder [folded by Robert Jarzmik Signed-off-by: Robert Jarzmik Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 54 ++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index 91ba1e93947..8cc676ecbb2 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -748,13 +748,13 @@ static void req_done(struct pxa_ep *ep, struct pxa27x_request *req, int status) } /** - * ep_end_out_req - Ends control endpoint in request + * ep_end_out_req - Ends endpoint OUT request * @ep: physical endpoint * @req: pxa request * * Context: ep->lock held * - * Ends endpoint in request (completes usb request). + * Ends endpoint OUT request (completes usb request). */ static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) { @@ -763,13 +763,13 @@ static void ep_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) } /** - * ep0_end_out_req - Ends control endpoint in request (ends data stage) + * ep0_end_out_req - Ends control endpoint OUT request (ends data stage) * @ep: physical endpoint * @req: pxa request * * Context: ep->lock held * - * Ends control endpoint in request (completes usb request), and puts + * Ends control endpoint OUT request (completes usb request), and puts * control endpoint into idle state */ static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) @@ -780,13 +780,13 @@ static void ep0_end_out_req(struct pxa_ep *ep, struct pxa27x_request *req) } /** - * ep_end_in_req - Ends endpoint out request + * ep_end_in_req - Ends endpoint IN request * @ep: physical endpoint * @req: pxa request * * Context: ep->lock held * - * Ends endpoint out request (completes usb request). + * Ends endpoint IN request (completes usb request). */ static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) { @@ -795,20 +795,18 @@ static void ep_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) } /** - * ep0_end_in_req - Ends control endpoint out request (ends data stage) + * ep0_end_in_req - Ends control endpoint IN request (ends data stage) * @ep: physical endpoint * @req: pxa request * * Context: ep->lock held * - * Ends control endpoint out request (completes usb request), and puts + * Ends control endpoint IN request (completes usb request), and puts * control endpoint into status state */ static void ep0_end_in_req(struct pxa_ep *ep, struct pxa27x_request *req) { - struct pxa_udc *udc = ep->dev; - - set_ep0state(udc, IN_STATUS_STAGE); + set_ep0state(ep->dev, IN_STATUS_STAGE); ep_end_in_req(ep, req); } @@ -1168,7 +1166,7 @@ static int pxa_ep_queue(struct usb_ep *_ep, struct usb_request *_req, ep_end_in_req(ep, req); } else { ep_err(ep, "got a request of %d bytes while" - "in state WATI_ACK_SET_CONF_INTERF\n", + "in state WAIT_ACK_SET_CONF_INTERF\n", length); ep_del_request(ep, req); rc = -EL2HLT; @@ -1214,30 +1212,26 @@ static int pxa_ep_dequeue(struct usb_ep *_ep, struct usb_request *_req) struct udc_usb_ep *udc_usb_ep; struct pxa27x_request *req; unsigned long flags; - int rc; + int rc = -EINVAL; if (!_ep) - return -EINVAL; + return rc; udc_usb_ep = container_of(_ep, struct udc_usb_ep, usb_ep); ep = udc_usb_ep->pxa_ep; if (!ep || is_ep0(ep)) - return -EINVAL; + return rc; spin_lock_irqsave(&ep->lock, flags); /* make sure it's actually queued on this endpoint */ list_for_each_entry(req, &ep->queue, queue) { - if (&req->req == _req) + if (&req->req == _req) { + req_done(ep, req, -ECONNRESET); + rc = 0; break; + } } - rc = -EINVAL; - if (&req->req != _req) - goto out; - - rc = 0; - req_done(ep, req, -ECONNRESET); -out: spin_unlock_irqrestore(&ep->lock, flags); return rc; } @@ -1706,10 +1700,9 @@ static __init void udc_init_data(struct pxa_udc *dev) } /* USB endpoints init */ - for (i = 0; i < NR_USB_ENDPOINTS; i++) - if (i != 0) - list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list, - &dev->gadget.ep_list); + for (i = 1; i < NR_USB_ENDPOINTS; i++) + list_add_tail(&dev->udc_usb_ep[i].usb_ep.ep_list, + &dev->gadget.ep_list); } /** @@ -1994,14 +1987,14 @@ static void handle_ep0(struct pxa_udc *udc, int fifo_irq, int opc_irq) struct pxa27x_request *req = NULL; int completed = 0; + if (!list_empty(&ep->queue)) + req = list_entry(ep->queue.next, struct pxa27x_request, queue); + udccsr0 = udc_ep_readl(ep, UDCCSR); ep_dbg(ep, "state=%s, req=%p, udccsr0=0x%03x, udcbcr=%d, irq_msk=%x\n", EP0_STNAME(udc), req, udccsr0, udc_ep_readl(ep, UDCBCR), (fifo_irq << 1 | opc_irq)); - if (!list_empty(&ep->queue)) - req = list_entry(ep->queue.next, struct pxa27x_request, queue); - if (udccsr0 & UDCCSR0_SST) { ep_dbg(ep, "clearing stall status\n"); nuke(ep, -EPIPE); @@ -2473,6 +2466,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) platform_set_drvdata(_dev, NULL); the_controller = NULL; clk_put(udc->clk); + iounmap(udc->regs); return 0; } -- cgit v1.2.3 From b7af0bb26899bb47ae16fb41d2296111b0784a56 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Fri, 20 Mar 2009 19:58:57 +0100 Subject: USB: allow malformed LANGID descriptors When an USB hardware does not provide a valid LANGID, fall back to value zero which is still a reasonable default for most devices. Signed-off-by: Daniel Mack Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/message.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index 293a30d78d2..30a0690f368 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -804,18 +804,16 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) dev_err(&dev->dev, "string descriptor 0 read error: %d\n", err); - goto errout; } else if (err < 4) { dev_err(&dev->dev, "string descriptor 0 too short\n"); - err = -EINVAL; - goto errout; } else { - dev->have_langid = 1; dev->string_langid = tbuf[2] | (tbuf[3] << 8); /* always use the first langid listed */ dev_dbg(&dev->dev, "default language 0x%04x\n", dev->string_langid); } + + dev->have_langid = 1; } err = usb_string_sub(dev, dev->string_langid, index, tbuf); -- cgit v1.2.3 From e6bdfe36e52f0e552b50acf49a82851eeb122fde Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Mon, 23 Mar 2009 12:38:16 +0000 Subject: USB: isp1760: Add a delay before reading the SKIPMAP registers in isp1760-hcd.c The data read from the SKIPMAP registers is not immediately available after writing and the driver panics when a packet is enqueued from the interrupt handler. This patch adds an ndelay(195) before these registers are read (delay value mentioned in section 15.1.1.3 of the ISP1760 data sheet). Signed-off-by: Catalin Marinas Acked-by: Sebastian Andrzej Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index 3172c0fd2a6..cd07ea3f0c6 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -819,6 +819,13 @@ static void enqueue_an_ATL_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, u32 atl_regs, payload; u32 buffstatus; + /* + * When this function is called from the interrupt handler to enqueue + * a follow-up packet, the SKIP register gets written and read back + * almost immediately. With ISP1761, this register requires a delay of + * 195ns between a write and subsequent read (see section 15.1.1.3). + */ + ndelay(195); skip_map = isp1760_readl(hcd->regs + HC_ATL_PTD_SKIPMAP_REG); BUG_ON(!skip_map); @@ -853,6 +860,13 @@ static void enqueue_an_INT_packet(struct usb_hcd *hcd, struct isp1760_qh *qh, u32 int_regs, payload; u32 buffstatus; + /* + * When this function is called from the interrupt handler to enqueue + * a follow-up packet, the SKIP register gets written and read back + * almost immediately. With ISP1761, this register requires a delay of + * 195ns between a write and subsequent read (see section 15.1.1.3). + */ + ndelay(195); skip_map = isp1760_readl(hcd->regs + HC_INT_PTD_SKIPMAP_REG); BUG_ON(!skip_map); -- cgit v1.2.3 From fd8345f8dea93691b0ceba55146088d8c05415f6 Mon Sep 17 00:00:00 2001 From: Alexander Shumakovitch Date: Sat, 21 Mar 2009 00:50:16 -0400 Subject: USB: qcserial: add device id for HP devices Signed-off-by: Greg Kroah-Hartman --- drivers/usb/serial/qcserial.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 6c6add50fea..e6d6b0c17fd 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c @@ -24,6 +24,8 @@ static int debug; static struct usb_device_id id_table[] = { {USB_DEVICE(0x05c6, 0x9211)}, /* Acer Gobi QDL device */ {USB_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ + {USB_DEVICE(0x03f0, 0x1f1d)}, /* HP un2400 Gobi Modem Device */ + {USB_DEVICE(0x03f0, 0x201d)}, /* HP un2400 Gobi QDL Device */ { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, id_table); -- cgit v1.2.3 From 031d5518591006efd13a33a86909b9477b22917b Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: edac: struct device - replace bus_id with dev_name(), dev_set_name() Cc: dougthompson@xmission.com Cc: bluesmoke-devel@lists.sourceforge.net Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/edac/cell_edac.c | 2 +- drivers/edac/mpc85xx_edac.c | 2 +- drivers/edac/mv64x60_edac.c | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c index 24f3ca85152..cb0f639f049 100644 --- a/drivers/edac/cell_edac.c +++ b/drivers/edac/cell_edac.c @@ -198,7 +198,7 @@ static int __devinit cell_edac_probe(struct platform_device *pdev) mci->edac_cap = EDAC_FLAG_EC | EDAC_FLAG_SECDED; mci->mod_name = "cell_edac"; mci->ctl_name = "MIC"; - mci->dev_name = pdev->dev.bus_id; + mci->dev_name = dev_name(&pdev->dev); mci->edac_check = cell_edac_check; cell_edac_init_csrows(mci); diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 853ef37ec00..4637a4a757d 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -218,7 +218,7 @@ static int __devinit mpc85xx_pci_err_probe(struct of_device *op, pci->dev = &op->dev; pci->mod_name = EDAC_MOD_STR; pci->ctl_name = pdata->name; - pci->dev_name = op->dev.bus_id; + pci->dev_name = dev_name(&op->dev); if (edac_op_state == EDAC_OPSTATE_POLL) pci->edac_check = mpc85xx_pci_check; diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 083ce8d0c63..5131aaae8e0 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c @@ -121,7 +121,7 @@ static int __devinit mv64x60_pci_err_probe(struct platform_device *pdev) pdata->irq = NO_IRQ; platform_set_drvdata(pdev, pci); pci->dev = &pdev->dev; - pci->dev_name = pdev->dev.bus_id; + pci->dev_name = dev_name(&pdev->dev); pci->mod_name = EDAC_MOD_STR; pci->ctl_name = pdata->name; @@ -294,7 +294,7 @@ static int __devinit mv64x60_sram_err_probe(struct platform_device *pdev) pdata->irq = NO_IRQ; edac_dev->dev = &pdev->dev; platform_set_drvdata(pdev, edac_dev); - edac_dev->dev_name = pdev->dev.bus_id; + edac_dev->dev_name = dev_name(&pdev->dev); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { @@ -462,7 +462,7 @@ static int __devinit mv64x60_cpu_err_probe(struct platform_device *pdev) pdata->irq = NO_IRQ; edac_dev->dev = &pdev->dev; platform_set_drvdata(pdev, edac_dev); - edac_dev->dev_name = pdev->dev.bus_id; + edac_dev->dev_name = dev_name(&pdev->dev); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r) { @@ -713,7 +713,7 @@ static int __devinit mv64x60_mc_err_probe(struct platform_device *pdev) platform_set_drvdata(pdev, mci); pdata->name = "mv64x60_mc_err"; pdata->irq = NO_IRQ; - mci->dev_name = pdev->dev.bus_id; + mci->dev_name = dev_name(&pdev->dev); pdata->edac_idx = edac_mc_idx++; r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -- cgit v1.2.3 From 6c7377ab6814c247d7600955a4ead2e3db490697 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: spi: struct device - replace bus_id with dev_name(), dev_set_name() Cc: dbrownell@users.sourceforge.net Cc: spi-devel-general@lists.sourceforge.net Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/spi/atmel_spi.c | 8 ++++---- drivers/spi/mpc52xx_psc_spi.c | 2 +- drivers/spi/omap2_mcspi.c | 2 +- drivers/spi/omap_uwire.c | 12 ++++++------ drivers/spi/orion_spi.c | 2 +- drivers/spi/pxa2xx_spi.c | 4 ++-- drivers/spi/spi_bfin5xx.c | 4 ++-- drivers/spi/spi_gpio.c | 2 +- drivers/spi/spi_imx.c | 5 +++-- drivers/spi/spi_mpc83xx.c | 4 ++-- drivers/spi/spi_txx9.c | 3 ++- 11 files changed, 25 insertions(+), 23 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 56ff3e6864e..12e443cc4ac 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -322,7 +322,7 @@ static void atmel_spi_next_message(struct spi_master *master) spi = msg->spi; dev_dbg(master->dev.parent, "start message %p for %s\n", - msg, spi->dev.bus_id); + msg, dev_name(&spi->dev)); /* select chip if it's not still active */ if (as->stay) { @@ -627,7 +627,7 @@ static int atmel_spi_setup(struct spi_device *spi) if (!asd) return -ENOMEM; - ret = gpio_request(npcs_pin, spi->dev.bus_id); + ret = gpio_request(npcs_pin, dev_name(&spi->dev)); if (ret) { kfree(asd); return ret; @@ -668,7 +668,7 @@ static int atmel_spi_transfer(struct spi_device *spi, struct spi_message *msg) as = spi_master_get_devdata(spi->master); dev_dbg(controller, "new message %p submitted for %s\n", - msg, spi->dev.bus_id); + msg, dev_name(&spi->dev)); if (unlikely(list_empty(&msg->transfers))) return -EINVAL; @@ -803,7 +803,7 @@ static int __init atmel_spi_probe(struct platform_device *pdev) as->clk = clk; ret = request_irq(irq, atmel_spi_interrupt, 0, - pdev->dev.bus_id, master); + dev_name(&pdev->dev), master); if (ret) goto out_unmap_regs; diff --git a/drivers/spi/mpc52xx_psc_spi.c b/drivers/spi/mpc52xx_psc_spi.c index 3b97803e1d1..68c77a91159 100644 --- a/drivers/spi/mpc52xx_psc_spi.c +++ b/drivers/spi/mpc52xx_psc_spi.c @@ -429,7 +429,7 @@ static int __init mpc52xx_psc_spi_do_probe(struct device *dev, u32 regaddr, INIT_LIST_HEAD(&mps->queue); mps->workqueue = create_singlethread_workqueue( - master->dev.parent->bus_id); + dev_name(master->dev.parent)); if (mps->workqueue == NULL) { ret = -EBUSY; goto free_irq; diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c index 454a2712e62..1c65e380c84 100644 --- a/drivers/spi/omap2_mcspi.c +++ b/drivers/spi/omap2_mcspi.c @@ -1003,7 +1003,7 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) goto err1; } if (!request_mem_region(r->start, (r->end - r->start) + 1, - pdev->dev.bus_id)) { + dev_name(&pdev->dev))) { status = -EBUSY; goto err1; } diff --git a/drivers/spi/omap_uwire.c b/drivers/spi/omap_uwire.c index bab6ff061e9..60b5381c65c 100644 --- a/drivers/spi/omap_uwire.c +++ b/drivers/spi/omap_uwire.c @@ -245,7 +245,7 @@ static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t) #ifdef VERBOSE pr_debug("%s: write-%d =%04x\n", - spi->dev.bus_id, bits, val); + dev_name(&spi->dev), bits, val); #endif if (wait_uwire_csr_flag(CSRB, 0, 0)) goto eio; @@ -305,7 +305,7 @@ static int uwire_txrx(struct spi_device *spi, struct spi_transfer *t) status += bytes; #ifdef VERBOSE pr_debug("%s: read-%d =%04x\n", - spi->dev.bus_id, bits, val); + dev_name(&spi->dev), bits, val); #endif } @@ -331,7 +331,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) uwire = spi_master_get_devdata(spi->master); if (spi->chip_select > 3) { - pr_debug("%s: cs%d?\n", spi->dev.bus_id, spi->chip_select); + pr_debug("%s: cs%d?\n", dev_name(&spi->dev), spi->chip_select); status = -ENODEV; goto done; } @@ -343,7 +343,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) bits = 8; if (bits > 16) { - pr_debug("%s: wordsize %d?\n", spi->dev.bus_id, bits); + pr_debug("%s: wordsize %d?\n", dev_name(&spi->dev), bits); status = -ENODEV; goto done; } @@ -378,7 +378,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) hz = t->speed_hz; if (!hz) { - pr_debug("%s: zero speed?\n", spi->dev.bus_id); + pr_debug("%s: zero speed?\n", dev_name(&spi->dev)); status = -EINVAL; goto done; } @@ -406,7 +406,7 @@ static int uwire_setup_transfer(struct spi_device *spi, struct spi_transfer *t) } if (div1_idx == 4) { pr_debug("%s: lowest clock %ld, need %d\n", - spi->dev.bus_id, rate / 10 / 8, hz); + dev_name(&spi->dev), rate / 10 / 8, hz); status = -EDOM; goto done; } diff --git a/drivers/spi/orion_spi.c b/drivers/spi/orion_spi.c index 014becb7d53..c8b0babdc2a 100644 --- a/drivers/spi/orion_spi.c +++ b/drivers/spi/orion_spi.c @@ -496,7 +496,7 @@ static int __init orion_spi_probe(struct platform_device *pdev) } if (!request_mem_region(r->start, (r->end - r->start) + 1, - pdev->dev.bus_id)) { + dev_name(&pdev->dev))) { status = -EBUSY; goto out; } diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index d0fc4ca2f65..ec24f2d16f3 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c @@ -1333,7 +1333,7 @@ static int __init init_queue(struct driver_data *drv_data) INIT_WORK(&drv_data->pump_messages, pump_messages); drv_data->workqueue = create_singlethread_workqueue( - drv_data->master->dev.parent->bus_id); + dev_name(drv_data->master->dev.parent)); if (drv_data->workqueue == NULL) return -EBUSY; @@ -1462,7 +1462,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR; } - status = request_irq(ssp->irq, ssp_int, 0, dev->bus_id, drv_data); + status = request_irq(ssp->irq, ssp_int, 0, dev_name(dev), drv_data); if (status < 0) { dev_err(&pdev->dev, "cannot get IRQ %d\n", ssp->irq); goto out_error_master_alloc; diff --git a/drivers/spi/spi_bfin5xx.c b/drivers/spi/spi_bfin5xx.c index 7fea3cf4588..3410b0c55ed 100644 --- a/drivers/spi/spi_bfin5xx.c +++ b/drivers/spi/spi_bfin5xx.c @@ -1160,8 +1160,8 @@ static inline int init_queue(struct driver_data *drv_data) /* init messages workqueue */ INIT_WORK(&drv_data->pump_messages, pump_messages); - drv_data->workqueue = - create_singlethread_workqueue(drv_data->master->dev.parent->bus_id); + drv_data->workqueue = create_singlethread_workqueue( + dev_name(drv_data->master->dev.parent)); if (drv_data->workqueue == NULL) return -EBUSY; diff --git a/drivers/spi/spi_gpio.c b/drivers/spi/spi_gpio.c index f5ed9721aab..d2866c293de 100644 --- a/drivers/spi/spi_gpio.c +++ b/drivers/spi/spi_gpio.c @@ -191,7 +191,7 @@ static int spi_gpio_setup(struct spi_device *spi) return -EINVAL; if (!spi->controller_state) { - status = gpio_request(cs, spi->dev.bus_id); + status = gpio_request(cs, dev_name(&spi->dev)); if (status) return status; status = gpio_direction_output(cs, spi->mode & SPI_CS_HIGH); diff --git a/drivers/spi/spi_imx.c b/drivers/spi/spi_imx.c index 269a55ec52e..0480d8bb19d 100644 --- a/drivers/spi/spi_imx.c +++ b/drivers/spi/spi_imx.c @@ -1381,7 +1381,7 @@ static int __init init_queue(struct driver_data *drv_data) INIT_WORK(&drv_data->work, pump_messages); drv_data->workqueue = create_singlethread_workqueue( - drv_data->master->dev.parent->bus_id); + dev_name(drv_data->master->dev.parent)); if (drv_data->workqueue == NULL) return -EBUSY; @@ -1525,7 +1525,8 @@ static int __init spi_imx_probe(struct platform_device *pdev) status = -ENODEV; goto err_no_irqres; } - status = request_irq(irq, spi_int, IRQF_DISABLED, dev->bus_id, drv_data); + status = request_irq(irq, spi_int, IRQF_DISABLED, + dev_name(dev), drv_data); if (status < 0) { dev_err(&pdev->dev, "probe - cannot get IRQ (%d)\n", status); goto err_no_irqres; diff --git a/drivers/spi/spi_mpc83xx.c b/drivers/spi/spi_mpc83xx.c index ac0e3e4b3c5..44a2b46ccb7 100644 --- a/drivers/spi/spi_mpc83xx.c +++ b/drivers/spi/spi_mpc83xx.c @@ -637,7 +637,7 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) INIT_LIST_HEAD(&mpc83xx_spi->queue); mpc83xx_spi->workqueue = create_singlethread_workqueue( - master->dev.parent->bus_id); + dev_name(master->dev.parent)); if (mpc83xx_spi->workqueue == NULL) { ret = -EBUSY; goto free_irq; @@ -649,7 +649,7 @@ static int __init mpc83xx_spi_probe(struct platform_device *dev) printk(KERN_INFO "%s: MPC83xx SPI Controller driver at 0x%p (irq = %d)\n", - dev->dev.bus_id, mpc83xx_spi->base, mpc83xx_spi->irq); + dev_name(&dev->dev), mpc83xx_spi->base, mpc83xx_spi->irq); return ret; diff --git a/drivers/spi/spi_txx9.c b/drivers/spi/spi_txx9.c index 2296f37ea3c..29cbb065618 100644 --- a/drivers/spi/spi_txx9.c +++ b/drivers/spi/spi_txx9.c @@ -404,7 +404,8 @@ static int __init txx9spi_probe(struct platform_device *dev) if (ret) goto exit; - c->workqueue = create_singlethread_workqueue(master->dev.parent->bus_id); + c->workqueue = create_singlethread_workqueue( + dev_name(master->dev.parent)); if (!c->workqueue) goto exit_busy; c->last_chipselect = -1; -- cgit v1.2.3 From 7ad33e74857f16f1202cbc5746faf52e88e8b376 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: video: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/video/pmag-ba-fb.c | 17 +++++++++-------- drivers/video/pmagb-b-fb.c | 17 +++++++++-------- drivers/video/ps3fb.c | 2 +- drivers/video/sh_mobile_lcdcfb.c | 2 +- drivers/video/tmiofb.c | 2 +- 5 files changed, 21 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/video/pmag-ba-fb.c b/drivers/video/pmag-ba-fb.c index 3a3f80f6521..0573ec685a5 100644 --- a/drivers/video/pmag-ba-fb.c +++ b/drivers/video/pmag-ba-fb.c @@ -151,7 +151,7 @@ static int __init pmagbafb_probe(struct device *dev) info = framebuffer_alloc(sizeof(struct pmagbafb_par), dev); if (!info) { - printk(KERN_ERR "%s: Cannot allocate memory\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev)); return -ENOMEM; } @@ -160,7 +160,7 @@ static int __init pmagbafb_probe(struct device *dev) if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { printk(KERN_ERR "%s: Cannot allocate color map\n", - dev->bus_id); + dev_name(dev)); err = -ENOMEM; goto err_alloc; } @@ -173,8 +173,9 @@ static int __init pmagbafb_probe(struct device *dev) /* Request the I/O MEM resource. */ start = tdev->resource.start; len = tdev->resource.end - start + 1; - if (!request_mem_region(start, len, dev->bus_id)) { - printk(KERN_ERR "%s: Cannot reserve FB region\n", dev->bus_id); + if (!request_mem_region(start, len, dev_name(dev))) { + printk(KERN_ERR "%s: Cannot reserve FB region\n", + dev_name(dev)); err = -EBUSY; goto err_cmap; } @@ -183,7 +184,7 @@ static int __init pmagbafb_probe(struct device *dev) info->fix.mmio_start = start; par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); if (!par->mmio) { - printk(KERN_ERR "%s: Cannot map MMIO\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev)); err = -ENOMEM; goto err_resource; } @@ -194,7 +195,7 @@ static int __init pmagbafb_probe(struct device *dev) info->screen_base = ioremap_nocache(info->fix.smem_start, info->fix.smem_len); if (!info->screen_base) { - printk(KERN_ERR "%s: Cannot map FB\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev)); err = -ENOMEM; goto err_mmio_map; } @@ -205,14 +206,14 @@ static int __init pmagbafb_probe(struct device *dev) err = register_framebuffer(info); if (err < 0) { printk(KERN_ERR "%s: Cannot register framebuffer\n", - dev->bus_id); + dev_name(dev)); goto err_smem_map; } get_device(dev); pr_info("fb%d: %s frame buffer device at %s\n", - info->node, info->fix.id, dev->bus_id); + info->node, info->fix.id, dev_name(dev)); return 0; diff --git a/drivers/video/pmagb-b-fb.c b/drivers/video/pmagb-b-fb.c index 9b80597241b..98748723af9 100644 --- a/drivers/video/pmagb-b-fb.c +++ b/drivers/video/pmagb-b-fb.c @@ -258,7 +258,7 @@ static int __init pmagbbfb_probe(struct device *dev) info = framebuffer_alloc(sizeof(struct pmagbbfb_par), dev); if (!info) { - printk(KERN_ERR "%s: Cannot allocate memory\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot allocate memory\n", dev_name(dev)); return -ENOMEM; } @@ -267,7 +267,7 @@ static int __init pmagbbfb_probe(struct device *dev) if (fb_alloc_cmap(&info->cmap, 256, 0) < 0) { printk(KERN_ERR "%s: Cannot allocate color map\n", - dev->bus_id); + dev_name(dev)); err = -ENOMEM; goto err_alloc; } @@ -280,8 +280,9 @@ static int __init pmagbbfb_probe(struct device *dev) /* Request the I/O MEM resource. */ start = tdev->resource.start; len = tdev->resource.end - start + 1; - if (!request_mem_region(start, len, dev->bus_id)) { - printk(KERN_ERR "%s: Cannot reserve FB region\n", dev->bus_id); + if (!request_mem_region(start, len, dev_name(dev))) { + printk(KERN_ERR "%s: Cannot reserve FB region\n", + dev_name(dev)); err = -EBUSY; goto err_cmap; } @@ -290,7 +291,7 @@ static int __init pmagbbfb_probe(struct device *dev) info->fix.mmio_start = start; par->mmio = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); if (!par->mmio) { - printk(KERN_ERR "%s: Cannot map MMIO\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot map MMIO\n", dev_name(dev)); err = -ENOMEM; goto err_resource; } @@ -301,7 +302,7 @@ static int __init pmagbbfb_probe(struct device *dev) info->fix.smem_start = start + PMAGB_B_FBMEM; par->smem = ioremap_nocache(info->fix.smem_start, info->fix.smem_len); if (!par->smem) { - printk(KERN_ERR "%s: Cannot map FB\n", dev->bus_id); + printk(KERN_ERR "%s: Cannot map FB\n", dev_name(dev)); err = -ENOMEM; goto err_mmio_map; } @@ -316,7 +317,7 @@ static int __init pmagbbfb_probe(struct device *dev) err = register_framebuffer(info); if (err < 0) { printk(KERN_ERR "%s: Cannot register framebuffer\n", - dev->bus_id); + dev_name(dev)); goto err_smem_map; } @@ -328,7 +329,7 @@ static int __init pmagbbfb_probe(struct device *dev) par->osc1 / 1000, par->osc1 % 1000); pr_info("fb%d: %s frame buffer device at %s\n", - info->node, info->fix.id, dev->bus_id); + info->node, info->fix.id, dev_name(dev)); pr_info("fb%d: Osc0: %s, Osc1: %s, Osc%u selected\n", info->node, freq0, par->osc1 ? freq1 : "disabled", par->osc1 != 0); diff --git a/drivers/video/ps3fb.c b/drivers/video/ps3fb.c index 87f826e4c95..e00c1dff55d 100644 --- a/drivers/video/ps3fb.c +++ b/drivers/video/ps3fb.c @@ -1213,7 +1213,7 @@ static int __devinit ps3fb_probe(struct ps3_system_bus_device *dev) dev->core.driver_data = info; dev_info(info->device, "%s %s, using %u KiB of video memory\n", - dev_driver_string(info->dev), info->dev->bus_id, + dev_driver_string(info->dev), dev_name(info->dev), info->fix.smem_len >> 10); task = kthread_run(ps3fbd, info, DEVICE_NAME); diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index 2c5d069e5f0..1d2636a898c 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -687,7 +687,7 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) } error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, - pdev->dev.bus_id, priv); + dev_name(&pdev->dev), priv); if (error) { dev_err(&pdev->dev, "unable to request irq\n"); goto err1; diff --git a/drivers/video/tmiofb.c b/drivers/video/tmiofb.c index 7baf2dd12d5..a1eb0862255 100644 --- a/drivers/video/tmiofb.c +++ b/drivers/video/tmiofb.c @@ -751,7 +751,7 @@ static int __devinit tmiofb_probe(struct platform_device *dev) } retval = request_irq(irq, &tmiofb_irq, IRQF_DISABLED, - dev->dev.bus_id, info); + dev_name(&dev->dev), info); if (retval) goto err_request_irq; -- cgit v1.2.3 From 2796872c40c462bacf2d09bb99faa6dcd640a620 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: zorro: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/zorro/zorro.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index a1585d6f648..d45fb34e2d2 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c @@ -140,7 +140,7 @@ static int __init zorro_init(void) /* Initialize the Zorro bus */ INIT_LIST_HEAD(&zorro_bus.devices); - strcpy(zorro_bus.dev.bus_id, "zorro"); + dev_set_name(&zorro_bus.dev, "zorro"); error = device_register(&zorro_bus.dev); if (error) { pr_err("Zorro: Error registering zorro_bus\n"); @@ -167,7 +167,7 @@ static int __init zorro_init(void) if (request_resource(zorro_find_parent_resource(z), &z->resource)) pr_err("Zorro: Address space collision on device %s %pR\n", z->name, &z->resource); - sprintf(z->dev.bus_id, "%02x", i); + dev_set_name(&z->dev, "%02x", i); z->dev.parent = &zorro_bus.dev; z->dev.bus = &zorro_bus_type; error = device_register(&z->dev); -- cgit v1.2.3 From 48f8151ea68ad78391ef6ff12a83e6fbdb6094f6 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: mmc: struct device - replace bus_id with dev_name(), dev_set_name() Cc: drzeus-mmc@drzeus.cx Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/mmc/host/atmel-mci.c | 2 +- drivers/mmc/host/of_mmc_spi.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 2b1196e6142..e94e92001e7 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c @@ -1603,7 +1603,7 @@ static int __init atmci_probe(struct platform_device *pdev) tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)host); - ret = request_irq(irq, atmci_interrupt, 0, pdev->dev.bus_id, host); + ret = request_irq(irq, atmci_interrupt, 0, dev_name(&pdev->dev), host); if (ret) goto err_request_irq; diff --git a/drivers/mmc/host/of_mmc_spi.c b/drivers/mmc/host/of_mmc_spi.c index fb2921f8099..0c44d560bf1 100644 --- a/drivers/mmc/host/of_mmc_spi.c +++ b/drivers/mmc/host/of_mmc_spi.c @@ -103,7 +103,7 @@ struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi) if (!gpio_is_valid(oms->gpios[i])) continue; - ret = gpio_request(oms->gpios[i], dev->bus_id); + ret = gpio_request(oms->gpios[i], dev_name(dev)); if (ret < 0) { oms->gpios[i] = -EINVAL; continue; -- cgit v1.2.3 From c36f1e3301ee9d8045938a2741da7f8e4c7fbbff Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: mtd: struct device - replace bus_id with dev_name(), dev_set_name() Cc: dwmw2@infradead.org Cc: linux-mtd@lists.infradead.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/mtd/nand/ndfc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/nand/ndfc.c b/drivers/mtd/nand/ndfc.c index 582cf80f555..89bf85af642 100644 --- a/drivers/mtd/nand/ndfc.c +++ b/drivers/mtd/nand/ndfc.c @@ -187,7 +187,7 @@ static int ndfc_chip_init(struct ndfc_controller *ndfc, return -ENODEV; ndfc->mtd.name = kasprintf(GFP_KERNEL, "%s.%s", - ndfc->ofdev->dev.bus_id, flash_np->name); + dev_name(&ndfc->ofdev->dev), flash_np->name); if (!ndfc->mtd.name) { ret = -ENOMEM; goto err; -- cgit v1.2.3 From 54cc6954a431dad42fb73e0a50b6d318a70594f6 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: pci: struct device - replace bus_id with dev_name(), dev_set_name() Cc: jbarnes@virtuousgeek.org Cc: linux-pci@vger.kernel.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/pci/hotplug/cpqphp_sysfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/cpqphp_sysfs.c b/drivers/pci/hotplug/cpqphp_sysfs.c index a13abf55d78..8450f4a6568 100644 --- a/drivers/pci/hotplug/cpqphp_sysfs.c +++ b/drivers/pci/hotplug/cpqphp_sysfs.c @@ -225,7 +225,8 @@ void cpqhp_shutdown_debugfs(void) void cpqhp_create_debugfs_files(struct controller *ctrl) { - ctrl->dentry = debugfs_create_file(ctrl->pci_dev->dev.bus_id, S_IRUGO, root, ctrl, &debug_ops); + ctrl->dentry = debugfs_create_file(dev_name(&ctrl->pci_dev->dev), + S_IRUGO, root, ctrl, &debug_ops); } void cpqhp_remove_debugfs_files(struct controller *ctrl) -- cgit v1.2.3 From 37f105448eac49073c3ff9f101553aad845d24eb Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: rapidio: struct device - replace bus_id with dev_name(), dev_set_name() Cc: mporter@kernel.crashing.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/rapidio/rio-driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c index addb87cf44d..3222fa3c808 100644 --- a/drivers/rapidio/rio-driver.c +++ b/drivers/rapidio/rio-driver.c @@ -193,7 +193,7 @@ static int rio_match_bus(struct device *dev, struct device_driver *drv) } static struct device rio_bus = { - .bus_id = "rapidio", + .init_name = "rapidio", }; struct bus_type rio_bus_type = { -- cgit v1.2.3 From 1173960b0e85761811a421eb0bbcefb117eb7535 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: s390: struct device - replace bus_id with dev_name(), dev_set_name() Cc: schwidefsky@de.ibm.com Cc: linux-s390@vger.kernel.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/s390/net/qeth_l3_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 3d04920b9bb..0dcc036d34a 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1038,7 +1038,7 @@ static int qeth_l3_setadapter_parms(struct qeth_card *card) rc = qeth_query_setadapterparms(card); if (rc) { QETH_DBF_MESSAGE(2, "%s couldn't set adapter parameters: " - "0x%x\n", card->gdev->dev.bus_id, rc); + "0x%x\n", dev_name(&card->gdev->dev), rc); return rc; } if (qeth_adp_supported(card, IPA_SETADP_ALTER_MAC_ADDRESS)) { -- cgit v1.2.3 From 65a212dd71ffd99c83ad780205932fcb96a973b6 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: serial: struct device - replace bus_id with dev_name(), dev_set_name() Cc: davem@davemloft.net Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/serial/sunzilog.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 45a299f3561..e09d3cebb4f 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c @@ -1438,12 +1438,12 @@ static int __devinit zs_probe(struct of_device *op, const struct of_device_id *m } else { printk(KERN_INFO "%s: Keyboard at MMIO 0x%llx (irq = %d) " "is a %s\n", - op->dev.bus_id, + dev_name(&op->dev), (unsigned long long) up[0].port.mapbase, op->irqs[0], sunzilog_type(&up[0].port)); printk(KERN_INFO "%s: Mouse at MMIO 0x%llx (irq = %d) " "is a %s\n", - op->dev.bus_id, + dev_name(&op->dev), (unsigned long long) up[1].port.mapbase, op->irqs[0], sunzilog_type(&up[1].port)); kbm_inst++; -- cgit v1.2.3 From 1692713ee94e8d26f592a8e90b817ef66354246c Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:21 -0700 Subject: sh: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/sh/maple/maple.c | 8 ++++---- drivers/sh/superhyway/superhyway.c | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/sh/maple/maple.c b/drivers/sh/maple/maple.c index 63f0de29aa1..7e1257af3d4 100644 --- a/drivers/sh/maple/maple.c +++ b/drivers/sh/maple/maple.c @@ -424,7 +424,7 @@ static void maple_attach_driver(struct maple_device *mdev) /* Do this silently - as not a real device */ function = 0; mdev->driver = &maple_dummy_driver; - sprintf(mdev->dev.bus_id, "%d:0.port", mdev->port); + dev_set_name(&mdev->dev, "%d:0.port", mdev->port); } else { printk(KERN_INFO "Maple bus at (%d, %d): Function 0x%lX\n", @@ -440,8 +440,8 @@ static void maple_attach_driver(struct maple_device *mdev) "No maple driver found.\n"); mdev->driver = &maple_dummy_driver; } - sprintf(mdev->dev.bus_id, "%d:0%d.%lX", mdev->port, - mdev->unit, function); + dev_set_name(&mdev->dev, "%d:0%d.%lX", mdev->port, + mdev->unit, function); } mdev->function = function; mdev->dev.release = &maple_release_device; @@ -780,7 +780,7 @@ struct bus_type maple_bus_type = { EXPORT_SYMBOL_GPL(maple_bus_type); static struct device maple_bus = { - .bus_id = "maple", + .init_name = "maple", .release = maple_bus_release, }; diff --git a/drivers/sh/superhyway/superhyway.c b/drivers/sh/superhyway/superhyway.c index 4d0282b821b..2d9e7f3d561 100644 --- a/drivers/sh/superhyway/superhyway.c +++ b/drivers/sh/superhyway/superhyway.c @@ -22,7 +22,7 @@ static int superhyway_devices; static struct device superhyway_bus_device = { - .bus_id = "superhyway", + .init_name = "superhyway", }; static void superhyway_device_release(struct device *dev) @@ -83,7 +83,7 @@ int superhyway_add_device(unsigned long base, struct superhyway_device *sdev, dev->id.id = dev->vcr.mod_id; sprintf(dev->name, "SuperHyway device %04x", dev->id.id); - sprintf(dev->dev.bus_id, "%02x", superhyway_devices); + dev_set_name(&dev->dev, "%02x", superhyway_devices); superhyway_devices++; -- cgit v1.2.3 From df388556d7d845983c0da3a4a49873472c466275 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: tc: struct device - replace bus_id with dev_name(), dev_set_name() Cc: macro@linux-mips.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/tc/tc.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/tc/tc.c b/drivers/tc/tc.c index f77f62a4b32..e5bd4470a57 100644 --- a/drivers/tc/tc.c +++ b/drivers/tc/tc.c @@ -86,7 +86,7 @@ static void __init tc_bus_add_devices(struct tc_bus *tbus) slot); goto out_err; } - sprintf(tdev->dev.bus_id, "tc%x", slot); + dev_set_name(&tdev->dev, "tc%x", slot); tdev->bus = tbus; tdev->dev.parent = &tbus->dev; tdev->dev.bus = &tc_bus_type; @@ -104,7 +104,7 @@ static void __init tc_bus_add_devices(struct tc_bus *tbus) tdev->vendor[8] = 0; tdev->name[8] = 0; - pr_info("%s: %s %s %s\n", tdev->dev.bus_id, tdev->vendor, + pr_info("%s: %s %s %s\n", dev_name(&tdev->dev), tdev->vendor, tdev->name, tdev->firmware); devsize = readb(module + offset + TC_SLOT_SIZE); @@ -118,7 +118,7 @@ static void __init tc_bus_add_devices(struct tc_bus *tbus) } else { printk(KERN_ERR "%s: Cannot provide slot space " "(%dMiB required, up to %dMiB supported)\n", - tdev->dev.bus_id, devsize >> 20, + dev_name(&tdev->dev), devsize >> 20, max(slotsize, extslotsize) >> 20); kfree(tdev); goto out_err; @@ -146,7 +146,7 @@ static int __init tc_init(void) return 0; INIT_LIST_HEAD(&tc_bus.devices); - strcpy(tc_bus.dev.bus_id, "tc"); + dev_set_name(&tc_bus.dev, "tc"); device_register(&tc_bus.dev); if (tc_bus.info.slot_size) { -- cgit v1.2.3 From f2fecec51ad593cce1b07a2b54830a8412a441ea Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: pcmcia: struct device - replace bus_id with dev_name(), dev_set_name() Cc: Dominik Brodowski Cc: linux-pcmcia@lists.infradead.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/pcmcia/rsrc_mgr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c index c0e2afc79e3..e592e0e0d7e 100644 --- a/drivers/pcmcia/rsrc_mgr.c +++ b/drivers/pcmcia/rsrc_mgr.c @@ -153,7 +153,7 @@ static struct resource *iodyn_find_io_region(unsigned long base, int num, unsigned long align, struct pcmcia_socket *s) { struct resource *res = make_resource(0, num, IORESOURCE_IO, - s->dev.bus_id); + dev_name(&s->dev)); struct pcmcia_align_data data; unsigned long min = base; int ret; -- cgit v1.2.3 From 744bcb13d376b38ff1df3bbcc810493e1b999502 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: rtc: struct device - replace bus_id with dev_name(), dev_set_name() Cc: a.zummo@towertech.it Cc: rtc-linux@googlegroups.com Signed-off-by: Kay Sievers Signed-off-by: Alessandro Zummo Signed-off-by: Greg Kroah-Hartman --- drivers/rtc/rtc-at91sam9.c | 4 ++-- drivers/rtc/rtc-omap.c | 4 ++-- drivers/rtc/rtc-twl4030.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c index d5e4e637dde..86c61f14351 100644 --- a/drivers/rtc/rtc-at91sam9.c +++ b/drivers/rtc/rtc-at91sam9.c @@ -351,7 +351,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) /* register irq handler after we know what name we'll use */ ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, IRQF_DISABLED | IRQF_SHARED, - rtc->rtcdev->dev.bus_id, rtc); + dev_name(&rtc->rtcdev->dev), rtc); if (ret) { dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS); rtc_device_unregister(rtc->rtcdev); @@ -366,7 +366,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) if (gpbr_readl(rtc) == 0) dev_warn(&pdev->dev, "%s: SET TIME!\n", - rtc->rtcdev->dev.bus_id); + dev_name(&rtc->rtcdev->dev)); return 0; diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c index 2cbeb0794f1..bd1ce8e2bc1 100644 --- a/drivers/rtc/rtc-omap.c +++ b/drivers/rtc/rtc-omap.c @@ -377,13 +377,13 @@ static int __init omap_rtc_probe(struct platform_device *pdev) /* handle periodic and alarm irqs */ if (request_irq(omap_rtc_timer, rtc_irq, IRQF_DISABLED, - rtc->dev.bus_id, rtc)) { + dev_name(&rtc->dev), rtc)) { pr_debug("%s: RTC timer interrupt IRQ%d already claimed\n", pdev->name, omap_rtc_timer); goto fail0; } if (request_irq(omap_rtc_alarm, rtc_irq, IRQF_DISABLED, - rtc->dev.bus_id, rtc)) { + dev_name(&rtc->dev), rtc)) { pr_debug("%s: RTC alarm interrupt IRQ%d already claimed\n", pdev->name, omap_rtc_alarm); goto fail1; diff --git a/drivers/rtc/rtc-twl4030.c b/drivers/rtc/rtc-twl4030.c index ad35f76c46b..a6341e4f9a0 100644 --- a/drivers/rtc/rtc-twl4030.c +++ b/drivers/rtc/rtc-twl4030.c @@ -426,7 +426,7 @@ static int __devinit twl4030_rtc_probe(struct platform_device *pdev) ret = request_irq(irq, twl4030_rtc_interrupt, IRQF_TRIGGER_RISING, - rtc->dev.bus_id, rtc); + dev_name(&rtc->dev), rtc); if (ret < 0) { dev_err(&pdev->dev, "IRQ is not free.\n"); goto out1; -- cgit v1.2.3 From c23135573f37facd18edb2e8e8512c67928c54ac Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: net: struct device - replace bus_id with dev_name(), dev_set_name() Cc: davem@davemloft.net Cc: netdev@vger.kernel.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/net/arm/ks8695net.c | 2 +- drivers/net/au1000_eth.c | 8 ++++---- drivers/net/bfin_mac.c | 12 ++++++------ drivers/net/bmac.c | 2 +- drivers/net/cpmac.c | 2 +- drivers/net/declance.c | 6 +++--- drivers/net/depca.c | 6 +++--- drivers/net/ehea/ehea_main.c | 2 +- drivers/net/jazzsonic.c | 6 ++++-- drivers/net/macb.c | 10 +++++----- drivers/net/macsonic.c | 15 ++++++++------- drivers/net/mv643xx_eth.c | 2 +- drivers/net/sb1250-mac.c | 10 +++++----- drivers/net/smc911x.c | 2 +- drivers/net/smc91x.c | 2 +- drivers/net/smsc911x.c | 7 ++++--- drivers/net/smsc9420.c | 4 ++-- drivers/net/tc35815.c | 4 ++-- drivers/net/xtsonic.c | 2 +- 19 files changed, 54 insertions(+), 50 deletions(-) (limited to 'drivers') diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index f3a12743489..35cd264abae 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -1059,7 +1059,7 @@ ks8695_get_drvinfo(struct net_device *ndev, struct ethtool_drvinfo *info) { strlcpy(info->driver, MODULENAME, sizeof(info->driver)); strlcpy(info->version, MODULEVERSION, sizeof(info->version)); - strlcpy(info->bus_info, ndev->dev.parent->bus_id, + strlcpy(info->bus_info, dev_name(ndev->dev.parent), sizeof(info->bus_info)); } diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index 9c875bb3f76..79aec32c6ad 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -355,8 +355,8 @@ static int mii_probe (struct net_device *dev) /* now we are supposed to have a proper phydev, to attach to... */ BUG_ON(phydev->attached_dev); - phydev = phy_connect(dev, phydev->dev.bus_id, &au1000_adjust_link, 0, - PHY_INTERFACE_MODE_MII); + phydev = phy_connect(dev, dev_name(&phydev->dev), &au1000_adjust_link, + 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); @@ -381,8 +381,8 @@ static int mii_probe (struct net_device *dev) aup->phy_dev = phydev; printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name, + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; } diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 78e31aa861e..9afe8092dfc 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c @@ -415,11 +415,11 @@ static int mii_probe(struct net_device *dev) } #if defined(CONFIG_BFIN_MAC_RMII) - phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0, - PHY_INTERFACE_MODE_RMII); + phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link, + 0, PHY_INTERFACE_MODE_RMII); #else - phydev = phy_connect(dev, phydev->dev.bus_id, &bfin_mac_adjust_link, 0, - PHY_INTERFACE_MODE_MII); + phydev = phy_connect(dev, dev_name(&phydev->dev), &bfin_mac_adjust_link, + 0, PHY_INTERFACE_MODE_MII); #endif if (IS_ERR(phydev)) { @@ -447,7 +447,7 @@ static int mii_probe(struct net_device *dev) printk(KERN_INFO "%s: attached PHY driver [%s] " "(mii_bus:phy_addr=%s, irq=%d, mdc_clk=%dHz(mdc_div=%d)" "@sclk=%dMHz)\n", - DRV_NAME, phydev->drv->name, phydev->dev.bus_id, phydev->irq, + DRV_NAME, phydev->drv->name, dev_name(&phydev->dev), phydev->irq, MDC_CLK, mdc_div, sclk/1000000); return 0; @@ -488,7 +488,7 @@ static void bfin_mac_ethtool_getdrvinfo(struct net_device *dev, strcpy(info->driver, DRV_NAME); strcpy(info->version, DRV_VERSION); strcpy(info->fw_version, "N/A"); - strcpy(info->bus_info, dev->dev.bus_id); + strcpy(info->bus_info, dev_name(&dev->dev)); } static struct ethtool_ops bfin_mac_ethtool_ops = { diff --git a/drivers/net/bmac.c b/drivers/net/bmac.c index 8a546a33d58..1ab58375d06 100644 --- a/drivers/net/bmac.c +++ b/drivers/net/bmac.c @@ -1240,7 +1240,7 @@ static void bmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *inf { struct bmac_data *bp = netdev_priv(dev); strcpy(info->driver, "bmac"); - strcpy(info->bus_info, bp->mdev->ofdev.dev.bus_id); + strcpy(info->bus_info, dev_name(&bp->mdev->ofdev.dev)); } static const struct ethtool_ops bmac_ethtool_ops = { diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index f66548751c3..79741c5f9fe 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -1161,7 +1161,7 @@ static int __devinit cpmac_probe(struct platform_device *pdev) priv->msg_enable = netif_msg_init(debug_level, 0xff); memcpy(dev->dev_addr, pdata->dev_addr, sizeof(dev->dev_addr)); - priv->phy = phy_connect(dev, cpmac_mii->phy_map[phy_id]->dev.bus_id, + priv->phy = phy_connect(dev, dev_name(&cpmac_mii->phy_map[phy_id]->dev), &cpmac_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(priv->phy)) { if (netif_msg_drv(priv)) diff --git a/drivers/net/declance.c b/drivers/net/declance.c index 7ce3053530f..861c867fca8 100644 --- a/drivers/net/declance.c +++ b/drivers/net/declance.c @@ -1027,7 +1027,7 @@ static int __init dec_lance_probe(struct device *bdev, const int type) printk(version); if (bdev) - snprintf(name, sizeof(name), "%s", bdev->bus_id); + snprintf(name, sizeof(name), "%s", dev_name(bdev)); else { i = 0; dev = root_lance_dev; @@ -1105,10 +1105,10 @@ static int __init dec_lance_probe(struct device *bdev, const int type) start = to_tc_dev(bdev)->resource.start; len = to_tc_dev(bdev)->resource.end - start + 1; - if (!request_mem_region(start, len, bdev->bus_id)) { + if (!request_mem_region(start, len, dev_name(bdev))) { printk(KERN_ERR "%s: Unable to reserve MMIO resource\n", - bdev->bus_id); + dev_name(bdev)); ret = -EBUSY; goto err_out_dev; } diff --git a/drivers/net/depca.c b/drivers/net/depca.c index e4cef491dc7..55625dbbae5 100644 --- a/drivers/net/depca.c +++ b/drivers/net/depca.c @@ -606,8 +606,8 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) if (!mem_start || lp->adapter < DEPCA || lp->adapter >=unknown) return -ENXIO; - printk ("%s: %s at 0x%04lx", - device->bus_id, depca_signature[lp->adapter], ioaddr); + printk("%s: %s at 0x%04lx", + dev_name(device), depca_signature[lp->adapter], ioaddr); switch (lp->depca_bus) { #ifdef CONFIG_MCA @@ -669,7 +669,7 @@ static int __init depca_hw_init (struct net_device *dev, struct device *device) spin_lock_init(&lp->lock); sprintf(lp->adapter_name, "%s (%s)", - depca_signature[lp->adapter], device->bus_id); + depca_signature[lp->adapter], dev_name(device)); status = -EBUSY; /* Initialisation Block */ diff --git a/drivers/net/ehea/ehea_main.c b/drivers/net/ehea/ehea_main.c index dfe92264e82..8e7c16535ad 100644 --- a/drivers/net/ehea/ehea_main.c +++ b/drivers/net/ehea/ehea_main.c @@ -3040,7 +3040,7 @@ static struct device *ehea_register_port(struct ehea_port *port, port->ofdev.dev.parent = &port->adapter->ofdev->dev; port->ofdev.dev.bus = &ibmebus_bus_type; - sprintf(port->ofdev.dev.bus_id, "port%d", port_name_cnt++); + dev_set_name(&port->ofdev.dev, "port%d", port_name_cnt++); port->ofdev.dev.release = logical_port_release; ret = of_device_register(&port->ofdev); diff --git a/drivers/net/jazzsonic.c b/drivers/net/jazzsonic.c index 334ff9e12cd..14248cfc3df 100644 --- a/drivers/net/jazzsonic.c +++ b/drivers/net/jazzsonic.c @@ -131,7 +131,8 @@ static int __init sonic_probe1(struct net_device *dev) if (sonic_debug && version_printed++ == 0) printk(version); - printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", lp->device->bus_id, dev->base_addr); + printk(KERN_INFO "%s: Sonic ethernet found at 0x%08lx, ", + dev_name(lp->device), dev->base_addr); /* * Put the sonic into software reset, then @@ -156,7 +157,8 @@ static int __init sonic_probe1(struct net_device *dev) if ((lp->descriptors = dma_alloc_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), &lp->descriptors_laddr, GFP_KERNEL)) == NULL) { - printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id); + printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", + dev_name(lp->device)); goto out; } diff --git a/drivers/net/macb.c b/drivers/net/macb.c index f6c4936e2fa..f4086542c35 100644 --- a/drivers/net/macb.c +++ b/drivers/net/macb.c @@ -211,10 +211,10 @@ static int macb_mii_probe(struct net_device *dev) /* attach the mac to the phy */ if (pdata && pdata->is_rmii) { - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &macb_handle_link_change, 0, PHY_INTERFACE_MODE_RMII); } else { - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &macb_handle_link_change, 0, PHY_INTERFACE_MODE_MII); } @@ -1077,7 +1077,7 @@ static void macb_get_drvinfo(struct net_device *dev, strcpy(info->driver, bp->pdev->dev.driver->name); strcpy(info->version, "$Revision: 1.14 $"); - strcpy(info->bus_info, bp->pdev->dev.bus_id); + strcpy(info->bus_info, dev_name(&bp->pdev->dev)); } static struct ethtool_ops macb_ethtool_ops = { @@ -1234,8 +1234,8 @@ static int __init macb_probe(struct platform_device *pdev) phydev = bp->phy_dev; printk(KERN_INFO "%s: attached PHY driver [%s] " - "(mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + "(mii_bus:phy_addr=%s, irq=%d)\n", dev->name, + phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; diff --git a/drivers/net/macsonic.c b/drivers/net/macsonic.c index 205bb05c25d..527166e35d5 100644 --- a/drivers/net/macsonic.c +++ b/drivers/net/macsonic.c @@ -176,7 +176,8 @@ static int __init macsonic_init(struct net_device *dev) if ((lp->descriptors = dma_alloc_coherent(lp->device, SIZEOF_SONIC_DESC * SONIC_BUS_SCALE(lp->dma_bitmode), &lp->descriptors_laddr, GFP_KERNEL)) == NULL) { - printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", lp->device->bus_id); + printk(KERN_ERR "%s: couldn't alloc DMA memory for descriptors.\n", + dev_name(lp->device)); return -ENOMEM; } @@ -337,7 +338,7 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev) sonic_version_printed = 1; } printk(KERN_INFO "%s: onboard / comm-slot SONIC at 0x%08lx\n", - lp->device->bus_id, dev->base_addr); + dev_name(lp->device), dev->base_addr); /* The PowerBook's SONIC is 16 bit always. */ if (macintosh_config->ident == MAC_MODEL_PB520) { @@ -370,10 +371,10 @@ static int __init mac_onboard_sonic_probe(struct net_device *dev) } printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n", - lp->device->bus_id, sr, lp->dma_bitmode?32:16, lp->reg_offset); + dev_name(lp->device), sr, lp->dma_bitmode?32:16, lp->reg_offset); #if 0 /* This is sometimes useful to find out how MacOS configured the card. */ - printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id, + printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", dev_name(lp->device), SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff); #endif @@ -525,12 +526,12 @@ static int __init mac_nubus_sonic_probe(struct net_device *dev) sonic_version_printed = 1; } printk(KERN_INFO "%s: %s in slot %X\n", - lp->device->bus_id, ndev->board->name, ndev->board->slot); + dev_name(lp->device), ndev->board->name, ndev->board->slot); printk(KERN_INFO "%s: revision 0x%04x, using %d bit DMA and register offset %d\n", - lp->device->bus_id, SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset); + dev_name(lp->device), SONIC_READ(SONIC_SR), dma_bitmode?32:16, reg_offset); #if 0 /* This is sometimes useful to find out how MacOS configured the card. */ - printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", lp->device->bus_id, + printk(KERN_INFO "%s: DCR: 0x%04x, DCR2: 0x%04x\n", dev_name(lp->device), SONIC_READ(SONIC_DCR) & 0xffff, SONIC_READ(SONIC_DCR2) & 0xffff); #endif diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index b0bc3bc18e9..fe4e158c893 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -2588,7 +2588,7 @@ static void phy_init(struct mv643xx_eth_private *mp, int speed, int duplex) phy_reset(mp); - phy_attach(mp->dev, phy->dev.bus_id, 0, PHY_INTERFACE_MODE_GMII); + phy_attach(mp->dev, dev_name(&phy->dev), 0, PHY_INTERFACE_MODE_GMII); if (speed == 0) { phy->autoneg = AUTONEG_ENABLE; diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 31e38fae017..845431c186a 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c @@ -2478,7 +2478,7 @@ static int sbmac_mii_probe(struct net_device *dev) return -ENXIO; } - phy_dev = phy_connect(dev, phy_dev->dev.bus_id, &sbmac_mii_poll, 0, + phy_dev = phy_connect(dev, dev_name(&phy_dev->dev), &sbmac_mii_poll, 0, PHY_INTERFACE_MODE_GMII); if (IS_ERR(phy_dev)) { printk(KERN_ERR "%s: could not attach to PHY\n", dev->name); @@ -2500,7 +2500,7 @@ static int sbmac_mii_probe(struct net_device *dev) pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", dev->name, phy_dev->drv->name, - phy_dev->dev.bus_id, phy_dev->irq); + dev_name(&phy_dev->dev), phy_dev->irq); sc->phy_dev = phy_dev; @@ -2697,7 +2697,7 @@ static int __init sbmac_probe(struct platform_device *pldev) sbm_base = ioremap_nocache(res->start, res->end - res->start + 1); if (!sbm_base) { printk(KERN_ERR "%s: unable to map device registers\n", - pldev->dev.bus_id); + dev_name(&pldev->dev)); err = -ENOMEM; goto out_out; } @@ -2708,7 +2708,7 @@ static int __init sbmac_probe(struct platform_device *pldev) * If we find a zero, skip this MAC. */ sbmac_orig_hwaddr = __raw_readq(sbm_base + R_MAC_ETHERNET_ADDR); - pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", pldev->dev.bus_id, + pr_debug("%s: %sconfiguring MAC at 0x%08Lx\n", dev_name(&pldev->dev), sbmac_orig_hwaddr ? "" : "not ", (long long)res->start); if (sbmac_orig_hwaddr == 0) { err = 0; @@ -2721,7 +2721,7 @@ static int __init sbmac_probe(struct platform_device *pldev) dev = alloc_etherdev(sizeof(struct sbmac_softc)); if (!dev) { printk(KERN_ERR "%s: unable to allocate etherdev\n", - pldev->dev.bus_id); + dev_name(&pldev->dev)); err = -ENOMEM; goto out_unmap; } diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 223cde0d43b..293610334a7 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c @@ -1545,7 +1545,7 @@ smc911x_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strncpy(info->driver, CARDNAME, sizeof(info->driver)); strncpy(info->version, version, sizeof(info->version)); - strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strncpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } static int smc911x_ethtool_nwayreset(struct net_device *dev) diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index b215a8d85e6..0b6da950144 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -1614,7 +1614,7 @@ smc_ethtool_getdrvinfo(struct net_device *dev, struct ethtool_drvinfo *info) { strncpy(info->driver, CARDNAME, sizeof(info->driver)); strncpy(info->version, version, sizeof(info->version)); - strncpy(info->bus_info, dev->dev.parent->bus_id, sizeof(info->bus_info)); + strncpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } static int smc_ethtool_nwayreset(struct net_device *dev) diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index d1590ac55e4..ab18ee0f60f 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c @@ -769,7 +769,7 @@ static int smsc911x_mii_probe(struct net_device *dev) return -ENODEV; } - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &smsc911x_phy_adjust_link, 0, pdata->config.phy_interface); if (IS_ERR(phydev)) { @@ -778,7 +778,8 @@ static int smsc911x_mii_probe(struct net_device *dev) } pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + dev->name, phydev->drv->name, + dev_name(&phydev->dev), phydev->irq); /* mask with MAC supported features */ phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | @@ -1549,7 +1550,7 @@ static void smsc911x_ethtool_getdrvinfo(struct net_device *dev, { strlcpy(info->driver, SMSC_CHIPNAME, sizeof(info->driver)); strlcpy(info->version, SMSC_DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, dev->dev.parent->bus_id, + strlcpy(info->bus_info, dev_name(dev->dev.parent), sizeof(info->bus_info)); } diff --git a/drivers/net/smsc9420.c b/drivers/net/smsc9420.c index 4e15ae068b3..72f1348eb80 100644 --- a/drivers/net/smsc9420.c +++ b/drivers/net/smsc9420.c @@ -1160,7 +1160,7 @@ static int smsc9420_mii_probe(struct net_device *dev) smsc_info(PROBE, "PHY addr %d, phy_id 0x%08X", phydev->addr, phydev->phy_id); - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &smsc9420_phy_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { @@ -1169,7 +1169,7 @@ static int smsc9420_mii_probe(struct net_device *dev) } pr_info("%s: attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, phydev->irq); + dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->irq); /* mask with MAC supported features */ phydev->supported &= (PHY_BASIC_FEATURES | SUPPORTED_Pause | diff --git a/drivers/net/tc35815.c b/drivers/net/tc35815.c index bcd0e60cbda..e1f8eb96a45 100644 --- a/drivers/net/tc35815.c +++ b/drivers/net/tc35815.c @@ -725,7 +725,7 @@ static int tc_mii_probe(struct net_device *dev) } /* attach the mac to the phy */ - phydev = phy_connect(dev, phydev->dev.bus_id, + phydev = phy_connect(dev, dev_name(&phydev->dev), &tc_handle_link_change, 0, lp->chiptype == TC35815_TX4939 ? PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII); @@ -735,7 +735,7 @@ static int tc_mii_probe(struct net_device *dev) } printk(KERN_INFO "%s: attached PHY driver [%s] " "(mii_bus:phy_addr=%s, id=%x)\n", - dev->name, phydev->drv->name, phydev->dev.bus_id, + dev->name, phydev->drv->name, dev_name(&phydev->dev), phydev->phy_id); /* mask with MAC supported features */ diff --git a/drivers/net/xtsonic.c b/drivers/net/xtsonic.c index 03a3f34e903..a12a7211c98 100644 --- a/drivers/net/xtsonic.c +++ b/drivers/net/xtsonic.c @@ -183,7 +183,7 @@ static int __init sonic_probe1(struct net_device *dev) if (lp->descriptors == NULL) { printk(KERN_ERR "%s: couldn't alloc DMA memory for " - " descriptors.\n", lp->device->bus_id); + " descriptors.\n", dev_name(lp->device)); goto out; } -- cgit v1.2.3 From 2ead054cd26752c7ce47dfbf320dd021ef70682d Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: drm: struct device - replace bus_id with dev_name(), dev_set_name() Cc: airlied@linux.ie Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/gpu/drm/drm_sysfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 5aa6780652a..186d08159d4 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c @@ -359,8 +359,8 @@ int drm_sysfs_connector_add(struct drm_connector *connector) DRM_DEBUG("adding \"%s\" to sysfs\n", drm_get_connector_name(connector)); - snprintf(connector->kdev.bus_id, BUS_ID_SIZE, "card%d-%s", - dev->primary->index, drm_get_connector_name(connector)); + dev_set_name(&connector->kdev, "card%d-%s", + dev->primary->index, drm_get_connector_name(connector)); ret = device_register(&connector->kdev); if (ret) { -- cgit v1.2.3 From c3ef01ce4f73f41e99b2a5f0796f1f1a1daaaaa2 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: v4l: struct device - replace bus_id with dev_name(), dev_set_name() Cc: mchehab@infradead.org Cc: linux-media@vger.kernel.org Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/media/radio/radio-tea5764.c | 3 ++- drivers/media/video/v4l2-device.c | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c index 4d35308fc1f..393623818ad 100644 --- a/drivers/media/radio/radio-tea5764.c +++ b/drivers/media/radio/radio-tea5764.c @@ -298,7 +298,8 @@ static int vidioc_querycap(struct file *file, void *priv, strlcpy(v->driver, dev->dev.driver->name, sizeof(v->driver)); strlcpy(v->card, dev->name, sizeof(v->card)); - snprintf(v->bus_info, sizeof(v->bus_info), "I2C:%s", dev->dev.bus_id); + snprintf(v->bus_info, sizeof(v->bus_info), + "I2C:%s", dev_name(&dev->dev)); v->version = RADIO_VERSION; v->capabilities = V4L2_CAP_TUNER | V4L2_CAP_RADIO; return 0; diff --git a/drivers/media/video/v4l2-device.c b/drivers/media/video/v4l2-device.c index cf9d4c7f571..8a4b74f3129 100644 --- a/drivers/media/video/v4l2-device.c +++ b/drivers/media/video/v4l2-device.c @@ -34,7 +34,7 @@ int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev) spin_lock_init(&v4l2_dev->lock); v4l2_dev->dev = dev; snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s", - dev->driver->name, dev->bus_id); + dev->driver->name, dev_name(dev)); dev_set_drvdata(dev, v4l2_dev); return 0; } -- cgit v1.2.3 From 9d6b4c82bffbe6de624ff86cb279166867f46365 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: amba: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/amba/bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c index 00c46e0b40e..3d763fdf99b 100644 --- a/drivers/amba/bus.c +++ b/drivers/amba/bus.c @@ -210,7 +210,7 @@ int amba_device_register(struct amba_device *dev, struct resource *parent) dev->dev.release = amba_device_release; dev->dev.bus = &amba_bustype; dev->dev.dma_mask = &dev->dma_mask; - dev->res.name = dev->dev.bus_id; + dev->res.name = dev_name(&dev->dev); if (!dev->dev.coherent_dma_mask && dev->dma_mask) dev_warn(&dev->dev, "coherent dma mask is unset\n"); @@ -294,7 +294,7 @@ static int amba_find_match(struct device *dev, void *data) if (d->parent) r &= d->parent == dev->parent; if (d->busid) - r &= strcmp(dev->bus_id, d->busid) == 0; + r &= strcmp(dev_name(dev), d->busid) == 0; if (r) { get_device(dev); -- cgit v1.2.3 From 9591463af7ea3a2d723c7e39c08aa05ad27e7bfc Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: dio: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/dio/dio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dio/dio.c b/drivers/dio/dio.c index 10c3c498358..55dd88d82d6 100644 --- a/drivers/dio/dio.c +++ b/drivers/dio/dio.c @@ -182,7 +182,7 @@ static int __init dio_init(void) /* Initialize the DIO bus */ INIT_LIST_HEAD(&dio_bus.devices); - strcpy(dio_bus.dev.bus_id, "dio"); + dev_set_name(&dio_bus.dev, "dio"); error = device_register(&dio_bus.dev); if (error) { pr_err("DIO: Error registering dio_bus\n"); @@ -237,7 +237,7 @@ static int __init dio_init(void) dev->scode = scode; dev->resource.start = pa; dev->resource.end = pa + DIO_SIZE(scode, va); - sprintf(dev->dev.bus_id,"%02x", scode); + dev_set_name(&dev->dev, "%02x", scode); /* read the ID byte(s) and encode if necessary. */ prid = DIO_ID(va); -- cgit v1.2.3 From dfbc90196dfb9a814e7f2e1f4c47aa425452d313 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: dma: struct device - replace bus_id with dev_name(), dev_set_name() Cc: Dan Williams Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/dma/dw_dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index a97c07eef7e..20ad3d26bec 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c @@ -1011,7 +1011,7 @@ static int __init dw_probe(struct platform_device *pdev) dma_writel(dw, CFG, DW_CFG_DMA_EN); printk(KERN_INFO "%s: DesignWare DMA Controller, %d channels\n", - pdev->dev.bus_id, dw->dma.chancnt); + dev_name(&pdev->dev), dw->dma.chancnt); dma_async_device_register(&dw->dma); -- cgit v1.2.3 From e537b2453ccf8884513201d6afcb62ca0763ecf0 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:22 -0700 Subject: eisa: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/eisa/eisa-bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/eisa/eisa-bus.c b/drivers/eisa/eisa-bus.c index c950bf8606d..66958b3f10b 100644 --- a/drivers/eisa/eisa-bus.c +++ b/drivers/eisa/eisa-bus.c @@ -200,7 +200,7 @@ static int __init eisa_init_device (struct eisa_root_device *root, edev->dev.bus = &eisa_bus_type; edev->dev.dma_mask = &edev->dma_mask; edev->dev.coherent_dma_mask = edev->dma_mask; - sprintf (edev->dev.bus_id, "%02X:%02X", root->bus_nr, slot); + dev_set_name(&edev->dev, "%02X:%02X", root->bus_nr, slot); for (i = 0; i < EISA_MAX_RESOURCES; i++) { #ifdef CONFIG_EISA_NAMES @@ -301,7 +301,7 @@ static int __init eisa_probe (struct eisa_root_device *root) struct eisa_device *edev; printk (KERN_INFO "EISA: Probing bus %d at %s\n", - root->bus_nr, root->dev->bus_id); + root->bus_nr, dev_name(root->dev)); /* First try to get hold of slot 0. If there is no device * here, simply fail, unless root->force_probe is set. */ -- cgit v1.2.3 From 3e274bd02b04064632492a86fe99d3b613c74d84 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:23 -0700 Subject: gpio: struct device - replace bus_id with dev_name(), dev_set_name() Cc: Michael Buesch Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/gpio/bt8xxgpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpio/bt8xxgpio.c b/drivers/gpio/bt8xxgpio.c index 7a1168249dd..984b587f0f9 100644 --- a/drivers/gpio/bt8xxgpio.c +++ b/drivers/gpio/bt8xxgpio.c @@ -160,7 +160,7 @@ static void bt8xxgpio_gpio_setup(struct bt8xxgpio *bg) { struct gpio_chip *c = &bg->gpio; - c->label = bg->pdev->dev.bus_id; + c->label = dev_name(&bg->pdev->dev); c->owner = THIS_MODULE; c->direction_input = bt8xxgpio_gpio_direction_input; c->get = bt8xxgpio_gpio_get; -- cgit v1.2.3 From cf43f4ab3a065296822bb245975d006707ccde8d Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:23 -0700 Subject: mca: struct device - replace bus_id with dev_name(), dev_set_name() Cc: James.Bottomley@HansenPartnership.com Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/mca/mca-bus.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mca/mca-bus.c b/drivers/mca/mca-bus.c index ef2dbfe7471..ada5ebbaa25 100644 --- a/drivers/mca/mca-bus.c +++ b/drivers/mca/mca-bus.c @@ -110,7 +110,7 @@ int __init mca_register_device(int bus, struct mca_device *mca_dev) mca_dev->dev.parent = &mca_bus->dev; mca_dev->dev.bus = &mca_bus_type; - sprintf (mca_dev->dev.bus_id, "%02d:%02X", bus, mca_dev->slot); + dev_set_name(&mca_dev->dev, "%02d:%02X", bus, mca_dev->slot); mca_dev->dma_mask = mca_bus->default_dma_mask; mca_dev->dev.dma_mask = &mca_dev->dma_mask; mca_dev->dev.coherent_dma_mask = mca_dev->dma_mask; @@ -151,7 +151,7 @@ struct mca_bus * __devinit mca_attach_bus(int bus) if (!mca_bus) return NULL; - sprintf(mca_bus->dev.bus_id,"mca%d",bus); + dev_set_name(&mca_bus->dev, "mca%d", bus); sprintf(mca_bus->name,"Host %s MCA Bridge", bus ? "Secondary" : "Primary"); if (device_register(&mca_bus->dev)) { kfree(mca_bus); -- cgit v1.2.3 From b2bf61f23f74d5b5aa35f242a2fe2f08ce4a53e7 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:23 -0700 Subject: mfd: struct device - replace bus_id with dev_name(), dev_set_name() Cc: sameo@openedhand.com Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/mfd/mcp-core.c | 2 +- drivers/mfd/ucb1x00-core.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mfd/mcp-core.c b/drivers/mfd/mcp-core.c index 6063dc2b52e..57271cb3b31 100644 --- a/drivers/mfd/mcp-core.c +++ b/drivers/mfd/mcp-core.c @@ -214,7 +214,7 @@ EXPORT_SYMBOL(mcp_host_alloc); int mcp_host_register(struct mcp *mcp) { - strcpy(mcp->attached_device.bus_id, "mcp0"); + dev_set_name(&mcp->attached_device, "mcp0"); return device_register(&mcp->attached_device); } EXPORT_SYMBOL(mcp_host_register); diff --git a/drivers/mfd/ucb1x00-core.c b/drivers/mfd/ucb1x00-core.c index 6860c924f36..fea9085fe52 100644 --- a/drivers/mfd/ucb1x00-core.c +++ b/drivers/mfd/ucb1x00-core.c @@ -492,7 +492,7 @@ static int ucb1x00_probe(struct mcp *mcp) ucb->dev.class = &ucb1x00_class; ucb->dev.parent = &mcp->attached_device; - strlcpy(ucb->dev.bus_id, "ucb1x00", sizeof(ucb->dev.bus_id)); + dev_set_name(&ucb->dev, "ucb1x00"); spin_lock_init(&ucb->lock); spin_lock_init(&ucb->io_lock); -- cgit v1.2.3 From 2c0f3e96f3fc7bbd1cb3caa601f19cf030c2b958 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:23 -0700 Subject: wimax: struct device - replace bus_id with dev_name(), dev_set_name() Cc: inaky.perez-gonzalez@intel.com Cc: linux-wimax@intel.com Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/net/wimax/i2400m/driver.c | 2 +- drivers/net/wimax/i2400m/usb-notif.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wimax/i2400m/driver.c b/drivers/net/wimax/i2400m/driver.c index e80a0b65a75..d58b971faa6 100644 --- a/drivers/net/wimax/i2400m/driver.c +++ b/drivers/net/wimax/i2400m/driver.c @@ -613,7 +613,7 @@ int i2400m_setup(struct i2400m *i2400m, enum i2400m_bri bm_flags) d_fnstart(3, dev, "(i2400m %p)\n", i2400m); snprintf(wimax_dev->name, sizeof(wimax_dev->name), - "i2400m-%s:%s", dev->bus->name, dev->bus_id); + "i2400m-%s:%s", dev->bus->name, dev_name(dev)); i2400m->bm_cmd_buf = kzalloc(I2400M_BM_CMD_BUF_SIZE, GFP_KERNEL); if (i2400m->bm_cmd_buf == NULL) { diff --git a/drivers/net/wimax/i2400m/usb-notif.c b/drivers/net/wimax/i2400m/usb-notif.c index 9702c22b249..0528879f6d3 100644 --- a/drivers/net/wimax/i2400m/usb-notif.c +++ b/drivers/net/wimax/i2400m/usb-notif.c @@ -102,7 +102,7 @@ int i2400mu_notification_grok(struct i2400mu *i2400mu, const void *buf, dev_err(dev, "HW BUG? Unknown/unexpected data in notification " "message (%zu bytes)\n", buf_len); snprintf(prefix, sizeof(prefix), "%s %s: ", - dev_driver_string(dev) , dev->bus_id); + dev_driver_string(dev) , dev_name(dev)); if (buf_len > 64) { print_hex_dump(KERN_ERR, prefix, DUMP_PREFIX_OFFSET, 8, 4, buf, 64, 0); -- cgit v1.2.3 From 5df5852446196c9713e897ab5f9b8a168d971a00 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Tue, 24 Mar 2009 16:38:23 -0700 Subject: usb: struct device - replace bus_id with dev_name(), dev_set_name() Acked-by: Greg Kroah-Hartman Signed-off-by: Kay Sievers --- drivers/usb/gadget/ci13xxx_udc.c | 2 +- drivers/usb/gadget/imx_udc.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c index bebf911c7e5..7f4e5eb1dc8 100644 --- a/drivers/usb/gadget/ci13xxx_udc.c +++ b/drivers/usb/gadget/ci13xxx_udc.c @@ -2626,7 +2626,7 @@ static int udc_probe(struct device *dev, void __iomem *regs, const char *name) INIT_LIST_HEAD(&udc->gadget.ep_list); udc->gadget.ep0 = NULL; - strcpy(udc->gadget.dev.bus_id, "gadget"); + dev_set_name(&udc->gadget.dev, "gadget"); udc->gadget.dev.dma_mask = dev->dma_mask; udc->gadget.dev.parent = dev; udc->gadget.dev.release = udc_release; diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 77c5d0a8a06..cd67ac75e62 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c @@ -1186,8 +1186,8 @@ static struct imx_udc_struct controller = { .ep0 = &controller.imx_ep[0].ep, .name = driver_name, .dev = { - .bus_id = "gadget", - }, + .init_name = "gadget", + }, }, .imx_ep[0] = { -- cgit v1.2.3 From 6866ac9db02ac1ec71f2aa720a1019581f69a725 Mon Sep 17 00:00:00 2001 From: Sachin Sant Date: Mon, 16 Feb 2009 19:10:11 +0530 Subject: USB: FHCI: use dev_name() in place of bus_id. Replace references to bus_id with dev_name() to fix fhci driver build break. drivers/usb/host/fhci-hcd.c:586: error: struct device has no member named bus_id drivers/usb/host/fhci-hcd.c:653: error: struct device has no member named bus_id drivers/usb/host/fhci-dbg.c:111: error: struct device has no member named bus_id Signed-off-by: Sachin Sant Acked-by: Anton Vorontsov Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/fhci-dbg.c | 2 +- drivers/usb/host/fhci-hcd.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/host/fhci-dbg.c b/drivers/usb/host/fhci-dbg.c index 34e14edf390..ea8a4255c5d 100644 --- a/drivers/usb/host/fhci-dbg.c +++ b/drivers/usb/host/fhci-dbg.c @@ -108,7 +108,7 @@ void fhci_dfs_create(struct fhci_hcd *fhci) { struct device *dev = fhci_to_hcd(fhci)->self.controller; - fhci->dfs_root = debugfs_create_dir(dev->bus_id, NULL); + fhci->dfs_root = debugfs_create_dir(dev_name(dev), NULL); if (!fhci->dfs_root) { WARN_ON(1); return; diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c index ba622cc8a9b..0951818ef93 100644 --- a/drivers/usb/host/fhci-hcd.c +++ b/drivers/usb/host/fhci-hcd.c @@ -583,7 +583,7 @@ static int __devinit of_fhci_probe(struct of_device *ofdev, if (sprop && strcmp(sprop, "host")) return -ENODEV; - hcd = usb_create_hcd(&fhci_driver, dev, dev->bus_id); + hcd = usb_create_hcd(&fhci_driver, dev, dev_name(dev)); if (!hcd) { dev_err(dev, "could not create hcd\n"); return -ENOMEM; @@ -650,7 +650,7 @@ static int __devinit of_fhci_probe(struct of_device *ofdev, } } - ret = gpio_request(gpio, dev->bus_id); + ret = gpio_request(gpio, dev_name(dev)); if (ret) { dev_err(dev, "failed to request gpio %d", i); goto err_gpios; -- cgit v1.2.3 From 1fa5ae857bb14f6046205171d98506d8112dd74e Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Sun, 25 Jan 2009 15:17:37 +0100 Subject: driver core: get rid of struct device's bus_id string array Now that all users of bus_id is gone, we can remove it from struct device. Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index f3eae630e58..059966b617f 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -777,17 +777,12 @@ static void device_remove_class_symlinks(struct device *dev) int dev_set_name(struct device *dev, const char *fmt, ...) { va_list vargs; - char *s; + int err; va_start(vargs, fmt); - vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs); + err = kobject_set_name_vargs(&dev->kobj, fmt, vargs); va_end(vargs); - - /* ewww... some of these buggers have / in the name... */ - while ((s = strchr(dev->bus_id, '/'))) - *s = '!'; - - return 0; + return err; } EXPORT_SYMBOL_GPL(dev_set_name); @@ -864,12 +859,17 @@ int device_add(struct device *dev) if (!dev) goto done; - /* Temporarily support init_name if it is set. - * It will override bus_id for now */ - if (dev->init_name) - dev_set_name(dev, "%s", dev->init_name); + /* + * for statically allocated devices, which should all be converted + * some day, we need to initialize the name. We prevent reading back + * the name, and force the use of dev_name() + */ + if (dev->init_name) { + dev_set_name(dev, dev->init_name); + dev->init_name = NULL; + } - if (!strlen(dev->bus_id)) + if (!dev_name(dev)) goto done; pr_debug("device: '%s': %s\n", dev_name(dev), __func__); @@ -1348,7 +1348,10 @@ struct device *device_create_vargs(struct class *class, struct device *parent, dev->release = device_create_release; dev_set_drvdata(dev, drvdata); - vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args); + retval = kobject_set_name_vargs(&dev->kobj, fmt, args); + if (retval) + goto error; + retval = device_register(dev); if (retval) goto error; @@ -1452,19 +1455,15 @@ int device_rename(struct device *dev, char *new_name) old_class_name = make_class_name(dev->class->name, &dev->kobj); #endif - old_device_name = kmalloc(BUS_ID_SIZE, GFP_KERNEL); + old_device_name = kstrdup(dev_name(dev), GFP_KERNEL); if (!old_device_name) { error = -ENOMEM; goto out; } - strlcpy(old_device_name, dev->bus_id, BUS_ID_SIZE); - strlcpy(dev->bus_id, new_name, BUS_ID_SIZE); error = kobject_rename(&dev->kobj, new_name); - if (error) { - strlcpy(dev->bus_id, old_device_name, BUS_ID_SIZE); + if (error) goto out; - } #ifdef CONFIG_SYSFS_DEPRECATED if (old_class_name) { -- cgit v1.2.3 From 49b420a13ff95b449947181190b08367348e3e1b Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Wed, 21 Jan 2009 23:27:47 +0800 Subject: driver core: check bus->match without holding device lock This patch moves bus->match out from driver_probe_device and does not hold device lock to check the match between a device and a driver. The idea has been verified by the commit 6cd495860901, which leads to a faster boot. But the commit 6cd495860901 has the following drawbacks: 1),only does the quick check in the path of __driver_attach->driver_probe_device, not in other paths; 2),for a matched device and driver, check the same match twice. It is a waste of cpu ,especially for some drivers with long device id table (eg. usb-storage driver). This patch adds a helper of driver_match_device to check the match in all paths, and testes the match only once. Signed-off-by: Ming Lei Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 5 +++++ drivers/base/bus.c | 2 +- drivers/base/dd.c | 19 +++++++------------ 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/base/base.h b/drivers/base/base.h index 9f50f1b545d..ca2b0376685 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -86,6 +86,11 @@ extern void bus_remove_driver(struct device_driver *drv); extern void driver_detach(struct device_driver *drv); extern int driver_probe_device(struct device_driver *drv, struct device *dev); +static inline int driver_match_device(struct device_driver *drv, + struct device *dev) +{ + return drv->bus->match && drv->bus->match(dev, drv); +} extern void sysdev_shutdown(void); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 83f32b891fa..8547b780bb5 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -198,7 +198,7 @@ static ssize_t driver_bind(struct device_driver *drv, int err = -ENODEV; dev = bus_find_device_by_name(bus, NULL, buf); - if (dev && dev->driver == NULL) { + if (dev && dev->driver == NULL && driver_match_device(drv, dev)) { if (dev->parent) /* Needed for USB */ down(&dev->parent->sem); down(&dev->sem); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 13523123910..3f32df7ed37 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -189,14 +189,8 @@ int wait_for_device_probe(void) * @drv: driver to bind a device to * @dev: device to try to bind to the driver * - * First, we call the bus's match function, if one present, which should - * compare the device IDs the driver supports with the device IDs of the - * device. Note we don't do this ourselves because we don't know the - * format of the ID structures, nor what is to be considered a match and - * what is not. - * - * This function returns 1 if a match is found, -ENODEV if the device is - * not registered, and 0 otherwise. + * This function returns -ENODEV if the device is not registered, + * 1 if the device is bound sucessfully and 0 otherwise. * * This function must be called with @dev->sem held. When called for a * USB interface, @dev->parent->sem must be held as well. @@ -207,21 +201,22 @@ int driver_probe_device(struct device_driver *drv, struct device *dev) if (!device_is_registered(dev)) return -ENODEV; - if (drv->bus->match && !drv->bus->match(dev, drv)) - goto done; pr_debug("bus: '%s': %s: matched device %s with driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); ret = really_probe(dev, drv); -done: return ret; } static int __device_attach(struct device_driver *drv, void *data) { struct device *dev = data; + + if (!driver_match_device(drv, dev)) + return 0; + return driver_probe_device(drv, dev); } @@ -274,7 +269,7 @@ static int __driver_attach(struct device *dev, void *data) * is an error. */ - if (drv->bus->match && !drv->bus->match(dev, drv)) + if (!driver_match_device(drv, dev)) return 0; if (dev->parent) /* Needed for USB */ -- cgit v1.2.3 From 71b3e0c1ad90f28e34c105069175cbd4edb43dfa Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Sat, 31 Jan 2009 22:47:44 +0800 Subject: platform: make better use of to_platform_{device,driver}() macros This helps the code look more consistent and cleaner. Signed-off-by: Eric Miao Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 21 +++++++++------------ drivers/block/floppy.c | 3 +-- drivers/isdn/gigaset/ser-gigaset.c | 3 +-- 3 files changed, 11 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 349a1013603..62a8768d96b 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -603,9 +603,8 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) */ static int platform_match(struct device *dev, struct device_driver *drv) { - struct platform_device *pdev; + struct platform_device *pdev = to_platform_device(dev); - pdev = container_of(dev, struct platform_device, dev); return (strcmp(pdev->name, drv->name) == 0); } @@ -623,26 +622,24 @@ static int platform_legacy_suspend(struct device *dev, pm_message_t mesg) static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg) { - struct platform_driver *drv = to_platform_driver(dev->driver); - struct platform_device *pdev; + struct platform_driver *pdrv = to_platform_driver(dev->driver); + struct platform_device *pdev = to_platform_device(dev); int ret = 0; - pdev = container_of(dev, struct platform_device, dev); - if (dev->driver && drv->suspend_late) - ret = drv->suspend_late(pdev, mesg); + if (dev->driver && pdrv->suspend_late) + ret = pdrv->suspend_late(pdev, mesg); return ret; } static int platform_legacy_resume_early(struct device *dev) { - struct platform_driver *drv = to_platform_driver(dev->driver); - struct platform_device *pdev; + struct platform_driver *pdrv = to_platform_driver(dev->driver); + struct platform_device *pdev = to_platform_device(dev); int ret = 0; - pdev = container_of(dev, struct platform_device, dev); - if (dev->driver && drv->resume_early) - ret = drv->resume_early(pdev); + if (dev->driver && pdrv->resume_early) + ret = pdrv->resume_early(pdev); return ret; } diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 83d8ed39433..c2c95e61450 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -4135,10 +4135,9 @@ static int have_no_fdc = -ENODEV; static ssize_t floppy_cmos_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct platform_device *p; + struct platform_device *p = to_platform_device(dev); int drive; - p = container_of(dev, struct platform_device,dev); drive = p->id; return sprintf(buf, "%X\n", UDP->cmos); } diff --git a/drivers/isdn/gigaset/ser-gigaset.c b/drivers/isdn/gigaset/ser-gigaset.c index ac245e7e96a..3071a52467e 100644 --- a/drivers/isdn/gigaset/ser-gigaset.c +++ b/drivers/isdn/gigaset/ser-gigaset.c @@ -389,8 +389,7 @@ static void gigaset_freecshw(struct cardstate *cs) static void gigaset_device_release(struct device *dev) { - struct platform_device *pdev = - container_of(dev, struct platform_device, dev); + struct platform_device *pdev = to_platform_device(dev); /* adapted from platform_device_release() in drivers/base/platform.c */ //FIXME is this actually necessary? -- cgit v1.2.3 From 57fee4a58fe802272742caae248872c392a60670 Mon Sep 17 00:00:00 2001 From: Eric Miao Date: Wed, 4 Feb 2009 11:52:40 +0800 Subject: platform: introduce module id table for platform devices Now platform_device is being widely used on SoC processors where the peripherals are attached to the system bus, which is simple enough. However, silicon IPs for these SoCs are usually shared heavily across a family of processors, even products from different companies. This makes the original simple driver name based matching insufficient, or simply not straight-forward. Introduce a module id table for platform devices, and makes it clear that a platform driver is able to support some shared IP and handle slight differences across different platforms (by 'driver_data'). Module alias is handled automatically when a MODULE_DEVICE_TABLE() is defined. To not disturb the current platform drivers too much, the matched id entry is recorded and can be retrieved by platform_get_device_id(). Signed-off-by: Eric Miao Cc: Kay Sievers Cc: Ben Dooks Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 62a8768d96b..ec993aa6a2c 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -584,10 +584,25 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) { struct platform_device *pdev = to_platform_device(dev); - add_uevent_var(env, "MODALIAS=platform:%s", pdev->name); + add_uevent_var(env, "MODALIAS=%s%s", PLATFORM_MODULE_PREFIX, + (pdev->id_entry) ? pdev->id_entry->name : pdev->name); return 0; } +static const struct platform_device_id *platform_match_id( + struct platform_device_id *id, + struct platform_device *pdev) +{ + while (id->name[0]) { + if (strcmp(pdev->name, id->name) == 0) { + pdev->id_entry = id; + return id; + } + id++; + } + return NULL; +} + /** * platform_match - bind platform device to platform driver. * @dev: device. @@ -604,7 +619,13 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) static int platform_match(struct device *dev, struct device_driver *drv) { struct platform_device *pdev = to_platform_device(dev); + struct platform_driver *pdrv = to_platform_driver(drv); + + /* match against the id table first */ + if (pdrv->id_table) + return platform_match_id(pdrv->id_table, pdev) != NULL; + /* fall-back to driver name match */ return (strcmp(pdev->name, drv->name) == 0); } -- cgit v1.2.3 From 8205779114e8f612549d191f8e151526a74ab9f2 Mon Sep 17 00:00:00 2001 From: "Hans J. Koch" Date: Wed, 7 Jan 2009 00:15:39 +0100 Subject: UIO: Add name attributes for mappings and port regions If a UIO device has several memory mappings, it can be difficult for userspace to find the right one. The situation becomes even worse if the UIO driver can handle different versions of a card that have different numbers of mappings. Benedikt Spranger has such cards and pointed this out to me. Thanks, Bene! To address this problem, this patch adds "name" sysfs attributes for each mapping. Userspace can use these to clearly identify each mapping. The name string is optional. If a driver doesn't set it, an empty string will be returned, so this patch won't break existing drivers. The same problem exists for port region information, so a "name" attribute is added there, too. Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'drivers') diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 4ca85a113aa..68a49655778 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -61,6 +61,14 @@ struct uio_map { }; #define to_map(map) container_of(map, struct uio_map, kobj) +static ssize_t map_name_show(struct uio_mem *mem, char *buf) +{ + if (unlikely(!mem->name)) + mem->name = ""; + + return sprintf(buf, "%s\n", mem->name); +} + static ssize_t map_addr_show(struct uio_mem *mem, char *buf) { return sprintf(buf, "0x%lx\n", mem->addr); @@ -82,6 +90,8 @@ struct map_sysfs_entry { ssize_t (*store)(struct uio_mem *, const char *, size_t); }; +static struct map_sysfs_entry name_attribute = + __ATTR(name, S_IRUGO, map_name_show, NULL); static struct map_sysfs_entry addr_attribute = __ATTR(addr, S_IRUGO, map_addr_show, NULL); static struct map_sysfs_entry size_attribute = @@ -90,6 +100,7 @@ static struct map_sysfs_entry offset_attribute = __ATTR(offset, S_IRUGO, map_offset_show, NULL); static struct attribute *attrs[] = { + &name_attribute.attr, &addr_attribute.attr, &size_attribute.attr, &offset_attribute.attr, @@ -133,6 +144,14 @@ struct uio_portio { }; #define to_portio(portio) container_of(portio, struct uio_portio, kobj) +static ssize_t portio_name_show(struct uio_port *port, char *buf) +{ + if (unlikely(!port->name)) + port->name = ""; + + return sprintf(buf, "%s\n", port->name); +} + static ssize_t portio_start_show(struct uio_port *port, char *buf) { return sprintf(buf, "0x%lx\n", port->start); @@ -159,6 +178,8 @@ struct portio_sysfs_entry { ssize_t (*store)(struct uio_port *, const char *, size_t); }; +static struct portio_sysfs_entry portio_name_attribute = + __ATTR(name, S_IRUGO, portio_name_show, NULL); static struct portio_sysfs_entry portio_start_attribute = __ATTR(start, S_IRUGO, portio_start_show, NULL); static struct portio_sysfs_entry portio_size_attribute = @@ -167,6 +188,7 @@ static struct portio_sysfs_entry portio_porttype_attribute = __ATTR(porttype, S_IRUGO, portio_porttype_show, NULL); static struct attribute *portio_attrs[] = { + &portio_name_attribute.attr, &portio_start_attribute.attr, &portio_size_attribute.attr, &portio_porttype_attribute.attr, -- cgit v1.2.3 From 1bafeb378e915f39b1bf44ee0871823d6f402ea5 Mon Sep 17 00:00:00 2001 From: Brandon Philips Date: Tue, 27 Jan 2009 13:00:04 -0800 Subject: uio: add the uio_aec driver UIO driver for the Adrienne Electronics Corporation PCI time code device. This device differs from other UIO devices since it uses I/O ports instead of memory mapped I/O. In order to make it possible for UIO to work with this device a utility, uioport, can be used to read and write the ports. uioport is designed to be a setuid program and checks the permissions of the /dev/uio* node and if the user has write permissions it will use iopl and out*/in* to access the device. [1] git clone git://ifup.org/philips/uioport.git Signed-off-by: Brandon Philips Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/Kconfig | 18 ++++++ drivers/uio/Makefile | 1 + drivers/uio/uio_aec.c | 175 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 194 insertions(+) create mode 100644 drivers/uio/uio_aec.c (limited to 'drivers') diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 04b954cfce7..7f86534de26 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -58,6 +58,24 @@ config UIO_SMX If you compile this as a module, it will be called uio_smx. +config UIO_AEC + tristate "AEC video timestamp device" + depends on PCI + default n + help + + UIO driver for the Adrienne Electronics Corporation PCI time + code device. + + This device differs from other UIO devices since it uses I/O + ports instead of memory mapped I/O. In order to make it + possible for UIO to work with this device a utility, uioport, + can be used to read and write the ports: + + git clone git://ifup.org/philips/uioport.git + + If you compile this as a module, it will be called uio_aec. + config UIO_SERCOS3 tristate "Automata Sercos III PCI card driver" default n diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index e6955814985..5c2586d7579 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile @@ -3,4 +3,5 @@ obj-$(CONFIG_UIO_CIF) += uio_cif.o obj-$(CONFIG_UIO_PDRV) += uio_pdrv.o obj-$(CONFIG_UIO_PDRV_GENIRQ) += uio_pdrv_genirq.o obj-$(CONFIG_UIO_SMX) += uio_smx.o +obj-$(CONFIG_UIO_AEC) += uio_aec.o obj-$(CONFIG_UIO_SERCOS3) += uio_sercos3.o diff --git a/drivers/uio/uio_aec.c b/drivers/uio/uio_aec.c new file mode 100644 index 00000000000..b7830e9a3ba --- /dev/null +++ b/drivers/uio/uio_aec.c @@ -0,0 +1,175 @@ +/* + * uio_aec.c -- simple driver for Adrienne Electronics Corp time code PCI device + * + * Copyright (C) 2008 Brandon Philips + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., 59 + * Temple Place, Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCI_VENDOR_ID_AEC 0xaecb +#define PCI_DEVICE_ID_AEC_VITCLTC 0x6250 + +#define INT_ENABLE_ADDR 0xFC +#define INT_ENABLE 0x10 +#define INT_DISABLE 0x0 + +#define INT_MASK_ADDR 0x2E +#define INT_MASK_ALL 0x3F + +#define INTA_DRVR_ADDR 0xFE +#define INTA_ENABLED_FLAG 0x08 +#define INTA_FLAG 0x01 + +#define MAILBOX 0x0F + +static struct pci_device_id ids[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AEC, PCI_DEVICE_ID_AEC_VITCLTC), }, + { 0, } +}; +MODULE_DEVICE_TABLE(pci, ids); + +static irqreturn_t aectc_irq(int irq, struct uio_info *dev_info) +{ + void __iomem *int_flag = dev_info->priv + INTA_DRVR_ADDR; + unsigned char status = ioread8(int_flag); + + + if ((status & INTA_ENABLED_FLAG) && (status & INTA_FLAG)) { + /* application writes 0x00 to 0x2F to get next interrupt */ + status = ioread8(dev_info->priv + MAILBOX); + return IRQ_HANDLED; + } + + return IRQ_NONE; +} + +static void print_board_data(struct pci_dev *pdev, struct uio_info *i) +{ + dev_info(&pdev->dev, "PCI-TC board vendor: %x%x number: %x%x" + " revision: %c%c\n", + ioread8(i->priv + 0x01), + ioread8(i->priv + 0x00), + ioread8(i->priv + 0x03), + ioread8(i->priv + 0x02), + ioread8(i->priv + 0x06), + ioread8(i->priv + 0x07)); +} + +static int __devinit probe(struct pci_dev *pdev, const struct pci_device_id *id) +{ + struct uio_info *info; + int ret; + + info = kzalloc(sizeof(struct uio_info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + if (pci_enable_device(pdev)) + goto out_free; + + if (pci_request_regions(pdev, "aectc")) + goto out_disable; + + info->name = "aectc"; + info->port[0].start = pci_resource_start(pdev, 0); + if (!info->port[0].start) + goto out_release; + info->priv = pci_iomap(pdev, 0, 0); + if (!info->priv) + goto out_release; + info->port[0].size = pci_resource_len(pdev, 0); + info->port[0].porttype = UIO_PORT_GPIO; + + info->version = "0.0.1"; + info->irq = pdev->irq; + info->irq_flags = IRQF_SHARED; + info->handler = aectc_irq; + + print_board_data(pdev, info); + ret = uio_register_device(&pdev->dev, info); + if (ret) + goto out_unmap; + + iowrite32(INT_ENABLE, info->priv + INT_ENABLE_ADDR); + iowrite8(INT_MASK_ALL, info->priv + INT_MASK_ADDR); + if (!(ioread8(info->priv + INTA_DRVR_ADDR) + & INTA_ENABLED_FLAG)) + dev_err(&pdev->dev, "aectc: interrupts not enabled\n"); + + pci_set_drvdata(pdev, info); + + return 0; + +out_unmap: + pci_iounmap(pdev, info->priv); +out_release: + pci_release_regions(pdev); +out_disable: + pci_disable_device(pdev); +out_free: + kfree(info); + return -ENODEV; +} + +static void remove(struct pci_dev *pdev) +{ + struct uio_info *info = pci_get_drvdata(pdev); + + /* disable interrupts */ + iowrite8(INT_DISABLE, info->priv + INT_MASK_ADDR); + iowrite32(INT_DISABLE, info->priv + INT_ENABLE_ADDR); + /* read mailbox to ensure board drops irq */ + ioread8(info->priv + MAILBOX); + + uio_unregister_device(info); + pci_release_regions(pdev); + pci_disable_device(pdev); + pci_set_drvdata(pdev, NULL); + iounmap(info->priv); + + kfree(info); +} + +static struct pci_driver pci_driver = { + .name = "aectc", + .id_table = ids, + .probe = probe, + .remove = remove, +}; + +static int __init aectc_init(void) +{ + return pci_register_driver(&pci_driver); +} + +static void __exit aectc_exit(void) +{ + pci_unregister_driver(&pci_driver); +} + +MODULE_LICENSE("GPL"); + +module_init(aectc_init); +module_exit(aectc_exit); -- cgit v1.2.3 From 6da2d377bba06c29d0bc41c8dee014164dec82a7 Mon Sep 17 00:00:00 2001 From: Ian Abbott Date: Tue, 24 Feb 2009 17:22:59 +0000 Subject: UIO: Take offset into account when determining number of pages that can be mapped If a UIO memory region does not start on a page boundary but straddles one, the number of actual pages that overlap the memory region may be calculated incorrectly because the offset isn't taken into account. If userspace sets the mmap length to offset+size, it may fail with -EINVAL if UIO thinks it's trying to allocate too many pages. Signed-off-by: Ian Abbott Cc: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/uio/uio.c b/drivers/uio/uio.c index 68a49655778..03efb065455 100644 --- a/drivers/uio/uio.c +++ b/drivers/uio/uio.c @@ -708,7 +708,8 @@ static int uio_mmap(struct file *filep, struct vm_area_struct *vma) return -EINVAL; requested_pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; - actual_pages = (idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT; + actual_pages = ((idev->info->mem[mi].addr & ~PAGE_MASK) + + idev->info->mem[mi].size + PAGE_SIZE -1) >> PAGE_SHIFT; if (requested_pages > actual_pages) return -EINVAL; -- cgit v1.2.3 From 7a192ec334cab9fafe3a8665a65af398b0e24730 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 6 Feb 2009 23:40:12 +0800 Subject: platform driver: fix incorrect use of 'platform_bus_type' with 'struct device_driver' This patch fixes the bug reported in http://bugzilla.kernel.org/show_bug.cgi?id=11681. "Lots of device drivers register a 'struct device_driver' with the '.bus' member set to '&platform_bus_type'. This is wrong, since the platform_bus functions expect the 'struct device_driver' to be wrapped up in a 'struct platform_driver' which provides some additional callbacks (like suspend_late, resume_early). The effect may be that platform_suspend_late() uses bogus data outside the device_driver struct as a pointer pointer to the device driver's suspend_late() function or other hard to reproduce failures."(Lothar Wassmann) Signed-off-by: Ming Lei Acked-by: Henrique de Moraes Holschuh Acked-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/char/tpm/tpm_atmel.c | 28 ++++++++++++++++++--------- drivers/char/tpm/tpm_tis.c | 28 ++++++++++++++++++--------- drivers/ide/au1xxx-ide.c | 36 +++++++++++++++++------------------ drivers/mtd/maps/pxa2xx-flash.c | 37 ++++++++++++++++++------------------ drivers/mtd/nand/excite_nandflash.c | 25 ++++++++++++------------ drivers/mtd/onenand/generic.c | 26 ++++++++++++------------- drivers/net/mipsnet.c | 26 +++++++++++++------------ drivers/pcmcia/au1000_generic.c | 37 +++++++++++++++++++++++------------- drivers/pcmcia/i82365.c | 28 +++++++++++++++++++-------- drivers/pcmcia/m32r_cfc.c | 30 ++++++++++++++++++++--------- drivers/pcmcia/m32r_pcc.c | 30 ++++++++++++++++++++--------- drivers/pcmcia/sa1100_generic.c | 38 +++++++++++++++++++++++++++---------- drivers/pcmcia/tcic.c | 30 ++++++++++++++++++++--------- drivers/pcmcia/vrc4171_card.c | 34 +++++++++++++++++++++++---------- drivers/scsi/a4000t.c | 26 +++++++++++++------------ drivers/scsi/bvme6000_scsi.c | 26 +++++++++++++------------ drivers/scsi/mvme16x_scsi.c | 26 +++++++++++++------------ drivers/video/au1100fb.c | 31 +++++++++++++++--------------- drivers/video/au1200fb.c | 25 +++++++++++++----------- drivers/watchdog/rm9k_wdt.c | 27 ++++++++++++-------------- 20 files changed, 358 insertions(+), 236 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index d0e7926eb48..c64a1bc6534 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c @@ -168,12 +168,22 @@ static void atml_plat_remove(void) } } -static struct device_driver atml_drv = { - .name = "tpm_atmel", - .bus = &platform_bus_type, - .owner = THIS_MODULE, - .suspend = tpm_pm_suspend, - .resume = tpm_pm_resume, +static int tpm_atml_suspend(struct platform_device *dev, pm_message_t msg) +{ + return tpm_pm_suspend(&dev->dev, msg); +} + +static int tpm_atml_resume(struct platform_device *dev) +{ + return tpm_pm_resume(&dev->dev); +} +static struct platform_driver atml_drv = { + .driver = { + .name = "tpm_atmel", + .owner = THIS_MODULE, + }, + .suspend = tpm_atml_suspend, + .resume = tpm_atml_resume, }; static int __init init_atmel(void) @@ -184,7 +194,7 @@ static int __init init_atmel(void) unsigned long base; struct tpm_chip *chip; - rc = driver_register(&atml_drv); + rc = platform_driver_register(&atml_drv); if (rc) return rc; @@ -223,13 +233,13 @@ err_rel_reg: atmel_release_region(base, region_size); err_unreg_drv: - driver_unregister(&atml_drv); + platform_driver_unregister(&atml_drv); return rc; } static void __exit cleanup_atmel(void) { - driver_unregister(&atml_drv); + platform_driver_unregister(&atml_drv); atml_plat_remove(); } diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index 717af7ad1bd..aec1931608a 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c @@ -654,12 +654,22 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); -static struct device_driver tis_drv = { - .name = "tpm_tis", - .bus = &platform_bus_type, - .owner = THIS_MODULE, - .suspend = tpm_pm_suspend, - .resume = tpm_pm_resume, +static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) +{ + return tpm_pm_suspend(&dev->dev, msg); +} + +static int tpm_tis_resume(struct platform_device *dev) +{ + return tpm_pm_resume(&dev->dev); +} +static struct platform_driver tis_drv = { + .driver = { + .name = "tpm_tis", + .owner = THIS_MODULE, + }, + .suspend = tpm_tis_suspend, + .resume = tpm_tis_resume, }; static struct platform_device *pdev; @@ -672,14 +682,14 @@ static int __init init_tis(void) int rc; if (force) { - rc = driver_register(&tis_drv); + rc = platform_driver_register(&tis_drv); if (rc < 0) return rc; if (IS_ERR(pdev=platform_device_register_simple("tpm_tis", -1, NULL, 0))) return PTR_ERR(pdev); if((rc=tpm_tis_init(&pdev->dev, TIS_MEM_BASE, TIS_MEM_LEN, 0)) != 0) { platform_device_unregister(pdev); - driver_unregister(&tis_drv); + platform_driver_unregister(&tis_drv); } return rc; } @@ -711,7 +721,7 @@ static void __exit cleanup_tis(void) if (force) { platform_device_unregister(pdev); - driver_unregister(&tis_drv); + platform_driver_unregister(&tis_drv); } else pnp_unregister_driver(&tis_pnp_driver); } diff --git a/drivers/ide/au1xxx-ide.c b/drivers/ide/au1xxx-ide.c index 79a2dfed8eb..154ec2cf734 100644 --- a/drivers/ide/au1xxx-ide.c +++ b/drivers/ide/au1xxx-ide.c @@ -536,9 +536,8 @@ static const struct ide_port_info au1xxx_port_info = { #endif }; -static int au_ide_probe(struct device *dev) +static int au_ide_probe(struct platform_device *dev) { - struct platform_device *pdev = to_platform_device(dev); _auide_hwif *ahwif = &auide_hwif; struct resource *res; struct ide_host *host; @@ -552,23 +551,23 @@ static int au_ide_probe(struct device *dev) #endif memset(&auide_hwif, 0, sizeof(_auide_hwif)); - ahwif->irq = platform_get_irq(pdev, 0); + ahwif->irq = platform_get_irq(dev, 0); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource(dev, IORESOURCE_MEM, 0); if (res == NULL) { - pr_debug("%s %d: no base address\n", DRV_NAME, pdev->id); + pr_debug("%s %d: no base address\n", DRV_NAME, dev->id); ret = -ENODEV; goto out; } if (ahwif->irq < 0) { - pr_debug("%s %d: no IRQ\n", DRV_NAME, pdev->id); + pr_debug("%s %d: no IRQ\n", DRV_NAME, dev->id); ret = -ENODEV; goto out; } if (!request_mem_region(res->start, res->end - res->start + 1, - pdev->name)) { + dev->name)) { pr_debug("%s: request_mem_region failed\n", DRV_NAME); ret = -EBUSY; goto out; @@ -583,7 +582,7 @@ static int au_ide_probe(struct device *dev) memset(&hw, 0, sizeof(hw)); auide_setup_ports(&hw, ahwif); hw.irq = ahwif->irq; - hw.dev = dev; + hw.dev = &dev->dev; hw.chipset = ide_au1xxx; ret = ide_host_add(&au1xxx_port_info, hws, &host); @@ -592,7 +591,7 @@ static int au_ide_probe(struct device *dev) auide_hwif.hwif = host->ports[0]; - dev_set_drvdata(dev, host); + platform_set_drvdata(dev, host); printk(KERN_INFO "Au1xxx IDE(builtin) configured for %s\n", mode ); @@ -600,38 +599,39 @@ static int au_ide_probe(struct device *dev) return ret; } -static int au_ide_remove(struct device *dev) +static int au_ide_remove(struct platform_device *dev) { - struct platform_device *pdev = to_platform_device(dev); struct resource *res; - struct ide_host *host = dev_get_drvdata(dev); + struct ide_host *host = platform_get_drvdata(dev); _auide_hwif *ahwif = &auide_hwif; ide_host_remove(host); iounmap((void *)ahwif->regbase); - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource(dev, IORESOURCE_MEM, 0); release_mem_region(res->start, res->end - res->start + 1); return 0; } -static struct device_driver au1200_ide_driver = { - .name = "au1200-ide", - .bus = &platform_bus_type, +static struct platform_driver au1200_ide_driver = { + .driver = { + .name = "au1200-ide", + .owner = THIS_MODULE, + }, .probe = au_ide_probe, .remove = au_ide_remove, }; static int __init au_ide_init(void) { - return driver_register(&au1200_ide_driver); + return platform_driver_register(&au1200_ide_driver); } static void __exit au_ide_exit(void) { - driver_unregister(&au1200_ide_driver); + platform_driver_unregister(&au1200_ide_driver); } MODULE_LICENSE("GPL"); diff --git a/drivers/mtd/maps/pxa2xx-flash.c b/drivers/mtd/maps/pxa2xx-flash.c index 771139c5bf8..e9026cb1c5b 100644 --- a/drivers/mtd/maps/pxa2xx-flash.c +++ b/drivers/mtd/maps/pxa2xx-flash.c @@ -41,9 +41,8 @@ struct pxa2xx_flash_info { static const char *probes[] = { "RedBoot", "cmdlinepart", NULL }; -static int __init pxa2xx_flash_probe(struct device *dev) +static int __init pxa2xx_flash_probe(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); struct flash_platform_data *flash = pdev->dev.platform_data; struct pxa2xx_flash_info *info; struct mtd_partition *parts; @@ -114,15 +113,15 @@ static int __init pxa2xx_flash_probe(struct device *dev) add_mtd_device(info->mtd); } - dev_set_drvdata(dev, info); + platform_set_drvdata(pdev, info); return 0; } -static int __exit pxa2xx_flash_remove(struct device *dev) +static int __exit pxa2xx_flash_remove(struct platform_device *dev) { - struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + struct pxa2xx_flash_info *info = platform_get_drvdata(dev); - dev_set_drvdata(dev, NULL); + platform_set_drvdata(dev, NULL); #ifdef CONFIG_MTD_PARTITIONS if (info->nr_parts) @@ -141,9 +140,9 @@ static int __exit pxa2xx_flash_remove(struct device *dev) } #ifdef CONFIG_PM -static int pxa2xx_flash_suspend(struct device *dev, pm_message_t state) +static int pxa2xx_flash_suspend(struct platform_device *dev, pm_message_t state) { - struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + struct pxa2xx_flash_info *info = platform_get_drvdata(dev); int ret = 0; if (info->mtd && info->mtd->suspend) @@ -151,17 +150,17 @@ static int pxa2xx_flash_suspend(struct device *dev, pm_message_t state) return ret; } -static int pxa2xx_flash_resume(struct device *dev) +static int pxa2xx_flash_resume(struct platform_device *dev) { - struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + struct pxa2xx_flash_info *info = platform_get_drvdata(dev); if (info->mtd && info->mtd->resume) info->mtd->resume(info->mtd); return 0; } -static void pxa2xx_flash_shutdown(struct device *dev) +static void pxa2xx_flash_shutdown(struct platform_device *dev) { - struct pxa2xx_flash_info *info = dev_get_drvdata(dev); + struct pxa2xx_flash_info *info = platform_get_drvdata(dev); if (info && info->mtd->suspend(info->mtd) == 0) info->mtd->resume(info->mtd); @@ -172,11 +171,13 @@ static void pxa2xx_flash_shutdown(struct device *dev) #define pxa2xx_flash_shutdown NULL #endif -static struct device_driver pxa2xx_flash_driver = { - .name = "pxa2xx-flash", - .bus = &platform_bus_type, +static struct platform_driver pxa2xx_flash_driver = { + .driver = { + .name = "pxa2xx-flash", + .owner = THIS_MODULE, + }, .probe = pxa2xx_flash_probe, - .remove = __exit_p(pxa2xx_flash_remove), + .remove = __devexit_p(pxa2xx_flash_remove), .suspend = pxa2xx_flash_suspend, .resume = pxa2xx_flash_resume, .shutdown = pxa2xx_flash_shutdown, @@ -184,12 +185,12 @@ static struct device_driver pxa2xx_flash_driver = { static int __init init_pxa2xx_flash(void) { - return driver_register(&pxa2xx_flash_driver); + return platform_driver_register(&pxa2xx_flash_driver); } static void __exit cleanup_pxa2xx_flash(void) { - driver_unregister(&pxa2xx_flash_driver); + platform_driver_unregister(&pxa2xx_flash_driver); } module_init(init_pxa2xx_flash); diff --git a/drivers/mtd/nand/excite_nandflash.c b/drivers/mtd/nand/excite_nandflash.c index ced14b5294d..72446fb48d4 100644 --- a/drivers/mtd/nand/excite_nandflash.c +++ b/drivers/mtd/nand/excite_nandflash.c @@ -128,11 +128,11 @@ static int excite_nand_devready(struct mtd_info *mtd) * The binding to the mtd and all allocated * resources are released. */ -static int __exit excite_nand_remove(struct device *dev) +static int __exit excite_nand_remove(struct platform_device *dev) { - struct excite_nand_drvdata * const this = dev_get_drvdata(dev); + struct excite_nand_drvdata * const this = platform_get_drvdata(dev); - dev_set_drvdata(dev, NULL); + platform_set_drvdata(dev, NULL); if (unlikely(!this)) { printk(KERN_ERR "%s: called %s without private data!!", @@ -159,9 +159,8 @@ static int __exit excite_nand_remove(struct device *dev) * it can allocate all necessary resources then calls the * nand layer to look for devices. */ -static int __init excite_nand_probe(struct device *dev) +static int __init excite_nand_probe(struct platform_device *pdev) { - struct platform_device * const pdev = to_platform_device(dev); struct excite_nand_drvdata *drvdata; /* private driver data */ struct nand_chip *board_chip; /* private flash chip data */ struct mtd_info *board_mtd; /* mtd info for this board */ @@ -175,7 +174,7 @@ static int __init excite_nand_probe(struct device *dev) } /* bind private data into driver */ - dev_set_drvdata(dev, drvdata); + platform_set_drvdata(pdev, drvdata); /* allocate and map the resource */ drvdata->regs = @@ -219,23 +218,25 @@ static int __init excite_nand_probe(struct device *dev) return 0; } -static struct device_driver excite_nand_driver = { - .name = "excite_nand", - .bus = &platform_bus_type, +static struct platform_driver excite_nand_driver = { + .driver = { + .name = "excite_nand", + .owner = THIS_MODULE, + }, .probe = excite_nand_probe, - .remove = __exit_p(excite_nand_remove) + .remove = __devexit_p(excite_nand_remove) }; static int __init excite_nand_init(void) { pr_info("Basler eXcite nand flash driver Version " EXCITE_NANDFLASH_VERSION "\n"); - return driver_register(&excite_nand_driver); + return platform_driver_register(&excite_nand_driver); } static void __exit excite_nand_exit(void) { - driver_unregister(&excite_nand_driver); + platform_driver_unregister(&excite_nand_driver); } module_init(excite_nand_init); diff --git a/drivers/mtd/onenand/generic.c b/drivers/mtd/onenand/generic.c index 5b69e7773c6..3a496c33fb5 100644 --- a/drivers/mtd/onenand/generic.c +++ b/drivers/mtd/onenand/generic.c @@ -36,10 +36,9 @@ struct onenand_info { struct onenand_chip onenand; }; -static int __devinit generic_onenand_probe(struct device *dev) +static int __devinit generic_onenand_probe(struct platform_device *pdev) { struct onenand_info *info; - struct platform_device *pdev = to_platform_device(dev); struct flash_platform_data *pdata = pdev->dev.platform_data; struct resource *res = pdev->resource; unsigned long size = res->end - res->start + 1; @@ -49,7 +48,7 @@ static int __devinit generic_onenand_probe(struct device *dev) if (!info) return -ENOMEM; - if (!request_mem_region(res->start, size, dev->driver->name)) { + if (!request_mem_region(res->start, size, pdev->dev.driver->name)) { err = -EBUSY; goto out_free_info; } @@ -82,7 +81,7 @@ static int __devinit generic_onenand_probe(struct device *dev) #endif err = add_mtd_device(&info->mtd); - dev_set_drvdata(&pdev->dev, info); + platform_set_drvdata(pdev, info); return 0; @@ -96,14 +95,13 @@ out_free_info: return err; } -static int __devexit generic_onenand_remove(struct device *dev) +static int __devexit generic_onenand_remove(struct platform_device *pdev) { - struct platform_device *pdev = to_platform_device(dev); - struct onenand_info *info = dev_get_drvdata(&pdev->dev); + struct onenand_info *info = platform_get_drvdata(pdev); struct resource *res = pdev->resource; unsigned long size = res->end - res->start + 1; - dev_set_drvdata(&pdev->dev, NULL); + platform_set_drvdata(pdev, NULL); if (info) { if (info->parts) @@ -120,9 +118,11 @@ static int __devexit generic_onenand_remove(struct device *dev) return 0; } -static struct device_driver generic_onenand_driver = { - .name = DRIVER_NAME, - .bus = &platform_bus_type, +static struct platform_driver generic_onenand_driver = { + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, .probe = generic_onenand_probe, .remove = __devexit_p(generic_onenand_remove), }; @@ -131,12 +131,12 @@ MODULE_ALIAS(DRIVER_NAME); static int __init generic_onenand_init(void) { - return driver_register(&generic_onenand_driver); + return platform_driver_register(&generic_onenand_driver); } static void __exit generic_onenand_exit(void) { - driver_unregister(&generic_onenand_driver); + platform_driver_unregister(&generic_onenand_driver); } module_init(generic_onenand_init); diff --git a/drivers/net/mipsnet.c b/drivers/net/mipsnet.c index 4e7a5faf035..664835b822f 100644 --- a/drivers/net/mipsnet.c +++ b/drivers/net/mipsnet.c @@ -237,7 +237,7 @@ static void mipsnet_set_mclist(struct net_device *dev) { } -static int __init mipsnet_probe(struct device *dev) +static int __init mipsnet_probe(struct platform_device *dev) { struct net_device *netdev; int err; @@ -248,7 +248,7 @@ static int __init mipsnet_probe(struct device *dev) goto out; } - dev_set_drvdata(dev, netdev); + platform_set_drvdata(dev, netdev); netdev->open = mipsnet_open; netdev->stop = mipsnet_close; @@ -293,23 +293,25 @@ out: return err; } -static int __devexit mipsnet_device_remove(struct device *device) +static int __devexit mipsnet_device_remove(struct platform_device *device) { - struct net_device *dev = dev_get_drvdata(device); + struct net_device *dev = platform_get_drvdata(device); unregister_netdev(dev); release_region(dev->base_addr, sizeof(struct mipsnet_regs)); free_netdev(dev); - dev_set_drvdata(device, NULL); + platform_set_drvdata(device, NULL); return 0; } -static struct device_driver mipsnet_driver = { - .name = mipsnet_string, - .bus = &platform_bus_type, - .probe = mipsnet_probe, - .remove = __devexit_p(mipsnet_device_remove), +static struct platform_driver mipsnet_driver = { + .driver = { + .name = mipsnet_string, + .owner = THIS_MODULE, + }, + .probe = mipsnet_probe, + .remove = __devexit_p(mipsnet_device_remove), }; static int __init mipsnet_init_module(void) @@ -319,7 +321,7 @@ static int __init mipsnet_init_module(void) printk(KERN_INFO "MIPSNet Ethernet driver. Version: %s. " "(c)2005 MIPS Technologies, Inc.\n", MIPSNET_VERSION); - err = driver_register(&mipsnet_driver); + err = platform_driver_register(&mipsnet_driver); if (err) printk(KERN_ERR "Driver registration failed\n"); @@ -328,7 +330,7 @@ static int __init mipsnet_init_module(void) static void __exit mipsnet_exit_module(void) { - driver_unregister(&mipsnet_driver); + platform_driver_unregister(&mipsnet_driver); } module_init(mipsnet_init_module); diff --git a/drivers/pcmcia/au1000_generic.c b/drivers/pcmcia/au1000_generic.c index fc1de46fd20..90013341cd5 100644 --- a/drivers/pcmcia/au1000_generic.c +++ b/drivers/pcmcia/au1000_generic.c @@ -468,13 +468,13 @@ out: return ret; } -int au1x00_drv_pcmcia_remove(struct device *dev) +int au1x00_drv_pcmcia_remove(struct platform_device *dev) { - struct skt_dev_info *sinfo = dev_get_drvdata(dev); + struct skt_dev_info *sinfo = platform_get_drvdata(dev); int i; mutex_lock(&pcmcia_sockets_lock); - dev_set_drvdata(dev, NULL); + platform_set_drvdata(dev, NULL); for (i = 0; i < sinfo->nskt; i++) { struct au1000_pcmcia_socket *skt = PCMCIA_SOCKET(i); @@ -498,13 +498,13 @@ int au1x00_drv_pcmcia_remove(struct device *dev) * PCMCIA "Driver" API */ -static int au1x00_drv_pcmcia_probe(struct device *dev) +static int au1x00_drv_pcmcia_probe(struct platform_device *dev) { int i, ret = -ENODEV; mutex_lock(&pcmcia_sockets_lock); for (i=0; i < ARRAY_SIZE(au1x00_pcmcia_hw_init); i++) { - ret = au1x00_pcmcia_hw_init[i](dev); + ret = au1x00_pcmcia_hw_init[i](&dev->dev); if (ret == 0) break; } @@ -512,14 +512,26 @@ static int au1x00_drv_pcmcia_probe(struct device *dev) return ret; } +static int au1x00_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int au1x00_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} -static struct device_driver au1x00_pcmcia_driver = { +static struct platform_driver au1x00_pcmcia_driver = { + .driver = { + .name = "au1x00-pcmcia", + .owner = THIS_MODULE, + }, .probe = au1x00_drv_pcmcia_probe, .remove = au1x00_drv_pcmcia_remove, - .name = "au1x00-pcmcia", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, + .suspend = au1x00_drv_pcmcia_suspend, + .resume = au1x00_drv_pcmcia_resume, }; @@ -533,8 +545,7 @@ static struct device_driver au1x00_pcmcia_driver = { static int __init au1x00_pcmcia_init(void) { int error = 0; - if ((error = driver_register(&au1x00_pcmcia_driver))) - return error; + error = platform_driver_register(&au1x00_pcmcia_driver); return error; } @@ -544,7 +555,7 @@ static int __init au1x00_pcmcia_init(void) */ static void __exit au1x00_pcmcia_exit(void) { - driver_unregister(&au1x00_pcmcia_driver); + platform_driver_unregister(&au1x00_pcmcia_driver); } module_init(au1x00_pcmcia_init); diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c index 71653ab8489..40d4953e4b1 100644 --- a/drivers/pcmcia/i82365.c +++ b/drivers/pcmcia/i82365.c @@ -1238,6 +1238,16 @@ static int pcic_init(struct pcmcia_socket *s) return 0; } +static int i82365_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int i82365_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} static struct pccard_operations pcic_operations = { .init = pcic_init, .get_status = pcic_get_status, @@ -1248,11 +1258,13 @@ static struct pccard_operations pcic_operations = { /*====================================================================*/ -static struct device_driver i82365_driver = { - .name = "i82365", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static struct platform_driver i82365_driver = { + .driver = { + .name = "i82365", + .owner = THIS_MODULE, + }, + .suspend = i82365_drv_pcmcia_suspend, + .resume = i82365_drv_pcmcia_resume, }; static struct platform_device *i82365_device; @@ -1261,7 +1273,7 @@ static int __init init_i82365(void) { int i, ret; - ret = driver_register(&i82365_driver); + ret = platform_driver_register(&i82365_driver); if (ret) goto err_out; @@ -1337,7 +1349,7 @@ err_dev_unregister: pnp_disable_dev(i82365_pnpdev); #endif err_driver_unregister: - driver_unregister(&i82365_driver); + platform_driver_unregister(&i82365_driver); err_out: return ret; } /* init_i82365 */ @@ -1365,7 +1377,7 @@ static void __exit exit_i82365(void) if (i82365_pnpdev) pnp_disable_dev(i82365_pnpdev); #endif - driver_unregister(&i82365_driver); + platform_driver_unregister(&i82365_driver); } /* exit_i82365 */ module_init(init_i82365); diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c index 2ab4f22c21d..62b4ecc97c4 100644 --- a/drivers/pcmcia/m32r_cfc.c +++ b/drivers/pcmcia/m32r_cfc.c @@ -696,13 +696,25 @@ static struct pccard_operations pcc_operations = { .set_mem_map = pcc_set_mem_map, }; +static int cfc_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int cfc_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} /*====================================================================*/ -static struct device_driver pcc_driver = { - .name = "cfc", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static struct platform_driver pcc_driver = { + .driver = { + .name = "cfc", + .owner = THIS_MODULE, + }, + .suspend = cfc_drv_pcmcia_suspend, + .resume = cfc_drv_pcmcia_resume, }; static struct platform_device pcc_device = { @@ -716,13 +728,13 @@ static int __init init_m32r_pcc(void) { int i, ret; - ret = driver_register(&pcc_driver); + ret = platform_driver_register(&pcc_driver); if (ret) return ret; ret = platform_device_register(&pcc_device); if (ret){ - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); return ret; } @@ -754,7 +766,7 @@ static int __init init_m32r_pcc(void) if (pcc_sockets == 0) { printk("socket is not found.\n"); platform_device_unregister(&pcc_device); - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); return -ENODEV; } @@ -802,7 +814,7 @@ static void __exit exit_m32r_pcc(void) if (poll_interval != 0) del_timer_sync(&poll_timer); - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); } /* exit_m32r_pcc */ module_init(init_m32r_pcc); diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c index 2f108c23dbd..12034b41d19 100644 --- a/drivers/pcmcia/m32r_pcc.c +++ b/drivers/pcmcia/m32r_pcc.c @@ -672,13 +672,25 @@ static struct pccard_operations pcc_operations = { .set_mem_map = pcc_set_mem_map, }; +static int pcc_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int pcc_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} /*====================================================================*/ -static struct device_driver pcc_driver = { - .name = "pcc", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static struct platform_driver pcc_driver = { + .driver = { + .name = "pcc", + .owner = THIS_MODULE, + }, + .suspend = pcc_drv_pcmcia_suspend, + .resume = pcc_drv_pcmcia_resume, }; static struct platform_device pcc_device = { @@ -692,13 +704,13 @@ static int __init init_m32r_pcc(void) { int i, ret; - ret = driver_register(&pcc_driver); + ret = platform_driver_register(&pcc_driver); if (ret) return ret; ret = platform_device_register(&pcc_device); if (ret){ - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); return ret; } @@ -715,7 +727,7 @@ static int __init init_m32r_pcc(void) if (pcc_sockets == 0) { printk("socket is not found.\n"); platform_device_unregister(&pcc_device); - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); return -ENODEV; } @@ -763,7 +775,7 @@ static void __exit exit_m32r_pcc(void) if (poll_interval != 0) del_timer_sync(&poll_timer); - driver_unregister(&pcc_driver); + platform_driver_unregister(&pcc_driver); } /* exit_m32r_pcc */ module_init(init_m32r_pcc); diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c index c5b2a44b4c3..d8da5ac844e 100644 --- a/drivers/pcmcia/sa1100_generic.c +++ b/drivers/pcmcia/sa1100_generic.c @@ -65,7 +65,7 @@ static int (*sa11x0_pcmcia_hw_init[])(struct device *dev) = { #endif }; -static int sa11x0_drv_pcmcia_probe(struct device *dev) +static int sa11x0_drv_pcmcia_probe(struct platform_device *dev) { int i, ret = -ENODEV; @@ -73,7 +73,7 @@ static int sa11x0_drv_pcmcia_probe(struct device *dev) * Initialise any "on-board" PCMCIA sockets. */ for (i = 0; i < ARRAY_SIZE(sa11x0_pcmcia_hw_init); i++) { - ret = sa11x0_pcmcia_hw_init[i](dev); + ret = sa11x0_pcmcia_hw_init[i](&dev->dev); if (ret == 0) break; } @@ -81,13 +81,31 @@ static int sa11x0_drv_pcmcia_probe(struct device *dev) return ret; } -static struct device_driver sa11x0_pcmcia_driver = { +static int sa11x0_drv_pcmcia_remove(struct platform_device *dev) +{ + return soc_common_drv_pcmcia_remove(&dev->dev); +} + +static int sa11x0_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int sa11x0_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} + +static struct platform_driver sa11x0_pcmcia_driver = { + .driver = { + .name = "sa11x0-pcmcia", + .owner = THIS_MODULE, + }, .probe = sa11x0_drv_pcmcia_probe, - .remove = soc_common_drv_pcmcia_remove, - .name = "sa11x0-pcmcia", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, + .remove = sa11x0_drv_pcmcia_remove, + .suspend = sa11x0_drv_pcmcia_suspend, + .resume = sa11x0_drv_pcmcia_resume, }; /* sa11x0_pcmcia_init() @@ -100,7 +118,7 @@ static struct device_driver sa11x0_pcmcia_driver = { */ static int __init sa11x0_pcmcia_init(void) { - return driver_register(&sa11x0_pcmcia_driver); + return platform_driver_register(&sa11x0_pcmcia_driver); } /* sa11x0_pcmcia_exit() @@ -110,7 +128,7 @@ static int __init sa11x0_pcmcia_init(void) */ static void __exit sa11x0_pcmcia_exit(void) { - driver_unregister(&sa11x0_pcmcia_driver); + platform_driver_unregister(&sa11x0_pcmcia_driver); } MODULE_AUTHOR("John Dorsey "); diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c index 2a613e920fd..9ad97ea836e 100644 --- a/drivers/pcmcia/tcic.c +++ b/drivers/pcmcia/tcic.c @@ -363,13 +363,25 @@ static int __init get_tcic_id(void) return id; } +static int tcic_drv_pcmcia_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int tcic_drv_pcmcia_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} /*====================================================================*/ -static struct device_driver tcic_driver = { - .name = "tcic-pcmcia", - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static struct platform_driver tcic_driver = { + .driver = { + .name = "tcic-pcmcia", + .owner = THIS_MODULE, + }, + .suspend = tcic_drv_pcmcia_suspend, + .resume = tcic_drv_pcmcia_resume, }; static struct platform_device tcic_device = { @@ -383,7 +395,7 @@ static int __init init_tcic(void) int i, sock, ret = 0; u_int mask, scan; - if (driver_register(&tcic_driver)) + if (platform_driver_register(&tcic_driver)) return -1; printk(KERN_INFO "Databook TCIC-2 PCMCIA probe: "); @@ -391,7 +403,7 @@ static int __init init_tcic(void) if (!request_region(tcic_base, 16, "tcic-2")) { printk("could not allocate ports,\n "); - driver_unregister(&tcic_driver); + platform_driver_unregister(&tcic_driver); return -ENODEV; } else { @@ -414,7 +426,7 @@ static int __init init_tcic(void) if (sock == 0) { printk("not found.\n"); release_region(tcic_base, 16); - driver_unregister(&tcic_driver); + platform_driver_unregister(&tcic_driver); return -ENODEV; } @@ -542,7 +554,7 @@ static void __exit exit_tcic(void) } platform_device_unregister(&tcic_device); - driver_unregister(&tcic_driver); + platform_driver_unregister(&tcic_driver); } /* exit_tcic */ /*====================================================================*/ diff --git a/drivers/pcmcia/vrc4171_card.c b/drivers/pcmcia/vrc4171_card.c index b2c41241905..659421d0ca4 100644 --- a/drivers/pcmcia/vrc4171_card.c +++ b/drivers/pcmcia/vrc4171_card.c @@ -704,24 +704,37 @@ static int __devinit vrc4171_card_setup(char *options) __setup("vrc4171_card=", vrc4171_card_setup); -static struct device_driver vrc4171_card_driver = { - .name = vrc4171_card_name, - .bus = &platform_bus_type, - .suspend = pcmcia_socket_dev_suspend, - .resume = pcmcia_socket_dev_resume, +static int vrc4171_card_suspend(struct platform_device *dev, + pm_message_t state) +{ + return pcmcia_socket_dev_suspend(&dev->dev, state); +} + +static int vrc4171_card_resume(struct platform_device *dev) +{ + return pcmcia_socket_dev_resume(&dev->dev); +} + +static struct platform_driver vrc4171_card_driver = { + .driver = { + .name = vrc4171_card_name, + .owner = THIS_MODULE, + }, + .suspend = vrc4171_card_suspend, + .resume = vrc4171_card_resume, }; static int __devinit vrc4171_card_init(void) { int retval; - retval = driver_register(&vrc4171_card_driver); + retval = platform_driver_register(&vrc4171_card_driver); if (retval < 0) return retval; retval = platform_device_register(&vrc4171_card_device); if (retval < 0) { - driver_unregister(&vrc4171_card_driver); + platform_driver_unregister(&vrc4171_card_driver); return retval; } @@ -735,11 +748,12 @@ static int __devinit vrc4171_card_init(void) if (retval < 0) { vrc4171_remove_sockets(); platform_device_unregister(&vrc4171_card_device); - driver_unregister(&vrc4171_card_driver); + platform_driver_unregister(&vrc4171_card_driver); return retval; } - printk(KERN_INFO "%s, connected to IRQ %d\n", vrc4171_card_driver.name, vrc4171_irq); + printk(KERN_INFO "%s, connected to IRQ %d\n", + vrc4171_card_driver.driver.name, vrc4171_irq); return 0; } @@ -749,7 +763,7 @@ static void __devexit vrc4171_card_exit(void) free_irq(vrc4171_irq, vrc4171_sockets); vrc4171_remove_sockets(); platform_device_unregister(&vrc4171_card_device); - driver_unregister(&vrc4171_card_driver); + platform_driver_unregister(&vrc4171_card_driver); } module_init(vrc4171_card_init); diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index d4bda201774..6d25aca7b41 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c @@ -35,7 +35,7 @@ static struct platform_device *a4000t_scsi_device; #define A4000T_SCSI_ADDR 0xdd0040 -static int __devinit a4000t_probe(struct device *dev) +static int __devinit a4000t_probe(struct platform_device *dev) { struct Scsi_Host *host; struct NCR_700_Host_Parameters *hostdata; @@ -78,7 +78,7 @@ static int __devinit a4000t_probe(struct device *dev) goto out_put_host; } - dev_set_drvdata(dev, host); + platform_set_drvdata(dev, host); scsi_scan_host(host); return 0; @@ -93,9 +93,9 @@ static int __devinit a4000t_probe(struct device *dev) return -ENODEV; } -static __devexit int a4000t_device_remove(struct device *dev) +static __devexit int a4000t_device_remove(struct platform_device *dev) { - struct Scsi_Host *host = dev_get_drvdata(dev); + struct Scsi_Host *host = platform_get_drvdata(dev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); scsi_remove_host(host); @@ -108,25 +108,27 @@ static __devexit int a4000t_device_remove(struct device *dev) return 0; } -static struct device_driver a4000t_scsi_driver = { - .name = "a4000t-scsi", - .bus = &platform_bus_type, - .probe = a4000t_probe, - .remove = __devexit_p(a4000t_device_remove), +static struct platform_driver a4000t_scsi_driver = { + .driver = { + .name = "a4000t-scsi", + .owner = THIS_MODULE, + }, + .probe = a4000t_probe, + .remove = __devexit_p(a4000t_device_remove), }; static int __init a4000t_scsi_init(void) { int err; - err = driver_register(&a4000t_scsi_driver); + err = platform_driver_register(&a4000t_scsi_driver); if (err) return err; a4000t_scsi_device = platform_device_register_simple("a4000t-scsi", -1, NULL, 0); if (IS_ERR(a4000t_scsi_device)) { - driver_unregister(&a4000t_scsi_driver); + platform_driver_register(&a4000t_scsi_driver); return PTR_ERR(a4000t_scsi_device); } @@ -136,7 +138,7 @@ static int __init a4000t_scsi_init(void) static void __exit a4000t_scsi_exit(void) { platform_device_unregister(a4000t_scsi_device); - driver_unregister(&a4000t_scsi_driver); + platform_driver_unregister(&a4000t_scsi_driver); } module_init(a4000t_scsi_init); diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c index d858f3d4127..9e9a82b03f2 100644 --- a/drivers/scsi/bvme6000_scsi.c +++ b/drivers/scsi/bvme6000_scsi.c @@ -34,7 +34,7 @@ static struct scsi_host_template bvme6000_scsi_driver_template = { static struct platform_device *bvme6000_scsi_device; static __devinit int -bvme6000_probe(struct device *dev) +bvme6000_probe(struct platform_device *dev) { struct Scsi_Host *host; struct NCR_700_Host_Parameters *hostdata; @@ -73,7 +73,7 @@ bvme6000_probe(struct device *dev) goto out_put_host; } - dev_set_drvdata(dev, host); + platform_set_drvdata(dev, host); scsi_scan_host(host); return 0; @@ -87,9 +87,9 @@ bvme6000_probe(struct device *dev) } static __devexit int -bvme6000_device_remove(struct device *dev) +bvme6000_device_remove(struct platform_device *dev) { - struct Scsi_Host *host = dev_get_drvdata(dev); + struct Scsi_Host *host = platform_get_drvdata(dev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); scsi_remove_host(host); @@ -100,25 +100,27 @@ bvme6000_device_remove(struct device *dev) return 0; } -static struct device_driver bvme6000_scsi_driver = { - .name = "bvme6000-scsi", - .bus = &platform_bus_type, - .probe = bvme6000_probe, - .remove = __devexit_p(bvme6000_device_remove), +static struct platform_driver bvme6000_scsi_driver = { + .driver = { + .name = "bvme6000-scsi", + .owner = THIS_MODULE, + }, + .probe = bvme6000_probe, + .remove = __devexit_p(bvme6000_device_remove), }; static int __init bvme6000_scsi_init(void) { int err; - err = driver_register(&bvme6000_scsi_driver); + err = platform_driver_register(&bvme6000_scsi_driver); if (err) return err; bvme6000_scsi_device = platform_device_register_simple("bvme6000-scsi", -1, NULL, 0); if (IS_ERR(bvme6000_scsi_device)) { - driver_unregister(&bvme6000_scsi_driver); + platform_driver_unregister(&bvme6000_scsi_driver); return PTR_ERR(bvme6000_scsi_device); } @@ -128,7 +130,7 @@ static int __init bvme6000_scsi_init(void) static void __exit bvme6000_scsi_exit(void) { platform_device_unregister(bvme6000_scsi_device); - driver_unregister(&bvme6000_scsi_driver); + platform_driver_unregister(&bvme6000_scsi_driver); } module_init(bvme6000_scsi_init); diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c index b264b499d98..7794fc158b1 100644 --- a/drivers/scsi/mvme16x_scsi.c +++ b/drivers/scsi/mvme16x_scsi.c @@ -34,7 +34,7 @@ static struct scsi_host_template mvme16x_scsi_driver_template = { static struct platform_device *mvme16x_scsi_device; static __devinit int -mvme16x_probe(struct device *dev) +mvme16x_probe(struct platform_device *dev) { struct Scsi_Host * host = NULL; struct NCR_700_Host_Parameters *hostdata; @@ -88,7 +88,7 @@ mvme16x_probe(struct device *dev) out_be32(0xfff4202c, v); } - dev_set_drvdata(dev, host); + platform_set_drvdata(dev, host); scsi_scan_host(host); return 0; @@ -102,9 +102,9 @@ mvme16x_probe(struct device *dev) } static __devexit int -mvme16x_device_remove(struct device *dev) +mvme16x_device_remove(struct platform_device *dev) { - struct Scsi_Host *host = dev_get_drvdata(dev); + struct Scsi_Host *host = platform_get_drvdata(dev); struct NCR_700_Host_Parameters *hostdata = shost_priv(host); /* Disable scsi chip ints */ @@ -123,25 +123,27 @@ mvme16x_device_remove(struct device *dev) return 0; } -static struct device_driver mvme16x_scsi_driver = { - .name = "mvme16x-scsi", - .bus = &platform_bus_type, - .probe = mvme16x_probe, - .remove = __devexit_p(mvme16x_device_remove), +static struct platform_driver mvme16x_scsi_driver = { + .driver = { + .name = "mvme16x-scsi", + .owner = THIS_MODULE, + }, + .probe = mvme16x_probe, + .remove = __devexit_p(mvme16x_device_remove), }; static int __init mvme16x_scsi_init(void) { int err; - err = driver_register(&mvme16x_scsi_driver); + err = platform_driver_register(&mvme16x_scsi_driver); if (err) return err; mvme16x_scsi_device = platform_device_register_simple("mvme16x-scsi", -1, NULL, 0); if (IS_ERR(mvme16x_scsi_device)) { - driver_unregister(&mvme16x_scsi_driver); + platform_driver_unregister(&mvme16x_scsi_driver); return PTR_ERR(mvme16x_scsi_device); } @@ -151,7 +153,7 @@ static int __init mvme16x_scsi_init(void) static void __exit mvme16x_scsi_exit(void) { platform_device_unregister(mvme16x_scsi_device); - driver_unregister(&mvme16x_scsi_driver); + platform_driver_unregister(&mvme16x_scsi_driver); } module_init(mvme16x_scsi_init); diff --git a/drivers/video/au1100fb.c b/drivers/video/au1100fb.c index 62bd4441b5e..378f27745a1 100644 --- a/drivers/video/au1100fb.c +++ b/drivers/video/au1100fb.c @@ -457,7 +457,7 @@ static struct fb_ops au1100fb_ops = /* AU1100 LCD controller device driver */ -static int __init au1100fb_drv_probe(struct device *dev) +static int __init au1100fb_drv_probe(struct platform_device *dev) { struct au1100fb_device *fbdev = NULL; struct resource *regs_res; @@ -475,7 +475,7 @@ static int __init au1100fb_drv_probe(struct device *dev) fbdev->panel = &known_lcd_panels[drv_info.panel_idx]; - dev_set_drvdata(dev, (void*)fbdev); + platform_set_drvdata(dev, (void *)fbdev); /* Allocate region for our registers and map them */ if (!(regs_res = platform_get_resource(to_platform_device(dev), @@ -583,19 +583,19 @@ failed: fb_dealloc_cmap(&fbdev->info.cmap); } kfree(fbdev); - dev_set_drvdata(dev, NULL); + platform_set_drvdata(dev, NULL); return 0; } -int au1100fb_drv_remove(struct device *dev) +int au1100fb_drv_remove(struct platform_device *dev) { struct au1100fb_device *fbdev = NULL; if (!dev) return -ENODEV; - fbdev = (struct au1100fb_device*) dev_get_drvdata(dev); + fbdev = (struct au1100fb_device *) platform_get_drvdata(dev); #if !defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_LOGO) au1100fb_fb_blank(VESA_POWERDOWN, &fbdev->info); @@ -620,9 +620,9 @@ int au1100fb_drv_remove(struct device *dev) static u32 sys_clksrc; static struct au1100fb_regs fbregs; -int au1100fb_drv_suspend(struct device *dev, pm_message_t state) +int au1100fb_drv_suspend(struct platform_device *dev, pm_message_t state) { - struct au1100fb_device *fbdev = dev_get_drvdata(dev); + struct au1100fb_device *fbdev = platform_get_drvdata(dev); if (!fbdev) return 0; @@ -641,9 +641,9 @@ int au1100fb_drv_suspend(struct device *dev, pm_message_t state) return 0; } -int au1100fb_drv_resume(struct device *dev) +int au1100fb_drv_resume(struct platform_device *dev) { - struct au1100fb_device *fbdev = dev_get_drvdata(dev); + struct au1100fb_device *fbdev = platform_get_drvdata(dev); if (!fbdev) return 0; @@ -663,10 +663,11 @@ int au1100fb_drv_resume(struct device *dev) #define au1100fb_drv_resume NULL #endif -static struct device_driver au1100fb_driver = { - .name = "au1100-lcd", - .bus = &platform_bus_type, - +static struct platform_driver au1100fb_driver = { + .driver = { + .name = "au1100-lcd", + .owner = THIS_MODULE, + }, .probe = au1100fb_drv_probe, .remove = au1100fb_drv_remove, .suspend = au1100fb_drv_suspend, @@ -753,12 +754,12 @@ int __init au1100fb_init(void) return ret; } - return driver_register(&au1100fb_driver); + return platform_driver_register(&au1100fb_driver); } void __exit au1100fb_cleanup(void) { - driver_unregister(&au1100fb_driver); + platform_driver_unregister(&au1100fb_driver); kfree(drv_info.opt_mode); } diff --git a/drivers/video/au1200fb.c b/drivers/video/au1200fb.c index 03e57ef8837..0d96f1d2d4c 100644 --- a/drivers/video/au1200fb.c +++ b/drivers/video/au1200fb.c @@ -1622,7 +1622,7 @@ static int au1200fb_init_fbinfo(struct au1200fb_device *fbdev) /* AU1200 LCD controller device driver */ -static int au1200fb_drv_probe(struct device *dev) +static int au1200fb_drv_probe(struct platform_device *dev) { struct au1200fb_device *fbdev; unsigned long page; @@ -1645,7 +1645,7 @@ static int au1200fb_drv_probe(struct device *dev) /* Allocate the framebuffer to the maximum screen size */ fbdev->fb_len = (win->w[plane].xres * win->w[plane].yres * bpp) / 8; - fbdev->fb_mem = dma_alloc_noncoherent(dev, + fbdev->fb_mem = dma_alloc_noncoherent(&dev->dev, PAGE_ALIGN(fbdev->fb_len), &fbdev->fb_phys, GFP_KERNEL); if (!fbdev->fb_mem) { @@ -1715,7 +1715,7 @@ failed: return ret; } -static int au1200fb_drv_remove(struct device *dev) +static int au1200fb_drv_remove(struct platform_device *dev) { struct au1200fb_device *fbdev; int plane; @@ -1733,7 +1733,8 @@ static int au1200fb_drv_remove(struct device *dev) /* Clean up all probe data */ unregister_framebuffer(&fbdev->fb_info); if (fbdev->fb_mem) - dma_free_noncoherent(dev, PAGE_ALIGN(fbdev->fb_len), + dma_free_noncoherent(&dev->dev, + PAGE_ALIGN(fbdev->fb_len), fbdev->fb_mem, fbdev->fb_phys); if (fbdev->fb_info.cmap.len != 0) fb_dealloc_cmap(&fbdev->fb_info.cmap); @@ -1747,22 +1748,24 @@ static int au1200fb_drv_remove(struct device *dev) } #ifdef CONFIG_PM -static int au1200fb_drv_suspend(struct device *dev, u32 state, u32 level) +static int au1200fb_drv_suspend(struct platform_device *dev, u32 state) { /* TODO */ return 0; } -static int au1200fb_drv_resume(struct device *dev, u32 level) +static int au1200fb_drv_resume(struct platform_device *dev) { /* TODO */ return 0; } #endif /* CONFIG_PM */ -static struct device_driver au1200fb_driver = { - .name = "au1200-lcd", - .bus = &platform_bus_type, +static struct platform_driver au1200fb_driver = { + .driver = { + .name = "au1200-lcd", + .owner = THIS_MODULE, + }, .probe = au1200fb_drv_probe, .remove = au1200fb_drv_remove, #ifdef CONFIG_PM @@ -1906,12 +1909,12 @@ static int __init au1200fb_init(void) printk(KERN_INFO "Power management device entry for the au1200fb loaded.\n"); #endif - return driver_register(&au1200fb_driver); + return platform_driver_register(&au1200fb_driver); } static void __exit au1200fb_cleanup(void) { - driver_unregister(&au1200fb_driver); + platform_driver_unregister(&au1200fb_driver); } module_init(au1200fb_init); diff --git a/drivers/watchdog/rm9k_wdt.c b/drivers/watchdog/rm9k_wdt.c index f1ae3729a19..cce1982a1b5 100644 --- a/drivers/watchdog/rm9k_wdt.c +++ b/drivers/watchdog/rm9k_wdt.c @@ -59,8 +59,8 @@ static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); -static int __init wdt_gpi_probe(struct device *); -static int __exit wdt_gpi_remove(struct device *); +static int __init wdt_gpi_probe(struct platform_device *); +static int __exit wdt_gpi_remove(struct platform_device *); static const char wdt_gpi_name[] = "wdt_gpi"; @@ -346,10 +346,9 @@ static const struct resource *wdt_gpi_get_resource(struct platform_device *pdv, } /* No hotplugging on the platform bus - use __init */ -static int __init wdt_gpi_probe(struct device *dev) +static int __init wdt_gpi_probe(struct platform_device *pdv) { int res; - struct platform_device * const pdv = to_platform_device(dev); const struct resource * const rr = wdt_gpi_get_resource(pdv, WDT_RESOURCE_REGS, IORESOURCE_MEM), @@ -374,7 +373,7 @@ static int __init wdt_gpi_probe(struct device *dev) return res; } -static int __exit wdt_gpi_remove(struct device *dev) +static int __exit wdt_gpi_remove(struct platform_device *dev) { int res; @@ -387,15 +386,13 @@ static int __exit wdt_gpi_remove(struct device *dev) /* Device driver init & exit */ -static struct device_driver wdt_gpi_driver = { - .name = (char *) wdt_gpi_name, - .bus = &platform_bus_type, - .owner = THIS_MODULE, +static struct platform_driver wgt_gpi_driver = { + .driver = { + .name = wdt_gpi_name, + .owner = THIS_MODULE, + }, .probe = wdt_gpi_probe, - .remove = __exit_p(wdt_gpi_remove), - .shutdown = NULL, - .suspend = NULL, - .resume = NULL, + .remove = __devexit_p(wdt_gpi_remove), }; static int __init wdt_gpi_init_module(void) @@ -403,12 +400,12 @@ static int __init wdt_gpi_init_module(void) atomic_set(&opencnt, 1); if (timeout > MAX_TIMEOUT_SECONDS) timeout = MAX_TIMEOUT_SECONDS; - return driver_register(&wdt_gpi_driver); + return platform_driver_register(&wdt_gpi_driver); } static void __exit wdt_gpi_cleanup_module(void) { - driver_unregister(&wdt_gpi_driver); + platform_driver_unregister(&wdt_gpi_driver); } module_init(wdt_gpi_init_module); -- cgit v1.2.3 From e5779a583ddb9916b37cfbb916dc53ec2eaf0b9b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 11 Mar 2009 09:23:52 +0100 Subject: scsi/m68k: Kill NCR_700_detect() warnings The patch from Ming Lei entitled: platform driver: fix incorrect use of 'platform_bus_type' with 'struct devic introduced the following warnings on m68k, as `dev' is now a `struct platform_device *' instead of a `struct device *': | drivers/scsi/a4000t.c:64: warning: passing argument 3 of 'NCR_700_detect' from incompatible pointer type | drivers/scsi/mvme16x_scsi.c:67: warning: passing argument 3 of 'NCR_700_detect' from incompatible pointer type | drivers/scsi/bvme6000_scsi.c:61: warning: passing argument 3 of 'NCR_700_detect' from incompatible pointer type I think the below is missing (untested on real hardware). Signed-off-by: Geert Uytterhoeven Cc: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/scsi/a4000t.c | 3 ++- drivers/scsi/bvme6000_scsi.c | 3 ++- drivers/scsi/mvme16x_scsi.c | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/a4000t.c b/drivers/scsi/a4000t.c index 6d25aca7b41..61af3d91ac8 100644 --- a/drivers/scsi/a4000t.c +++ b/drivers/scsi/a4000t.c @@ -61,7 +61,8 @@ static int __devinit a4000t_probe(struct platform_device *dev) hostdata->dcntl_extra = EA_710; /* and register the chip */ - host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, dev); + host = NCR_700_detect(&a4000t_scsi_driver_template, hostdata, + &dev->dev); if (!host) { printk(KERN_ERR "a4000t-scsi: No host detected; " "board configuration problem?\n"); diff --git a/drivers/scsi/bvme6000_scsi.c b/drivers/scsi/bvme6000_scsi.c index 9e9a82b03f2..5799cb5cba6 100644 --- a/drivers/scsi/bvme6000_scsi.c +++ b/drivers/scsi/bvme6000_scsi.c @@ -58,7 +58,8 @@ bvme6000_probe(struct platform_device *dev) hostdata->ctest7_extra = CTEST7_TT1; /* and register the chip */ - host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata, dev); + host = NCR_700_detect(&bvme6000_scsi_driver_template, hostdata, + &dev->dev); if (!host) { printk(KERN_ERR "bvme6000-scsi: No host detected; " "board configuration problem?\n"); diff --git a/drivers/scsi/mvme16x_scsi.c b/drivers/scsi/mvme16x_scsi.c index 7794fc158b1..b5fbfd6ce87 100644 --- a/drivers/scsi/mvme16x_scsi.c +++ b/drivers/scsi/mvme16x_scsi.c @@ -64,7 +64,8 @@ mvme16x_probe(struct platform_device *dev) hostdata->ctest7_extra = CTEST7_TT1; /* and register the chip */ - host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata, dev); + host = NCR_700_detect(&mvme16x_scsi_driver_template, hostdata, + &dev->dev); if (!host) { printk(KERN_ERR "mvme16x-scsi: No host detected; " "board configuration problem?\n"); -- cgit v1.2.3 From f48f3febb2cbfd0f2ecee7690835ba745c1034a4 Mon Sep 17 00:00:00 2001 From: Dave Young Date: Sat, 14 Feb 2009 21:23:22 +0800 Subject: driver-core: do not register a driver with bus_type not registered If the bus_type is not registerd, driver_register to that bus will cause oops. I found this bug when test built-in usb serial drivers (ie. aircable driver) with 'nousb' cmdline params. In this patch: 1. set the bus->p=NULL when bus_register failed and unregisterd. 2. if bus->p is NULL, driver_register BUG_ON will be triggered. Signed-off-by: Dave Young Signed-off-by: Greg Kroah-Hartman --- drivers/base/bus.c | 2 ++ drivers/base/driver.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 8547b780bb5..11463c00451 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -932,6 +932,7 @@ bus_uevent_fail: kset_unregister(&bus->p->subsys); kfree(bus->p); out: + bus->p = NULL; return retval; } EXPORT_SYMBOL_GPL(bus_register); @@ -953,6 +954,7 @@ void bus_unregister(struct bus_type *bus) bus_remove_file(bus, &bus_attr_uevent); kset_unregister(&bus->p->subsys); kfree(bus->p); + bus->p = NULL; } EXPORT_SYMBOL_GPL(bus_unregister); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 1e2bda780e4..2889ad57e48 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -216,6 +216,8 @@ int driver_register(struct device_driver *drv) int ret; struct device_driver *other; + BUG_ON(!drv->bus->p); + if ((drv->bus->probe && drv->probe) || (drv->bus->remove && drv->remove) || (drv->bus->shutdown && drv->shutdown)) -- cgit v1.2.3 From b23530ebc339c4092ae2c9f37341a5398fea8b89 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sat, 21 Feb 2009 16:45:07 +0800 Subject: driver core: remove polling for driver_probe_done(v5) This patch removes 100ms polling for driver_probe_done in wait_for_device_probe(), and uses wait_event() instead. Removing polling in fs initialization may lead to a faster boot. This patch also changes the return type of wait_for_device_done() from int to void. This patch is against Arjan's patch in linux-next tree. Signed-off-by: Ming Lei Acked-by: Cornelia Huck Reviewed-by: Arjan van de Ven Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 3f32df7ed37..0dfd08c1592 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -172,16 +172,12 @@ int driver_probe_done(void) /** * wait_for_device_probe * Wait for device probing to be completed. - * - * Note: this function polls at 100 msec intervals. */ -int wait_for_device_probe(void) +void wait_for_device_probe(void) { /* wait for the known devices to complete their probing */ - while (driver_probe_done() != 0) - msleep(100); + wait_event(probe_waitqueue, atomic_read(&probe_count) == 0); async_synchronize_full(); - return 0; } /** -- cgit v1.2.3 From fb069a5d132fb926ed17af3211a114ac7cf27d7a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Dec 2008 12:23:36 -0800 Subject: driver core: create a private portion of struct device This is to be used to move things out of struct device that no code outside of the driver core should ever touch. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 12 ++++++++++++ drivers/base/core.c | 9 +++++++++ 2 files changed, 21 insertions(+) (limited to 'drivers') diff --git a/drivers/base/base.h b/drivers/base/base.h index ca2b0376685..62a2cb5e178 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -63,6 +63,18 @@ struct class_private { #define to_class(obj) \ container_of(obj, struct class_private, class_subsys.kobj) +/** + * struct device_private - structure to hold the private to the driver core portions of the device structure. + * + * @device - pointer back to the struct class that this structure is + * associated with. + * + * Nothing outside of the driver core should ever touch these fields. + */ +struct device_private { + struct device *device; +}; + /* initialisation functions */ extern int devices_init(void); extern int buses_init(void); diff --git a/drivers/base/core.c b/drivers/base/core.c index 059966b617f..16d85991010 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -109,6 +109,7 @@ static struct sysfs_ops dev_sysfs_ops = { static void device_release(struct kobject *kobj) { struct device *dev = to_dev(kobj); + struct device_private *p = dev->p; if (dev->release) dev->release(dev); @@ -120,6 +121,7 @@ static void device_release(struct kobject *kobj) WARN(1, KERN_ERR "Device '%s' does not have a release() " "function, it is broken and must be fixed.\n", dev_name(dev)); + kfree(p); } static struct kobj_type device_ktype = { @@ -859,6 +861,13 @@ int device_add(struct device *dev) if (!dev) goto done; + dev->p = kzalloc(sizeof(*dev->p), GFP_KERNEL); + if (!dev->p) { + error = -ENOMEM; + goto done; + } + dev->p->device = dev; + /* * for statically allocated devices, which should all be converted * some day, we need to initialize the name. We prevent reading back -- cgit v1.2.3 From f791b8c836307b58cbf62133a6a772ed1a92fb33 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Dec 2008 12:24:56 -0800 Subject: driver core: move klist_children into private structure Nothing outside of the driver core should ever touch klist_children, or knode_parent, so move them out of the public eye. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 6 ++++++ drivers/base/core.c | 39 +++++++++++++++++++++++++-------------- 2 files changed, 31 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/base/base.h b/drivers/base/base.h index 62a2cb5e178..7c4fafc314c 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -66,14 +66,20 @@ struct class_private { /** * struct device_private - structure to hold the private to the driver core portions of the device structure. * + * @klist_children - klist containing all children of this device + * @knode_parent - node in sibling list * @device - pointer back to the struct class that this structure is * associated with. * * Nothing outside of the driver core should ever touch these fields. */ struct device_private { + struct klist klist_children; + struct klist_node knode_parent; struct device *device; }; +#define to_device_private_parent(obj) \ + container_of(obj, struct device_private, knode_parent) /* initialisation functions */ extern int devices_init(void); diff --git a/drivers/base/core.c b/drivers/base/core.c index 16d85991010..a90f56f64d6 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -509,14 +509,16 @@ EXPORT_SYMBOL_GPL(device_schedule_callback_owner); static void klist_children_get(struct klist_node *n) { - struct device *dev = container_of(n, struct device, knode_parent); + struct device_private *p = to_device_private_parent(n); + struct device *dev = p->device; get_device(dev); } static void klist_children_put(struct klist_node *n) { - struct device *dev = container_of(n, struct device, knode_parent); + struct device_private *p = to_device_private_parent(n); + struct device *dev = p->device; put_device(dev); } @@ -540,8 +542,6 @@ void device_initialize(struct device *dev) { dev->kobj.kset = devices_kset; kobject_init(&dev->kobj, &device_ktype); - klist_init(&dev->klist_children, klist_children_get, - klist_children_put); INIT_LIST_HEAD(&dev->dma_pools); init_MUTEX(&dev->sem); spin_lock_init(&dev->devres_lock); @@ -867,6 +867,8 @@ int device_add(struct device *dev) goto done; } dev->p->device = dev; + klist_init(&dev->p->klist_children, klist_children_get, + klist_children_put); /* * for statically allocated devices, which should all be converted @@ -937,7 +939,8 @@ int device_add(struct device *dev) kobject_uevent(&dev->kobj, KOBJ_ADD); bus_attach_device(dev); if (parent) - klist_add_tail(&dev->knode_parent, &parent->klist_children); + klist_add_tail(&dev->p->knode_parent, + &parent->p->klist_children); if (dev->class) { mutex_lock(&dev->class->p->class_mutex); @@ -1051,7 +1054,7 @@ void device_del(struct device *dev) device_pm_remove(dev); dpm_sysfs_remove(dev); if (parent) - klist_del(&dev->knode_parent); + klist_del(&dev->p->knode_parent); if (MAJOR(dev->devt)) { device_remove_sys_dev_entry(dev); device_remove_file(dev, &devt_attr); @@ -1112,7 +1115,14 @@ void device_unregister(struct device *dev) static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); - return n ? container_of(n, struct device, knode_parent) : NULL; + struct device *dev = NULL; + struct device_private *p; + + if (n) { + p = to_device_private_parent(n); + dev = p->device; + } + return dev; } /** @@ -1134,7 +1144,7 @@ int device_for_each_child(struct device *parent, void *data, struct device *child; int error = 0; - klist_iter_init(&parent->klist_children, &i); + klist_iter_init(&parent->p->klist_children, &i); while ((child = next_device(&i)) && !error) error = fn(child, data); klist_iter_exit(&i); @@ -1165,7 +1175,7 @@ struct device *device_find_child(struct device *parent, void *data, if (!parent) return NULL; - klist_iter_init(&parent->klist_children, &i); + klist_iter_init(&parent->p->klist_children, &i); while ((child = next_device(&i))) if (match(child, data) && get_device(child)) break; @@ -1578,9 +1588,10 @@ int device_move(struct device *dev, struct device *new_parent) old_parent = dev->parent; dev->parent = new_parent; if (old_parent) - klist_remove(&dev->knode_parent); + klist_remove(&dev->p->knode_parent); if (new_parent) { - klist_add_tail(&dev->knode_parent, &new_parent->klist_children); + klist_add_tail(&dev->p->knode_parent, + &new_parent->p->klist_children); set_dev_node(dev, dev_to_node(new_parent)); } @@ -1592,11 +1603,11 @@ int device_move(struct device *dev, struct device *new_parent) device_move_class_links(dev, new_parent, old_parent); if (!kobject_move(&dev->kobj, &old_parent->kobj)) { if (new_parent) - klist_remove(&dev->knode_parent); + klist_remove(&dev->p->knode_parent); dev->parent = old_parent; if (old_parent) { - klist_add_tail(&dev->knode_parent, - &old_parent->klist_children); + klist_add_tail(&dev->p->knode_parent, + &old_parent->p->klist_children); set_dev_node(dev, dev_to_node(old_parent)); } } -- cgit v1.2.3 From 8940b4f312dced51b45004819b776ec3aa7fcd5d Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Dec 2008 12:25:49 -0800 Subject: driver core: move knode_driver into private structure Nothing outside of the driver core should ever touch knode_driver, so move it out of the public eye. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 4 ++++ drivers/base/dd.c | 13 ++++++++----- drivers/base/driver.c | 13 ++++++++++--- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/base/base.h b/drivers/base/base.h index 7c4fafc314c..4fc5fd3984c 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -68,6 +68,7 @@ struct class_private { * * @klist_children - klist containing all children of this device * @knode_parent - node in sibling list + * @knode_driver - node in driver list * @device - pointer back to the struct class that this structure is * associated with. * @@ -76,10 +77,13 @@ struct class_private { struct device_private { struct klist klist_children; struct klist_node knode_parent; + struct klist_node knode_driver; struct device *device; }; #define to_device_private_parent(obj) \ container_of(obj, struct device_private, knode_parent) +#define to_device_private_driver(obj) \ + container_of(obj, struct device_private, knode_driver) /* initialisation functions */ extern int devices_init(void); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 0dfd08c1592..f17c3266a0e 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -30,7 +30,7 @@ static void driver_bound(struct device *dev) { - if (klist_node_attached(&dev->knode_driver)) { + if (klist_node_attached(&dev->p->knode_driver)) { printk(KERN_WARNING "%s: device %s already bound\n", __func__, kobject_name(&dev->kobj)); return; @@ -43,7 +43,7 @@ static void driver_bound(struct device *dev) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, BUS_NOTIFY_BOUND_DRIVER, dev); - klist_add_tail(&dev->knode_driver, &dev->driver->p->klist_devices); + klist_add_tail(&dev->p->knode_driver, &dev->driver->p->klist_devices); } static int driver_sysfs_add(struct device *dev) @@ -318,7 +318,7 @@ static void __device_release_driver(struct device *dev) drv->remove(dev); devres_release_all(dev); dev->driver = NULL; - klist_remove(&dev->knode_driver); + klist_remove(&dev->p->knode_driver); } } @@ -348,6 +348,7 @@ EXPORT_SYMBOL_GPL(device_release_driver); */ void driver_detach(struct device_driver *drv) { + struct device_private *dev_prv; struct device *dev; for (;;) { @@ -356,8 +357,10 @@ void driver_detach(struct device_driver *drv) spin_unlock(&drv->p->klist_devices.k_lock); break; } - dev = list_entry(drv->p->klist_devices.k_list.prev, - struct device, knode_driver.n_node); + dev_prv = list_entry(drv->p->klist_devices.k_list.prev, + struct device_private, + knode_driver.n_node); + dev = dev_prv->device; get_device(dev); spin_unlock(&drv->p->klist_devices.k_lock); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 2889ad57e48..c51f11bb29a 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -19,7 +19,14 @@ static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); - return n ? container_of(n, struct device, knode_driver) : NULL; + struct device *dev = NULL; + struct device_private *dev_prv; + + if (n) { + dev_prv = to_device_private_driver(n); + dev = dev_prv->device; + } + return dev; } /** @@ -42,7 +49,7 @@ int driver_for_each_device(struct device_driver *drv, struct device *start, return -EINVAL; klist_iter_init_node(&drv->p->klist_devices, &i, - start ? &start->knode_driver : NULL); + start ? &start->p->knode_driver : NULL); while ((dev = next_device(&i)) && !error) error = fn(dev, data); klist_iter_exit(&i); @@ -76,7 +83,7 @@ struct device *driver_find_device(struct device_driver *drv, return NULL; klist_iter_init_node(&drv->p->klist_devices, &i, - (start ? &start->knode_driver : NULL)); + (start ? &start->p->knode_driver : NULL)); while ((dev = next_device(&i))) if (match(dev, data) && get_device(dev)) break; -- cgit v1.2.3 From ae1b41715ee2aae356fbcca032838b71d70b855f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 16 Dec 2008 12:26:21 -0800 Subject: driver core: move knode_bus into private structure Nothing outside of the driver core should ever touch knode_bus, so move it out of the public eye. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/base.h | 4 ++++ drivers/base/bus.c | 40 +++++++++++++++++++++++++++------------- 2 files changed, 31 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/base/base.h b/drivers/base/base.h index 4fc5fd3984c..ddc97496db4 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -69,6 +69,7 @@ struct class_private { * @klist_children - klist containing all children of this device * @knode_parent - node in sibling list * @knode_driver - node in driver list + * @knode_bus - node in bus list * @device - pointer back to the struct class that this structure is * associated with. * @@ -78,12 +79,15 @@ struct device_private { struct klist klist_children; struct klist_node knode_parent; struct klist_node knode_driver; + struct klist_node knode_bus; struct device *device; }; #define to_device_private_parent(obj) \ container_of(obj, struct device_private, knode_parent) #define to_device_private_driver(obj) \ container_of(obj, struct device_private, knode_driver) +#define to_device_private_bus(obj) \ + container_of(obj, struct device_private, knode_bus) /* initialisation functions */ extern int devices_init(void); diff --git a/drivers/base/bus.c b/drivers/base/bus.c index 11463c00451..dc030f1f00f 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -253,7 +253,14 @@ static ssize_t store_drivers_probe(struct bus_type *bus, static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); - return n ? container_of(n, struct device, knode_bus) : NULL; + struct device *dev = NULL; + struct device_private *dev_prv; + + if (n) { + dev_prv = to_device_private_bus(n); + dev = dev_prv->device; + } + return dev; } /** @@ -286,7 +293,7 @@ int bus_for_each_dev(struct bus_type *bus, struct device *start, return -EINVAL; klist_iter_init_node(&bus->p->klist_devices, &i, - (start ? &start->knode_bus : NULL)); + (start ? &start->p->knode_bus : NULL)); while ((dev = next_device(&i)) && !error) error = fn(dev, data); klist_iter_exit(&i); @@ -320,7 +327,7 @@ struct device *bus_find_device(struct bus_type *bus, return NULL; klist_iter_init_node(&bus->p->klist_devices, &i, - (start ? &start->knode_bus : NULL)); + (start ? &start->p->knode_bus : NULL)); while ((dev = next_device(&i))) if (match(dev, data) && get_device(dev)) break; @@ -507,7 +514,8 @@ void bus_attach_device(struct device *dev) ret = device_attach(dev); WARN_ON(ret < 0); if (ret >= 0) - klist_add_tail(&dev->knode_bus, &bus->p->klist_devices); + klist_add_tail(&dev->p->knode_bus, + &bus->p->klist_devices); } } @@ -528,8 +536,8 @@ void bus_remove_device(struct device *dev) sysfs_remove_link(&dev->bus->p->devices_kset->kobj, dev_name(dev)); device_remove_attrs(dev->bus, dev); - if (klist_node_attached(&dev->knode_bus)) - klist_del(&dev->knode_bus); + if (klist_node_attached(&dev->p->knode_bus)) + klist_del(&dev->p->knode_bus); pr_debug("bus: '%s': remove device %s\n", dev->bus->name, dev_name(dev)); @@ -831,14 +839,16 @@ static void bus_remove_attrs(struct bus_type *bus) static void klist_devices_get(struct klist_node *n) { - struct device *dev = container_of(n, struct device, knode_bus); + struct device_private *dev_prv = to_device_private_bus(n); + struct device *dev = dev_prv->device; get_device(dev); } static void klist_devices_put(struct klist_node *n) { - struct device *dev = container_of(n, struct device, knode_bus); + struct device_private *dev_prv = to_device_private_bus(n); + struct device *dev = dev_prv->device; put_device(dev); } @@ -995,18 +1005,20 @@ static void device_insertion_sort_klist(struct device *a, struct list_head *list { struct list_head *pos; struct klist_node *n; + struct device_private *dev_prv; struct device *b; list_for_each(pos, list) { n = container_of(pos, struct klist_node, n_node); - b = container_of(n, struct device, knode_bus); + dev_prv = to_device_private_bus(n); + b = dev_prv->device; if (compare(a, b) <= 0) { - list_move_tail(&a->knode_bus.n_node, - &b->knode_bus.n_node); + list_move_tail(&a->p->knode_bus.n_node, + &b->p->knode_bus.n_node); return; } } - list_move_tail(&a->knode_bus.n_node, list); + list_move_tail(&a->p->knode_bus.n_node, list); } void bus_sort_breadthfirst(struct bus_type *bus, @@ -1016,6 +1028,7 @@ void bus_sort_breadthfirst(struct bus_type *bus, LIST_HEAD(sorted_devices); struct list_head *pos, *tmp; struct klist_node *n; + struct device_private *dev_prv; struct device *dev; struct klist *device_klist; @@ -1024,7 +1037,8 @@ void bus_sort_breadthfirst(struct bus_type *bus, spin_lock(&device_klist->k_lock); list_for_each_safe(pos, tmp, &device_klist->k_list) { n = container_of(pos, struct klist_node, n_node); - dev = container_of(n, struct device, knode_bus); + dev_prv = to_device_private_bus(n); + dev = dev_prv->device; device_insertion_sort_klist(dev, &sorted_devices, compare); } list_splice(&sorted_devices, &device_klist->k_list); -- cgit v1.2.3 From 006f4571a15fae3a0575f2a0f9e9b63b3d1012f8 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 8 Mar 2009 23:13:32 +0800 Subject: driver core: move platform_data into platform_device This patch moves platform_data from struct device into struct platform_device, based on the two ideas: 1. Now all platform_driver is registered by platform_driver_register, which makes probe()/release()/... of platform_driver passed parameter of platform_device *, so platform driver can get platform_data from platform_device; 2. Other kind of devices do not need to use platform_data, we can decrease size of device if moving it to platform_device. Taking into consideration of thousands of files to be fixed and they can't be finished in one night(maybe it will take a long time), so we keep platform_data in device to allow two kind of cases coexist until all platform devices pass its platfrom data from platform_device->platform_data. All patches to do this kind of conversion are welcome. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index ec993aa6a2c..c5ac81d2230 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -217,6 +217,7 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, if (d) { memcpy(d, data, size); pdev->dev.platform_data = d; + pdev->platform_data = d; } return d ? 0 : -ENOMEM; } @@ -246,6 +247,8 @@ int platform_device_add(struct platform_device *pdev) else dev_set_name(&pdev->dev, pdev->name); + pdev->platform_data = pdev->dev.platform_data; + for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; -- cgit v1.2.3 From ce21c7bcd796fc4f45d48781b7e85f493cc55ee5 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Fri, 13 Mar 2009 23:06:59 +0800 Subject: driver core: fix passing platform_data We will remove platform_data field from struct device until all platform devices pass its specific data from platfom_device and all platform drivers use platform specific data passed by platform_device->platform_data. This kind of conversion will need a long time, for thousands of files is affected. To make the conversion easily, we allow platform specific data passed by struct device or struct platform_device and platform driver may use it from struct device or struct platform_device. Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/base/platform.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/platform.c b/drivers/base/platform.c index c5ac81d2230..d2198f64ad4 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -247,7 +247,20 @@ int platform_device_add(struct platform_device *pdev) else dev_set_name(&pdev->dev, pdev->name); - pdev->platform_data = pdev->dev.platform_data; + /* We will remove platform_data field from struct device + * if all platform devices pass its platform specific data + * from platform_device. The conversion is going to be a + * long time, so we allow the two cases coexist to make + * this kind of fix more easily*/ + if (pdev->platform_data && pdev->dev.platform_data) { + printk(KERN_ERR + "%s: use which platform_data?\n", + dev_name(&pdev->dev)); + } else if (pdev->platform_data) { + pdev->dev.platform_data = pdev->platform_data; + } else if (pdev->dev.platform_data) { + pdev->platform_data = pdev->dev.platform_data; + } for (i = 0; i < pdev->num_resources; i++) { struct resource *p, *r = &pdev->resource[i]; -- cgit v1.2.3 From 4995f8ef9d3aac72745e12419d7fbaa8d01b1d81 Mon Sep 17 00:00:00 2001 From: Kay Sievers Date: Mon, 9 Mar 2009 14:18:52 +0100 Subject: vcs: hook sysfs devices into object lifetime instead of "binding" During bootup performance tracing I noticed many occurrences of vca* device creation and removal, leading to the usual userspace uevent processing, which are, in this case, rather pointless. A simple test showing the kernel timing (not including all the work userspace has to do), gives us these numbers: $ time for i in `seq 1000`; do echo a > /dev/tty2; done real 0m1.142s user 0m0.015s sys 0m0.540s If we move the hook for the vcs* driver core devices from the tty "binding" to the vc allocation/deallocation, which is what the vcs* devices represent, we get the following numbers: $ time for i in `seq 1000`; do echo a > /dev/tty2; done real 0m0.152s user 0m0.030s sys 0m0.072s Cc: Alan Cox Signed-off-by: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/char/vc_screen.c | 16 ++++++++-------- drivers/char/vt.c | 5 +++-- 2 files changed, 11 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c index 4f3b3f95fc4..d94d25c12aa 100644 --- a/drivers/char/vc_screen.c +++ b/drivers/char/vc_screen.c @@ -479,18 +479,18 @@ static const struct file_operations vcs_fops = { static struct class *vc_class; -void vcs_make_sysfs(struct tty_struct *tty) +void vcs_make_sysfs(int index) { - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 1), NULL, - "vcs%u", tty->index + 1); - device_create(vc_class, NULL, MKDEV(VCS_MAJOR, tty->index + 129), NULL, - "vcsa%u", tty->index + 1); + device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 1), NULL, + "vcs%u", index + 1); + device_create(vc_class, NULL, MKDEV(VCS_MAJOR, index + 129), NULL, + "vcsa%u", index + 1); } -void vcs_remove_sysfs(struct tty_struct *tty) +void vcs_remove_sysfs(int index) { - device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1)); - device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129)); + device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 1)); + device_destroy(vc_class, MKDEV(VCS_MAJOR, index + 129)); } int __init vcs_init(void) diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 7900bd63b36..2c1d133819b 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c @@ -778,6 +778,7 @@ int vc_allocate(unsigned int currcons) /* return 0 on success */ } vc->vc_kmalloced = 1; vc_init(vc, vc->vc_rows, vc->vc_cols, 1); + vcs_make_sysfs(currcons); atomic_notifier_call_chain(&vt_notifier_list, VT_ALLOCATE, ¶m); } return 0; @@ -987,7 +988,9 @@ void vc_deallocate(unsigned int currcons) if (vc_cons_allocated(currcons)) { struct vc_data *vc = vc_cons[currcons].d; struct vt_notifier_param param = { .vc = vc }; + atomic_notifier_call_chain(&vt_notifier_list, VT_DEALLOCATE, ¶m); + vcs_remove_sysfs(currcons); vc->vc_sw->con_deinit(vc); put_pid(vc->vt_pid); module_put(vc->vc_sw->owner); @@ -2775,7 +2778,6 @@ static int con_open(struct tty_struct *tty, struct file *filp) tty->termios->c_iflag |= IUTF8; else tty->termios->c_iflag &= ~IUTF8; - vcs_make_sysfs(tty); release_console_sem(); return ret; } @@ -2795,7 +2797,6 @@ static void con_shutdown(struct tty_struct *tty) BUG_ON(vc == NULL); acquire_console_sem(); vc->vc_tty = NULL; - vcs_remove_sysfs(tty); release_console_sem(); tty_shutdown(tty); } -- cgit v1.2.3 From f67f129e519fa87f8ebd236b6336fe43f31ee141 Mon Sep 17 00:00:00 2001 From: Ming Lei Date: Sun, 1 Mar 2009 21:10:49 +0800 Subject: Driver core: implement uevent suppress in kobject This patch implements uevent suppress in kobject and removes it from struct device, based on the following ideas: 1,Uevent sending should be one attribute of kobject, so suppressing it in kobject layer is more natural than in device layer. By this way, we can do it for other objects embedded with kobject. 2,It may save several bytes for each instance of struct device.(On my omap3(32bit ARM) based box, can save 8bytes per device object) This patch also introduces dev_set|get_uevent_suppress() helpers to set and query uevent_suppress attribute in case to help kobject as private part of struct device in future. [This version is against the latest driver-core patch set of Greg,please ignore the last version.] Signed-off-by: Ming Lei Signed-off-by: Greg Kroah-Hartman --- drivers/acpi/dock.c | 2 +- drivers/base/core.c | 2 -- drivers/base/firmware_class.c | 4 ++-- drivers/i2c/i2c-core.c | 2 +- drivers/s390/cio/chsc_sch.c | 4 ++-- drivers/s390/cio/css.c | 4 ++-- drivers/s390/cio/device.c | 4 ++-- 7 files changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/acpi/dock.c b/drivers/acpi/dock.c index 35094f230b1..7af7db1ba8c 100644 --- a/drivers/acpi/dock.c +++ b/drivers/acpi/dock.c @@ -977,7 +977,7 @@ static int dock_add(acpi_handle handle) sizeof(struct dock_station *)); /* we want the dock device to send uevents */ - dock_device->dev.uevent_suppress = 0; + dev_set_uevent_suppress(&dock_device->dev, 0); if (is_dock(handle)) dock_station->flags |= DOCK_IS_DOCK; diff --git a/drivers/base/core.c b/drivers/base/core.c index a90f56f64d6..95c67ffd71d 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -136,8 +136,6 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj) if (ktype == &device_ktype) { struct device *dev = to_dev(kobj); - if (dev->uevent_suppress) - return 0; if (dev->bus) return 1; if (dev->class) diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 44699d9dd85..d3a59c688fe 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -319,7 +319,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, f_dev->parent = device; f_dev->class = &firmware_class; dev_set_drvdata(f_dev, fw_priv); - f_dev->uevent_suppress = 1; + dev_set_uevent_suppress(f_dev, 1); retval = device_register(f_dev); if (retval) { dev_err(device, "%s: device_register failed\n", __func__); @@ -366,7 +366,7 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p, } if (uevent) - f_dev->uevent_suppress = 0; + dev_set_uevent_suppress(f_dev, 0); *dev_p = f_dev; goto out; diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e7d984866de..fbb9030b68a 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -841,7 +841,7 @@ int i2c_attach_client(struct i2c_client *client) if (client->driver && !is_newstyle_driver(client->driver)) { client->dev.release = i2c_client_release; - client->dev.uevent_suppress = 1; + dev_set_uevent_suppress(&client->dev, 1); } else client->dev.release = i2c_client_dev_release; diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 0a2f2edafc0..93eca1731b8 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c @@ -84,8 +84,8 @@ static int chsc_subchannel_probe(struct subchannel *sch) kfree(private); } else { sch->private = private; - if (sch->dev.uevent_suppress) { - sch->dev.uevent_suppress = 0; + if (dev_get_uevent_suppress(&sch->dev)) { + dev_set_uevent_suppress(&sch->dev, 0); kobject_uevent(&sch->dev.kobj, KOBJ_ADD); } } diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 8019288bc6d..427d11d8806 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -272,7 +272,7 @@ static int css_register_subchannel(struct subchannel *sch) * the subchannel driver can decide itself when it wants to inform * userspace of its existence. */ - sch->dev.uevent_suppress = 1; + dev_set_uevent_suppress(&sch->dev, 1); css_update_ssd_info(sch); /* make it known to the system */ ret = css_sch_device_register(sch); @@ -287,7 +287,7 @@ static int css_register_subchannel(struct subchannel *sch) * a fitting driver module may be loaded based on the * modalias. */ - sch->dev.uevent_suppress = 0; + dev_set_uevent_suppress(&sch->dev, 0); kobject_uevent(&sch->dev.kobj, KOBJ_ADD); } return ret; diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 23d5752349b..611d2e001dd 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -981,7 +981,7 @@ io_subchannel_register(struct work_struct *work) * Now we know this subchannel will stay, we can throw * our delayed uevent. */ - sch->dev.uevent_suppress = 0; + dev_set_uevent_suppress(&sch->dev, 0); kobject_uevent(&sch->dev.kobj, KOBJ_ADD); /* make it known to the system */ ret = ccw_device_register(cdev); @@ -1243,7 +1243,7 @@ static int io_subchannel_probe(struct subchannel *sch) * the ccw_device and exit. This happens for all early * devices, e.g. the console. */ - sch->dev.uevent_suppress = 0; + dev_set_uevent_suppress(&sch->dev, 0); kobject_uevent(&sch->dev.kobj, KOBJ_ADD); cdev->dev.groups = ccwdev_attr_groups; device_initialize(&cdev->dev); -- cgit v1.2.3 From 60530afe1ee8a5532cb09d0ab5bc3f1a6495b780 Mon Sep 17 00:00:00 2001 From: Zhenwen Xu Date: Tue, 3 Mar 2009 18:36:02 +0800 Subject: Driver core: some cleanup on drivers/base/sys.c do some cleanup on drivers/base/sys.c Signed-off-by: Zhenwen Xu Signed-off-by: Greg Kroah-Hartman --- drivers/base/sys.c | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/base/sys.c b/drivers/base/sys.c index b428c8c4bc6..cbd36cf59a0 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c @@ -30,10 +30,10 @@ static ssize_t -sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer) +sysdev_show(struct kobject *kobj, struct attribute *attr, char *buffer) { - struct sys_device * sysdev = to_sysdev(kobj); - struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); + struct sys_device *sysdev = to_sysdev(kobj); + struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr); if (sysdev_attr->show) return sysdev_attr->show(sysdev, sysdev_attr, buffer); @@ -42,11 +42,11 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer) static ssize_t -sysdev_store(struct kobject * kobj, struct attribute * attr, - const char * buffer, size_t count) +sysdev_store(struct kobject *kobj, struct attribute *attr, + const char *buffer, size_t count) { - struct sys_device * sysdev = to_sysdev(kobj); - struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); + struct sys_device *sysdev = to_sysdev(kobj); + struct sysdev_attribute *sysdev_attr = to_sysdev_attr(attr); if (sysdev_attr->store) return sysdev_attr->store(sysdev, sysdev_attr, buffer, count); @@ -63,13 +63,13 @@ static struct kobj_type ktype_sysdev = { }; -int sysdev_create_file(struct sys_device * s, struct sysdev_attribute * a) +int sysdev_create_file(struct sys_device *s, struct sysdev_attribute *a) { return sysfs_create_file(&s->kobj, &a->attr); } -void sysdev_remove_file(struct sys_device * s, struct sysdev_attribute * a) +void sysdev_remove_file(struct sys_device *s, struct sysdev_attribute *a) { sysfs_remove_file(&s->kobj, &a->attr); } @@ -84,7 +84,7 @@ EXPORT_SYMBOL_GPL(sysdev_remove_file); static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr, char *buffer) { - struct sysdev_class * class = to_sysdev_class(kobj); + struct sysdev_class *class = to_sysdev_class(kobj); struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); if (class_attr->show) @@ -95,8 +95,8 @@ static ssize_t sysdev_class_show(struct kobject *kobj, struct attribute *attr, static ssize_t sysdev_class_store(struct kobject *kobj, struct attribute *attr, const char *buffer, size_t count) { - struct sysdev_class * class = to_sysdev_class(kobj); - struct sysdev_class_attribute * class_attr = to_sysdev_class_attr(attr); + struct sysdev_class *class = to_sysdev_class(kobj); + struct sysdev_class_attribute *class_attr = to_sysdev_class_attr(attr); if (class_attr->store) return class_attr->store(class, buffer, count); @@ -128,7 +128,7 @@ EXPORT_SYMBOL_GPL(sysdev_class_remove_file); static struct kset *system_kset; -int sysdev_class_register(struct sysdev_class * cls) +int sysdev_class_register(struct sysdev_class *cls) { pr_debug("Registering sysdev class '%s'\n", cls->name); @@ -141,7 +141,7 @@ int sysdev_class_register(struct sysdev_class * cls) return kset_register(&cls->kset); } -void sysdev_class_unregister(struct sysdev_class * cls) +void sysdev_class_unregister(struct sysdev_class *cls) { pr_debug("Unregistering sysdev class '%s'\n", kobject_name(&cls->kset.kobj)); @@ -203,8 +203,8 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) * @cls: Class driver belongs to. * @drv: Driver. */ -void sysdev_driver_unregister(struct sysdev_class * cls, - struct sysdev_driver * drv) +void sysdev_driver_unregister(struct sysdev_class *cls, + struct sysdev_driver *drv) { mutex_lock(&sysdev_drivers_lock); list_del_init(&drv->entry); @@ -229,10 +229,10 @@ EXPORT_SYMBOL_GPL(sysdev_driver_unregister); * @sysdev: device in question * */ -int sysdev_register(struct sys_device * sysdev) +int sysdev_register(struct sys_device *sysdev) { int error; - struct sysdev_class * cls = sysdev->cls; + struct sysdev_class *cls = sysdev->cls; if (!cls) return -EINVAL; @@ -252,7 +252,7 @@ int sysdev_register(struct sys_device * sysdev) sysdev->id); if (!error) { - struct sysdev_driver * drv; + struct sysdev_driver *drv; pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj)); @@ -274,9 +274,9 @@ int sysdev_register(struct sys_device * sysdev) return error; } -void sysdev_unregister(struct sys_device * sysdev) +void sysdev_unregister(struct sys_device *sysdev) { - struct sysdev_driver * drv; + struct sysdev_driver *drv; mutex_lock(&sysdev_drivers_lock); list_for_each_entry(drv, &sysdev->cls->drivers, entry) { @@ -305,19 +305,19 @@ void sysdev_unregister(struct sys_device * sysdev) */ void sysdev_shutdown(void) { - struct sysdev_class * cls; + struct sysdev_class *cls; pr_debug("Shutting Down System Devices\n"); mutex_lock(&sysdev_drivers_lock); list_for_each_entry_reverse(cls, &system_kset->list, kset.kobj.entry) { - struct sys_device * sysdev; + struct sys_device *sysdev; pr_debug("Shutting down type '%s':\n", kobject_name(&cls->kset.kobj)); list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) { - struct sysdev_driver * drv; + struct sysdev_driver *drv; pr_debug(" %s\n", kobject_name(&sysdev->kobj)); /* Call auxillary drivers first */ @@ -364,7 +364,7 @@ static void __sysdev_resume(struct sys_device *dev) */ int sysdev_suspend(pm_message_t state) { - struct sysdev_class * cls; + struct sysdev_class *cls; struct sys_device *sysdev, *err_dev; struct sysdev_driver *drv, *err_drv; int ret; @@ -442,12 +442,12 @@ EXPORT_SYMBOL_GPL(sysdev_suspend); */ int sysdev_resume(void) { - struct sysdev_class * cls; + struct sysdev_class *cls; pr_debug("Resuming System Devices\n"); list_for_each_entry(cls, &system_kset->list, kset.kobj.entry) { - struct sys_device * sysdev; + struct sys_device *sysdev; pr_debug("Resuming type '%s':\n", kobject_name(&cls->kset.kobj)); -- cgit v1.2.3 From ffa6a7054d172a2f57248dff2de600ca795c5656 Mon Sep 17 00:00:00 2001 From: Cornelia Huck Date: Wed, 4 Mar 2009 12:44:00 +0100 Subject: Driver core: Fix device_move() vs. dpm list ordering, v2 dpm_list currently relies on the fact that child devices will be registered after their parents to get a correct suspend order. Using device_move() however destroys this assumption, as an already registered device may be moved under a newly registered one. This patch adds a new argument to device_move(), allowing callers to specify how dpm_list should be adapted. Signed-off-by: Cornelia Huck Acked-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 19 ++++++++++++++++++- drivers/base/power/main.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ drivers/base/power/power.h | 8 ++++++++ drivers/s390/cio/device.c | 9 +++++---- 4 files changed, 75 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 95c67ffd71d..e73c92d13a2 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1561,8 +1561,10 @@ out: * device_move - moves a device to a new parent * @dev: the pointer to the struct device to be moved * @new_parent: the new parent of the device (can by NULL) + * @dpm_order: how to reorder the dpm_list */ -int device_move(struct device *dev, struct device *new_parent) +int device_move(struct device *dev, struct device *new_parent, + enum dpm_order dpm_order) { int error; struct device *old_parent; @@ -1572,6 +1574,7 @@ int device_move(struct device *dev, struct device *new_parent) if (!dev) return -EINVAL; + device_pm_lock(); new_parent = get_device(new_parent); new_parent_kobj = get_device_parent(dev, new_parent); @@ -1613,9 +1616,23 @@ int device_move(struct device *dev, struct device *new_parent) put_device(new_parent); goto out; } + switch (dpm_order) { + case DPM_ORDER_NONE: + break; + case DPM_ORDER_DEV_AFTER_PARENT: + device_pm_move_after(dev, new_parent); + break; + case DPM_ORDER_PARENT_BEFORE_DEV: + device_pm_move_before(new_parent, dev); + break; + case DPM_ORDER_DEV_LAST: + device_pm_move_last(dev); + break; + } out_put: put_device(old_parent); out: + device_pm_unlock(); put_device(dev); return error; } diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 2d14f4ae6c0..e255341682c 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -106,6 +106,50 @@ void device_pm_remove(struct device *dev) mutex_unlock(&dpm_list_mtx); } +/** + * device_pm_move_before - move device in dpm_list + * @deva: Device to move in dpm_list + * @devb: Device @deva should come before + */ +void device_pm_move_before(struct device *deva, struct device *devb) +{ + pr_debug("PM: Moving %s:%s before %s:%s\n", + deva->bus ? deva->bus->name : "No Bus", + kobject_name(&deva->kobj), + devb->bus ? devb->bus->name : "No Bus", + kobject_name(&devb->kobj)); + /* Delete deva from dpm_list and reinsert before devb. */ + list_move_tail(&deva->power.entry, &devb->power.entry); +} + +/** + * device_pm_move_after - move device in dpm_list + * @deva: Device to move in dpm_list + * @devb: Device @deva should come after + */ +void device_pm_move_after(struct device *deva, struct device *devb) +{ + pr_debug("PM: Moving %s:%s after %s:%s\n", + deva->bus ? deva->bus->name : "No Bus", + kobject_name(&deva->kobj), + devb->bus ? devb->bus->name : "No Bus", + kobject_name(&devb->kobj)); + /* Delete deva from dpm_list and reinsert after devb. */ + list_move(&deva->power.entry, &devb->power.entry); +} + +/** + * device_pm_move_last - move device to end of dpm_list + * @dev: Device to move in dpm_list + */ +void device_pm_move_last(struct device *dev) +{ + pr_debug("PM: Moving %s:%s to end of list\n", + dev->bus ? dev->bus->name : "No Bus", + kobject_name(&dev->kobj)); + list_move_tail(&dev->power.entry, &dpm_list); +} + /** * pm_op - execute the PM operation appropiate for given PM event * @dev: Device. diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index 41f51fae042..c7cb4fc3735 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -18,11 +18,19 @@ static inline struct device *to_device(struct list_head *entry) extern void device_pm_add(struct device *); extern void device_pm_remove(struct device *); +extern void device_pm_move_before(struct device *, struct device *); +extern void device_pm_move_after(struct device *, struct device *); +extern void device_pm_move_last(struct device *); #else /* CONFIG_PM_SLEEP */ static inline void device_pm_add(struct device *dev) {} static inline void device_pm_remove(struct device *dev) {} +static inline void device_pm_move_before(struct device *deva, + struct device *devb) {} +static inline void device_pm_move_after(struct device *deva, + struct device *devb) {} +static inline void device_pm_move_last(struct device *dev) {} #endif diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 611d2e001dd..e28f8ae5345 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -799,7 +799,7 @@ static void sch_attach_disconnected_device(struct subchannel *sch, return; other_sch = to_subchannel(cdev->dev.parent); /* Note: device_move() changes cdev->dev.parent */ - ret = device_move(&cdev->dev, &sch->dev); + ret = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV); if (ret) { CIO_MSG_EVENT(0, "Moving disconnected device 0.%x.%04x failed " "(ret=%d)!\n", cdev->private->dev_id.ssid, @@ -830,7 +830,7 @@ static void sch_attach_orphaned_device(struct subchannel *sch, * Try to move the ccw device to its new subchannel. * Note: device_move() changes cdev->dev.parent */ - ret = device_move(&cdev->dev, &sch->dev); + ret = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV); if (ret) { CIO_MSG_EVENT(0, "Moving device 0.%x.%04x from orphanage " "failed (ret=%d)!\n", @@ -897,7 +897,8 @@ void ccw_device_move_to_orphanage(struct work_struct *work) * ccw device can take its place on the subchannel. * Note: device_move() changes cdev->dev.parent */ - ret = device_move(&cdev->dev, &css->pseudo_subchannel->dev); + ret = device_move(&cdev->dev, &css->pseudo_subchannel->dev, + DPM_ORDER_NONE); if (ret) { CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to orphanage failed " "(ret=%d)!\n", cdev->private->dev_id.ssid, @@ -1129,7 +1130,7 @@ static void ccw_device_move_to_sch(struct work_struct *work) * Try to move the ccw device to its new subchannel. * Note: device_move() changes cdev->dev.parent */ - rc = device_move(&cdev->dev, &sch->dev); + rc = device_move(&cdev->dev, &sch->dev, DPM_ORDER_PARENT_BEFORE_DEV); mutex_unlock(&sch->reg_mutex); if (rc) { CIO_MSG_EVENT(0, "Moving device 0.%x.%04x to subchannel " -- cgit v1.2.3 From 669420644c79c207f83fdf9105ae782867e2991f Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Fri, 13 Mar 2009 12:07:36 -0600 Subject: sysfs: only allow one scheduled removal callback per kobj The only way for a sysfs attribute to remove itself (without deadlock) is to use the sysfs_schedule_callback() interface. Vegard Nossum discovered that a poorly written sysfs ->store callback can repeatedly schedule remove callbacks on the same device over and over, e.g. $ while true ; do echo 1 > /sys/devices/.../remove ; done If the 'remove' attribute uses the sysfs_schedule_callback API and also does not protect itself from concurrent accesses, its callback handler will be called multiple times, and will eventually attempt to perform operations on a freed kobject, leading to many problems. Instead of requiring all callers of sysfs_schedule_callback to implement their own synchronization, provide the protection in the infrastructure. Now, sysfs_schedule_callback will only allow one scheduled callback per kobject. On subsequent calls with the same kobject, return -EAGAIN. This is a short term fix. The long term fix is to allow sysfs attributes to remove themselves directly, without any of this callback hokey pokey. [cornelia.huck@de.ibm.com: s390 ccwgroup bits] Reported-by: vegard.nossum@gmail.com Signed-off-by: Alex Chiang Acked-by: Cornelia Huck Signed-off-by: Greg Kroah-Hartman --- drivers/s390/cio/ccwgroup.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 918e6fce257..b91c1719b07 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -104,8 +104,9 @@ ccwgroup_ungroup_store(struct device *dev, struct device_attribute *attr, const rc = device_schedule_callback(dev, ccwgroup_ungroup_callback); out: if (rc) { - /* Release onoff "lock" when ungrouping failed. */ - atomic_set(&gdev->onoff, 0); + if (rc != -EAGAIN) + /* Release onoff "lock" when ungrouping failed. */ + atomic_set(&gdev->onoff, 0); return rc; } return count; -- cgit v1.2.3 From 91b1a84c10869e2e46a576e5367de3166bff8ecc Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:46:39 -0500 Subject: sata_mv: cleanup chipset GENeration FLAGS Clean up the chipset GENeration FLAGS, and rename them for consistency with other uses of GEN_XX within sata_mv. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 74b1080d116..3dc35543fb3 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -120,14 +120,15 @@ enum { MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | - ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | - ATA_FLAG_PIO_POLLING, + ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, - MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE, + MV_GEN_I_FLAGS = MV_COMMON_FLAGS | ATA_FLAG_NO_ATAPI, - MV_GENIIE_FLAGS = MV_COMMON_FLAGS | MV_6XXX_FLAGS | + MV_GEN_II_FLAGS = MV_COMMON_FLAGS | MV_FLAG_IRQ_COALESCE | ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA | - ATA_FLAG_NCQ | ATA_FLAG_AN, + ATA_FLAG_NCQ | ATA_FLAG_NO_ATAPI, + + MV_GEN_IIE_FLAGS = MV_GEN_II_FLAGS | ATA_FLAG_AN, CRQB_FLAG_READ = (1 << 0), CRQB_TAG_SHIFT = 1, @@ -603,53 +604,49 @@ static struct ata_port_operations mv_iie_ops = { static const struct ata_port_info mv_port_info[] = { { /* chip_504x */ - .flags = MV_COMMON_FLAGS, + .flags = MV_GEN_I_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv5_ops, }, { /* chip_508x */ - .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC, + .flags = MV_GEN_I_FLAGS | MV_FLAG_DUAL_HC, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv5_ops, }, { /* chip_5080 */ - .flags = MV_COMMON_FLAGS | MV_FLAG_DUAL_HC, + .flags = MV_GEN_I_FLAGS | MV_FLAG_DUAL_HC, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv5_ops, }, { /* chip_604x */ - .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS | - ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA | - ATA_FLAG_NCQ, + .flags = MV_GEN_II_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv6_ops, }, { /* chip_608x */ - .flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS | - ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA | - ATA_FLAG_NCQ | MV_FLAG_DUAL_HC, + .flags = MV_GEN_II_FLAGS | MV_FLAG_DUAL_HC, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv6_ops, }, { /* chip_6042 */ - .flags = MV_GENIIE_FLAGS, + .flags = MV_GEN_IIE_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv_iie_ops, }, { /* chip_7042 */ - .flags = MV_GENIIE_FLAGS, + .flags = MV_GEN_IIE_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv_iie_ops, }, { /* chip_soc */ - .flags = MV_GENIIE_FLAGS, + .flags = MV_GEN_IIE_FLAGS, .pio_mask = 0x1f, /* pio0-4 */ .udma_mask = ATA_UDMA6, .port_ops = &mv_iie_ops, -- cgit v1.2.3 From 00b81235aa0368f84c0e704bec4142cd8c516ad5 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:47:51 -0500 Subject: sata_mv: rearrange mv_start_dma() and friends Rearrange mv_start_dma() and friends, in preparation for adding non-EDMA DMA modes, and non-EDMA interrupts, to the driver. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 66 +++++++++++++++++++++++++++++---------------------- 1 file changed, 38 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 3dc35543fb3..fb3288bbd9f 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -536,7 +536,7 @@ static void mv_reset_channel(struct mv_host_priv *hpriv, void __iomem *mmio, unsigned int port_no); static int mv_stop_edma(struct ata_port *ap); static int mv_stop_edma_engine(void __iomem *port_mmio); -static void mv_edma_cfg(struct ata_port *ap, int want_ncq); +static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma); static void mv_pmp_select(struct ata_port *ap, int pmp); static int mv_pmp_hardreset(struct ata_link *link, unsigned int *class, @@ -849,8 +849,32 @@ static void mv_enable_port_irqs(struct ata_port *ap, mv_set_main_irq_mask(ap->host, disable_bits, enable_bits); } +static void mv_clear_and_enable_port_irqs(struct ata_port *ap, + void __iomem *port_mmio, + unsigned int port_irqs) +{ + struct mv_host_priv *hpriv = ap->host->private_data; + int hardport = mv_hardport_from_port(ap->port_no); + void __iomem *hc_mmio = mv_hc_base_from_port( + mv_host_base(ap->host), ap->port_no); + u32 hc_irq_cause; + + /* clear EDMA event indicators, if any */ + writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); + + /* clear pending irq events */ + hc_irq_cause = ~((DEV_IRQ | DMA_IRQ) << hardport); + writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); + + /* clear FIS IRQ Cause */ + if (IS_GEN_IIE(hpriv)) + writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS); + + mv_enable_port_irqs(ap, port_irqs); +} + /** - * mv_start_dma - Enable eDMA engine + * mv_start_edma - Enable eDMA engine * @base: port base address * @pp: port private data * @@ -860,7 +884,7 @@ static void mv_enable_port_irqs(struct ata_port *ap, * LOCKING: * Inherited from caller. */ -static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio, +static void mv_start_edma(struct ata_port *ap, void __iomem *port_mmio, struct mv_port_priv *pp, u8 protocol) { int want_ncq = (protocol == ATA_PROT_NCQ); @@ -872,26 +896,11 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio, } if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) { struct mv_host_priv *hpriv = ap->host->private_data; - int hardport = mv_hardport_from_port(ap->port_no); - void __iomem *hc_mmio = mv_hc_base_from_port( - mv_host_base(ap->host), ap->port_no); - u32 hc_irq_cause; - - /* clear EDMA event indicators, if any */ - writelfl(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS); - - /* clear pending irq events */ - hc_irq_cause = ~((DEV_IRQ | DMA_IRQ) << hardport); - writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS); - mv_edma_cfg(ap, want_ncq); - - /* clear FIS IRQ Cause */ - if (IS_GEN_IIE(hpriv)) - writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS); + mv_edma_cfg(ap, want_ncq, 1); mv_set_edma_ptrs(port_mmio, hpriv, pp); - mv_enable_port_irqs(ap, DONE_IRQ|ERR_IRQ); + mv_clear_and_enable_port_irqs(ap, port_mmio, DONE_IRQ|ERR_IRQ); writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS); pp->pp_flags |= MV_PP_FLAG_EDMA_EN; @@ -1173,7 +1182,7 @@ static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq) writel(new, hpriv->base + MV_GPIO_PORT_CTL_OFS); } -static void mv_edma_cfg(struct ata_port *ap, int want_ncq) +static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) { u32 cfg; struct mv_port_priv *pp = ap->private_data; @@ -1182,7 +1191,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq) /* set up non-NCQ EDMA configuration */ cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ - pp->pp_flags &= ~MV_PP_FLAG_FBS_EN; + pp->pp_flags &= ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN); if (IS_GEN_I(hpriv)) cfg |= (1 << 8); /* enab config burst size mask */ @@ -1211,9 +1220,11 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq) } cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */ - cfg |= (1 << 22); /* enab 4-entry host queue cache */ - if (!IS_SOC(hpriv)) - cfg |= (1 << 18); /* enab early completion */ + if (want_edma) { + cfg |= (1 << 22); /* enab 4-entry host queue cache */ + if (!IS_SOC(hpriv)) + cfg |= (1 << 18); /* enab early completion */ + } if (hpriv->hp_flags & MV_HP_CUT_THROUGH) cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ } @@ -1221,8 +1232,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq) if (want_ncq) { cfg |= EDMA_CFG_NCQ; pp->pp_flags |= MV_PP_FLAG_NCQ_EN; - } else - pp->pp_flags &= ~MV_PP_FLAG_NCQ_EN; + } writelfl(cfg, port_mmio + EDMA_CFG_OFS); } @@ -1591,7 +1601,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) return ata_sff_qc_issue(qc); } - mv_start_dma(ap, port_mmio, pp, qc->tf.protocol); + mv_start_edma(ap, port_mmio, pp, qc->tf.protocol); pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK; in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT; -- cgit v1.2.3 From f48765ccb48a62596b664aa88a2b0f943c12c0e1 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:48:41 -0500 Subject: sata_mv: restructure mv_qc_issue Rearrange logic in mv_qc_issue() to handle protocols other than ATA_PROT_DMA, ATA_PROT_NCQ, and ATA_PROT_PIO. This is in preparation for later enabling ATAPI support. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index fb3288bbd9f..0c25f52249d 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1565,14 +1565,26 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc) */ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) { + static int limit_warnings = 10; struct ata_port *ap = qc->ap; void __iomem *port_mmio = mv_ap_base(ap); struct mv_port_priv *pp = ap->private_data; u32 in_index; + unsigned int port_irqs = DONE_IRQ | ERR_IRQ; + + switch (qc->tf.protocol) { + case ATA_PROT_DMA: + case ATA_PROT_NCQ: + mv_start_edma(ap, port_mmio, pp, qc->tf.protocol); + pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK; + in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT; + + /* Write the request in pointer to kick the EDMA to life */ + writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index, + port_mmio + EDMA_REQ_Q_IN_PTR_OFS); + return 0; - if ((qc->tf.protocol != ATA_PROT_DMA) && - (qc->tf.protocol != ATA_PROT_NCQ)) { - static int limit_warnings = 10; + case ATA_PROT_PIO: /* * Errata SATA#16, SATA#24: warn if multiple DRQs expected. * @@ -1590,27 +1602,22 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) ": attempting PIO w/multiple DRQ: " "this may fail due to h/w errata\n"); } + /* drop through */ + case ATAPI_PROT_PIO: + port_irqs = ERR_IRQ; /* leave DONE_IRQ masked for PIO */ + /* drop through */ + default: /* * We're about to send a non-EDMA capable command to the * port. Turn off EDMA so there won't be problems accessing * shadow block, etc registers. */ mv_stop_edma(ap); - mv_enable_port_irqs(ap, ERR_IRQ); + mv_edma_cfg(ap, 0, 0); + mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); mv_pmp_select(ap, qc->dev->link->pmp); return ata_sff_qc_issue(qc); } - - mv_start_edma(ap, port_mmio, pp, qc->tf.protocol); - - pp->req_idx = (pp->req_idx + 1) & MV_MAX_Q_DEPTH_MASK; - in_index = pp->req_idx << EDMA_REQ_Q_PTR_SHIFT; - - /* and write the request in pointer to kick the EDMA to life */ - writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | in_index, - port_mmio + EDMA_REQ_Q_IN_PTR_OFS); - - return 0; } static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap) -- cgit v1.2.3 From 95db505125fb7bc624b7c3b6747bbeaebbffc2e4 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:49:29 -0500 Subject: sata_mv: update ata_qc_from_tag Update the logic in ata_qc_from_tag() to match that used in similar places elsewhere in libata. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 0c25f52249d..181f0212741 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1628,6 +1628,12 @@ static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap) if (pp->pp_flags & MV_PP_FLAG_NCQ_EN) return NULL; qc = ata_qc_from_tag(ap, ap->link.active_tag); + if (qc) { + if (qc->tf.flags & ATA_TFLAG_POLLING) + qc = NULL; + else if (!(qc->flags & ATA_QCFLAG_ACTIVE)) + qc = NULL; + } if (qc && (qc->tf.flags & ATA_TFLAG_POLLING)) qc = NULL; return qc; -- cgit v1.2.3 From 32cd11a61007511ddb38783deec8bb1aa6735789 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Sun, 1 Feb 2009 16:50:32 -0500 Subject: sata_mv: mv_fill_sg fixes v2 Fix mv_fill_sg() to zero out the reserved word (required for ATAPI), and to include a memory barrier. This may also help with problems reported by Jens on the PPC platform. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 181f0212741..9c8ea2c1116 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1364,12 +1364,13 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) u32 offset = addr & 0xffff; u32 len = sg_len; - if ((offset + sg_len > 0x10000)) + if (offset + len > 0x10000) len = 0x10000 - offset; mv_sg->addr = cpu_to_le32(addr & 0xffffffff); mv_sg->addr_hi = cpu_to_le32((addr >> 16) >> 16); mv_sg->flags_size = cpu_to_le32(len & 0xffff); + mv_sg->reserved = 0; sg_len -= len; addr += len; @@ -1381,6 +1382,7 @@ static void mv_fill_sg(struct ata_queued_cmd *qc) if (likely(last_sg)) last_sg->flags_size |= cpu_to_le32(EPRD_FLAG_END_OF_TBL); + mb(); /* ensure data structure is visible to the chipset */ } static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) -- cgit v1.2.3 From da14265e776f35067045b8555b5f5f7521e50bc4 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:51:54 -0500 Subject: sata_mv: introduce support for ATAPI devices Add ATAPI support to sata_mv, using sff DMA for GEN_II chipsets, and plain old PIO for GEN_IIE. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 186 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 9c8ea2c1116..6f8a49bc452 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -31,8 +31,6 @@ * * --> Complete a full errata audit for all chipsets to identify others. * - * --> ATAPI support (Marvell claims the 60xx/70xx chips can do it). - * * --> Develop a low-power-consumption strategy, and implement it. * * --> [Experiment, low priority] Investigate interrupt coalescing. @@ -68,7 +66,7 @@ #include #define DRV_NAME "sata_mv" -#define DRV_VERSION "1.25" +#define DRV_VERSION "1.26" enum { /* BAR's are enumerated in terms of pci_resource_start() terms */ @@ -126,7 +124,7 @@ enum { MV_GEN_II_FLAGS = MV_COMMON_FLAGS | MV_FLAG_IRQ_COALESCE | ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA | - ATA_FLAG_NCQ | ATA_FLAG_NO_ATAPI, + ATA_FLAG_NCQ, MV_GEN_IIE_FLAGS = MV_GEN_II_FLAGS | ATA_FLAG_AN, @@ -348,6 +346,12 @@ enum { EDMA_HALTCOND_OFS = 0x60, /* GenIIe halt conditions */ + + BMDMA_CMD_OFS = 0x224, /* bmdma command register */ + BMDMA_STATUS_OFS = 0x228, /* bmdma status register */ + BMDMA_PRD_LOW_OFS = 0x22c, /* bmdma PRD addr 31:0 */ + BMDMA_PRD_HIGH_OFS = 0x230, /* bmdma PRD addr 63:32 */ + /* Host private flags (hp_flags) */ MV_HP_FLAG_MSI = (1 << 0), MV_HP_ERRATA_50XXB0 = (1 << 1), @@ -547,6 +551,15 @@ static void mv_pmp_error_handler(struct ata_port *ap); static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp); +static unsigned long mv_mode_filter(struct ata_device *dev, + unsigned long xfer_mask); +static void mv_sff_irq_clear(struct ata_port *ap); +static int mv_check_atapi_dma(struct ata_queued_cmd *qc); +static void mv_bmdma_setup(struct ata_queued_cmd *qc); +static void mv_bmdma_start(struct ata_queued_cmd *qc); +static void mv_bmdma_stop(struct ata_queued_cmd *qc); +static u8 mv_bmdma_status(struct ata_port *ap); + /* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below * because we have to allow room for worst case splitting of * PRDs for 64K boundaries in mv_fill_sg(). @@ -594,6 +607,14 @@ static struct ata_port_operations mv6_ops = { .pmp_softreset = mv_softreset, .softreset = mv_softreset, .error_handler = mv_pmp_error_handler, + + .sff_irq_clear = mv_sff_irq_clear, + .check_atapi_dma = mv_check_atapi_dma, + .bmdma_setup = mv_bmdma_setup, + .bmdma_start = mv_bmdma_start, + .bmdma_stop = mv_bmdma_stop, + .bmdma_status = mv_bmdma_status, + .mode_filter = mv_mode_filter, }; static struct ata_port_operations mv_iie_ops = { @@ -1392,6 +1413,167 @@ static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) *cmdw = cpu_to_le16(tmp); } +/** + * mv_mode_filter - Allow ATAPI DMA only on GenII chips. + * @dev: device whose xfer modes are being configured. + * + * Only the GenII hardware can use DMA with ATAPI drives. + */ +static unsigned long mv_mode_filter(struct ata_device *adev, + unsigned long xfer_mask) +{ + if (adev->class == ATA_DEV_ATAPI) { + struct mv_host_priv *hpriv = adev->link->ap->host->private_data; + if (!IS_GEN_II(hpriv)) { + xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); + ata_dev_printk(adev, KERN_INFO, + "ATAPI DMA not supported on this chipset\n"); + } + } + return xfer_mask; +} + +/** + * mv_sff_irq_clear - Clear hardware interrupt after DMA. + * @ap: Port associated with this ATA transaction. + * + * We need this only for ATAPI bmdma transactions, + * as otherwise we experience spurious interrupts + * after libata-sff handles the bmdma interrupts. + */ +static void mv_sff_irq_clear(struct ata_port *ap) +{ + mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), ERR_IRQ); +} + +/** + * mv_check_atapi_dma - Filter ATAPI cmds which are unsuitable for DMA. + * @qc: queued command to check for chipset/DMA compatibility. + * + * The bmdma engines cannot handle speculative data sizes + * (bytecount under/over flow). So only allow DMA for + * data transfer commands with known data sizes. + * + * LOCKING: + * Inherited from caller. + */ +static int mv_check_atapi_dma(struct ata_queued_cmd *qc) +{ + struct scsi_cmnd *scmd = qc->scsicmd; + + if (scmd) { + switch (scmd->cmnd[0]) { + case READ_6: + case READ_10: + case READ_12: + case WRITE_6: + case WRITE_10: + case WRITE_12: + case GPCMD_READ_CD: + case GPCMD_SEND_DVD_STRUCTURE: + case GPCMD_SEND_CUE_SHEET: + return 0; /* DMA is safe */ + } + } + return -EOPNOTSUPP; /* use PIO instead */ +} + +/** + * mv_bmdma_setup - Set up BMDMA transaction + * @qc: queued command to prepare DMA for. + * + * LOCKING: + * Inherited from caller. + */ +static void mv_bmdma_setup(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *port_mmio = mv_ap_base(ap); + struct mv_port_priv *pp = ap->private_data; + + mv_fill_sg(qc); + + /* clear all DMA cmd bits */ + writel(0, port_mmio + BMDMA_CMD_OFS); + + /* load PRD table addr. */ + writel((pp->sg_tbl_dma[qc->tag] >> 16) >> 16, + port_mmio + BMDMA_PRD_HIGH_OFS); + writelfl(pp->sg_tbl_dma[qc->tag], + port_mmio + BMDMA_PRD_LOW_OFS); + + /* issue r/w command */ + ap->ops->sff_exec_command(ap, &qc->tf); +} + +/** + * mv_bmdma_start - Start a BMDMA transaction + * @qc: queued command to start DMA on. + * + * LOCKING: + * Inherited from caller. + */ +static void mv_bmdma_start(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *port_mmio = mv_ap_base(ap); + unsigned int rw = (qc->tf.flags & ATA_TFLAG_WRITE); + u32 cmd = (rw ? 0 : ATA_DMA_WR) | ATA_DMA_START; + + /* start host DMA transaction */ + writelfl(cmd, port_mmio + BMDMA_CMD_OFS); +} + +/** + * mv_bmdma_stop - Stop BMDMA transfer + * @qc: queued command to stop DMA on. + * + * Clears the ATA_DMA_START flag in the bmdma control register + * + * LOCKING: + * Inherited from caller. + */ +static void mv_bmdma_stop(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + void __iomem *port_mmio = mv_ap_base(ap); + u32 cmd; + + /* clear start/stop bit */ + cmd = readl(port_mmio + BMDMA_CMD_OFS); + cmd &= ~ATA_DMA_START; + writelfl(cmd, port_mmio + BMDMA_CMD_OFS); + + /* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */ + ata_sff_dma_pause(ap); +} + +/** + * mv_bmdma_status - Read BMDMA status + * @ap: port for which to retrieve DMA status. + * + * Read and return equivalent of the sff BMDMA status register. + * + * LOCKING: + * Inherited from caller. + */ +static u8 mv_bmdma_status(struct ata_port *ap) +{ + void __iomem *port_mmio = mv_ap_base(ap); + u32 reg, status; + + /* + * Other bits are valid only if ATA_DMA_ACTIVE==0, + * and the ATA_DMA_INTR bit doesn't exist. + */ + reg = readl(port_mmio + BMDMA_STATUS_OFS); + if (reg & ATA_DMA_ACTIVE) + status = ATA_DMA_ACTIVE; + else + status = (reg & ATA_DMA_ERR) | ATA_DMA_INTR; + return status; +} + /** * mv_qc_prep - Host specific command preparation. * @qc: queued command to prepare -- cgit v1.2.3 From 66e57a2cb0c538d4f84a7233c224735fe1eaa672 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 18:52:58 -0500 Subject: sata_mv: optimize use of mv_edma_cfg Try and avoid unnecessary reconfiguration of the EDMA config register on every single non-EDMA I/O operation, by moving the call to mv_edma_cfg() into mv_stop_edma(). It must then also be invoked from mv_hardreset() and from mv_port_start(). Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 6f8a49bc452..8f356e4417d 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -979,6 +979,7 @@ static int mv_stop_edma(struct ata_port *ap) { void __iomem *port_mmio = mv_ap_base(ap); struct mv_port_priv *pp = ap->private_data; + int err = 0; if (!(pp->pp_flags & MV_PP_FLAG_EDMA_EN)) return 0; @@ -986,9 +987,10 @@ static int mv_stop_edma(struct ata_port *ap) mv_wait_for_edma_empty_idle(ap); if (mv_stop_edma_engine(port_mmio)) { ata_port_printk(ap, KERN_ERR, "Unable to stop eDMA\n"); - return -EIO; + err = -EIO; } - return 0; + mv_edma_cfg(ap, 0, 0); + return err; } #ifdef ATA_DEBUG @@ -1337,6 +1339,7 @@ static int mv_port_start(struct ata_port *ap) pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0]; } } + mv_edma_cfg(ap, 0, 0); return 0; out_port_free_dma_mem: @@ -1797,7 +1800,6 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) * shadow block, etc registers. */ mv_stop_edma(ap); - mv_edma_cfg(ap, 0, 0); mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); mv_pmp_select(ap, qc->dev->link->pmp); return ata_sff_qc_issue(qc); @@ -2997,6 +2999,7 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class, extra = HZ; /* only extend it once, max */ } } while (sstatus != 0x0 && sstatus != 0x113 && sstatus != 0x123); + mv_edma_cfg(ap, 0, 0); return rc; } -- cgit v1.2.3 From 84bcbeebcfd283c3f4804287ed4610c3a18e1590 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Fri, 30 Jan 2009 21:40:48 -0500 Subject: sata_mv: remove leftovers Remove redundant code left over from the earlier patch 04/07. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 8f356e4417d..1f14b1b5234 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1820,8 +1820,6 @@ static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap) else if (!(qc->flags & ATA_QCFLAG_ACTIVE)) qc = NULL; } - if (qc && (qc->tf.flags & ATA_TFLAG_POLLING)) - qc = NULL; return qc; } -- cgit v1.2.3 From 96b34ce7cafa0888580698d199b9fac6ad9f9a2e Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 27 Jan 2009 14:35:50 +0100 Subject: pata-rb532-cf: replace rb532_pata_finish_io() Since the delay used internally is just the same as ata_sff_pause() uses, rb532_pata_finish_io() does exactly the same as ata_sff_pause() and thus can be replaced by the later one. Signed-off-by: Phil Sutter Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index ebfcda26d63..6fe660b27dc 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -54,22 +54,11 @@ struct rb532_cf_info { /* ------------------------------------------------------------------------ */ -static inline void rb532_pata_finish_io(struct ata_port *ap) -{ - struct ata_host *ah = ap->host; - struct rb532_cf_info *info = ah->private_data; - - /* FIXME: Keep previous delay. If this is merely a fence then - ata_sff_sync might be sufficient. */ - ata_sff_dma_pause(ap); - ndelay(RB500_CF_IO_DELAY); -} - static void rb532_pata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf) { writeb(tf->command, ap->ioaddr.command_addr); - rb532_pata_finish_io(ap); + ata_sff_pause(ap); } static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf, @@ -87,7 +76,7 @@ static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf = readb(ioaddr); } - rb532_pata_finish_io(adev->link->ap); + ata_sff_pause(ap); return retlen; } -- cgit v1.2.3 From bff9ad3c4c8fff340854d3912196ed470f94602c Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 27 Jan 2009 14:35:51 +0100 Subject: pata-rb532-cf: use ata_sff_exec_command() The only difference between rb532_pata_exec_command() and ata_sff_exec_command() is added debugging output, so it can be dropped and the standard op used instead. Signed-off-by: Phil Sutter Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 8 -------- 1 file changed, 8 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 6fe660b27dc..9d61ce51e4e 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -54,13 +54,6 @@ struct rb532_cf_info { /* ------------------------------------------------------------------------ */ -static void rb532_pata_exec_command(struct ata_port *ap, - const struct ata_taskfile *tf) -{ - writeb(tf->command, ap->ioaddr.command_addr); - ata_sff_pause(ap); -} - static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data) { @@ -112,7 +105,6 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance) static struct ata_port_operations rb532_pata_port_ops = { .inherits = &ata_sff_port_ops, - .sff_exec_command = rb532_pata_exec_command, .sff_data_xfer = rb532_pata_data_xfer, .freeze = rb532_pata_freeze, .thaw = rb532_pata_thaw, -- cgit v1.2.3 From 180bd147f18316d92bd5f59aebc9932cabc03edd Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 27 Jan 2009 14:35:52 +0100 Subject: pata-rb532-cf: use ata_sff_data_xfer32() The biggest difference between rb532_pata_data_xfer() and ata_sff_data_xfer32() is the call to ata_sff_pause() at the end of rb532_pata_data_xfer() which I suppose to be unnecessary since it works without. I've also tested using ata_sff_data_xfer() as replacement, but since we know that the driver supports 32bit IO, using the optimised version should be safe. Signed-off-by: Phil Sutter Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 9d61ce51e4e..9fb91e4dd88 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -54,25 +54,6 @@ struct rb532_cf_info { /* ------------------------------------------------------------------------ */ -static unsigned int rb532_pata_data_xfer(struct ata_device *adev, unsigned char *buf, - unsigned int buflen, int write_data) -{ - struct ata_port *ap = adev->link->ap; - void __iomem *ioaddr = ap->ioaddr.data_addr; - int retlen = buflen; - - if (write_data) { - for (; buflen > 0; buflen--, buf++) - writeb(*buf, ioaddr); - } else { - for (; buflen > 0; buflen--, buf++) - *buf = readb(ioaddr); - } - - ata_sff_pause(ap); - return retlen; -} - static void rb532_pata_freeze(struct ata_port *ap) { struct rb532_cf_info *info = ap->host->private_data; @@ -105,7 +86,7 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance) static struct ata_port_operations rb532_pata_port_ops = { .inherits = &ata_sff_port_ops, - .sff_data_xfer = rb532_pata_data_xfer, + .sff_data_xfer = ata_sff_data_xfer32, .freeze = rb532_pata_freeze, .thaw = rb532_pata_thaw, }; -- cgit v1.2.3 From 6be976e79db3ba691b657476a8bf4a635e5586f9 Mon Sep 17 00:00:00 2001 From: Phil Sutter Date: Tue, 27 Jan 2009 14:35:53 +0100 Subject: pata-rb532-cf: drop custom freeze and thaw I'm not quite sure what freezing and thawing is used for. Tests showed that the port is being frozen at initialisation state and thawed right afterwards, then the functions were not called anymore. Dropping the complete custom code for handling the frozen state seems to work at least for a standard use case including mounting a partition, copying some files in it (in parallel) and finally removing them and unmounting the partition. Signed-off-by: Phil Sutter Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 20 +------------------- 1 file changed, 1 insertion(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 9fb91e4dd88..fbfee1bd85f 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -48,26 +48,11 @@ struct rb532_cf_info { void __iomem *iobase; unsigned int gpio_line; - int frozen; unsigned int irq; }; /* ------------------------------------------------------------------------ */ -static void rb532_pata_freeze(struct ata_port *ap) -{ - struct rb532_cf_info *info = ap->host->private_data; - - info->frozen = 1; -} - -static void rb532_pata_thaw(struct ata_port *ap) -{ - struct rb532_cf_info *info = ap->host->private_data; - - info->frozen = 0; -} - static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance) { struct ata_host *ah = dev_instance; @@ -75,8 +60,7 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance) if (gpio_get_value(info->gpio_line)) { set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW); - if (!info->frozen) - ata_sff_interrupt(info->irq, dev_instance); + ata_sff_interrupt(info->irq, dev_instance); } else { set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH); } @@ -87,8 +71,6 @@ static irqreturn_t rb532_pata_irq_handler(int irq, void *dev_instance) static struct ata_port_operations rb532_pata_port_ops = { .inherits = &ata_sff_port_ops, .sff_data_xfer = ata_sff_data_xfer32, - .freeze = rb532_pata_freeze, - .thaw = rb532_pata_thaw, }; /* ------------------------------------------------------------------------ */ -- cgit v1.2.3 From a5bfc4714b3f01365aef89a92673f2ceb1ccf246 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 23 Jan 2009 11:31:39 +0900 Subject: ahci: drop intx manipulation on msi enable There's no need to turn off intx explicitly on msi enable. This is automatically handled by pci. Drop it. This might be needed on machines if the BIOS turns intx off during boot. However, there's no evidence of such behavior for ahci and the only such case seems to be ICH5 PATA according to ata_piix. Also, given the way ahci operates, it's highly unlikely BIOS ever disables IRQ for the controller. However, as this change has slight possibility of introducing failure, please schedule it for #upstream. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 66e012cd327..98d7a9fbb7e 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -2647,8 +2647,8 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; - if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) - pci_intx(pdev, 1); + if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) + pci_enable_msi(pdev); /* save initial config */ ahci_save_initial_config(pdev, hpriv); -- cgit v1.2.3 From 08da175937a35d34a83eaefbb3458472eb1a89d4 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:13:03 -0500 Subject: [libata] sata_mv: cache frequently-accessed registers Maintain a local (mv_port_priv) cache of frequently accessed registers, to avoid having to re-read them (very slow) on every transistion between EDMA and non-EDMA modes. This speeds up things like flushing the drive write cache, and anything using basic DMA transfers. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 91 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 70 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 1f14b1b5234..146b8e67c44 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -438,6 +438,17 @@ struct mv_sg { __le32 reserved; }; +/* + * We keep a local cache of a few frequently accessed port + * registers here, to avoid having to read them (very slow) + * when switching between EDMA and non-EDMA modes. + */ +struct mv_cached_regs { + u32 fiscfg; + u32 ltmode; + u32 haltcond; +}; + struct mv_port_priv { struct mv_crqb *crqb; dma_addr_t crqb_dma; @@ -450,6 +461,7 @@ struct mv_port_priv { unsigned int resp_idx; u32 pp_flags; + struct mv_cached_regs cached; unsigned int delayed_eh_pmp_map; }; @@ -812,6 +824,43 @@ static inline int mv_get_hc_count(unsigned long port_flags) return ((port_flags & MV_FLAG_DUAL_HC) ? 2 : 1); } +/** + * mv_save_cached_regs - (re-)initialize cached port registers + * @ap: the port whose registers we are caching + * + * Initialize the local cache of port registers, + * so that reading them over and over again can + * be avoided on the hotter paths of this driver. + * This saves a few microseconds each time we switch + * to/from EDMA mode to perform (eg.) a drive cache flush. + */ +static void mv_save_cached_regs(struct ata_port *ap) +{ + void __iomem *port_mmio = mv_ap_base(ap); + struct mv_port_priv *pp = ap->private_data; + + pp->cached.fiscfg = readl(port_mmio + FISCFG_OFS); + pp->cached.ltmode = readl(port_mmio + LTMODE_OFS); + pp->cached.haltcond = readl(port_mmio + EDMA_HALTCOND_OFS); +} + +/** + * mv_write_cached_reg - write to a cached port register + * @addr: hardware address of the register + * @old: pointer to cached value of the register + * @new: new value for the register + * + * Write a new value to a cached register, + * but only if the value is different from before. + */ +static inline void mv_write_cached_reg(void __iomem *addr, u32 *old, u32 new) +{ + if (new != *old) { + *old = new; + writel(new, addr); + } +} + static void mv_set_edma_ptrs(void __iomem *port_mmio, struct mv_host_priv *hpriv, struct mv_port_priv *pp) @@ -1159,35 +1208,33 @@ static int mv_qc_defer(struct ata_queued_cmd *qc) return ATA_DEFER_PORT; } -static void mv_config_fbs(void __iomem *port_mmio, int want_ncq, int want_fbs) +static void mv_config_fbs(struct ata_port *ap, int want_ncq, int want_fbs) { - u32 new_fiscfg, old_fiscfg; - u32 new_ltmode, old_ltmode; - u32 new_haltcond, old_haltcond; + struct mv_port_priv *pp = ap->private_data; + void __iomem *port_mmio; - old_fiscfg = readl(port_mmio + FISCFG_OFS); - old_ltmode = readl(port_mmio + LTMODE_OFS); - old_haltcond = readl(port_mmio + EDMA_HALTCOND_OFS); + u32 fiscfg, *old_fiscfg = &pp->cached.fiscfg; + u32 ltmode, *old_ltmode = &pp->cached.ltmode; + u32 haltcond, *old_haltcond = &pp->cached.haltcond; - new_fiscfg = old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR); - new_ltmode = old_ltmode & ~LTMODE_BIT8; - new_haltcond = old_haltcond | EDMA_ERR_DEV; + ltmode = *old_ltmode & ~LTMODE_BIT8; + haltcond = *old_haltcond | EDMA_ERR_DEV; if (want_fbs) { - new_fiscfg = old_fiscfg | FISCFG_SINGLE_SYNC; - new_ltmode = old_ltmode | LTMODE_BIT8; + fiscfg = *old_fiscfg | FISCFG_SINGLE_SYNC; + ltmode = *old_ltmode | LTMODE_BIT8; if (want_ncq) - new_haltcond &= ~EDMA_ERR_DEV; + haltcond &= ~EDMA_ERR_DEV; else - new_fiscfg |= FISCFG_WAIT_DEV_ERR; + fiscfg |= FISCFG_WAIT_DEV_ERR; + } else { + fiscfg = *old_fiscfg & ~(FISCFG_SINGLE_SYNC | FISCFG_WAIT_DEV_ERR); } - if (new_fiscfg != old_fiscfg) - writelfl(new_fiscfg, port_mmio + FISCFG_OFS); - if (new_ltmode != old_ltmode) - writelfl(new_ltmode, port_mmio + LTMODE_OFS); - if (new_haltcond != old_haltcond) - writelfl(new_haltcond, port_mmio + EDMA_HALTCOND_OFS); + port_mmio = mv_ap_base(ap); + mv_write_cached_reg(port_mmio + FISCFG_OFS, old_fiscfg, fiscfg); + mv_write_cached_reg(port_mmio + LTMODE_OFS, old_ltmode, ltmode); + mv_write_cached_reg(port_mmio + EDMA_HALTCOND_OFS, old_haltcond, haltcond); } static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq) @@ -1235,7 +1282,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) */ want_fbs &= want_ncq; - mv_config_fbs(port_mmio, want_ncq, want_fbs); + mv_config_fbs(ap, want_ncq, want_fbs); if (want_fbs) { pp->pp_flags |= MV_PP_FLAG_FBS_EN; @@ -1339,6 +1386,7 @@ static int mv_port_start(struct ata_port *ap) pp->sg_tbl_dma[tag] = pp->sg_tbl_dma[0]; } } + mv_save_cached_regs(ap); mv_edma_cfg(ap, 0, 0); return 0; @@ -2997,6 +3045,7 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class, extra = HZ; /* only extend it once, max */ } } while (sstatus != 0x0 && sstatus != 0x113 && sstatus != 0x123); + mv_save_cached_regs(ap); mv_edma_cfg(ap, 0, 0); return rc; -- cgit v1.2.3 From c01e8a23128c746f23088db836bd4c820f3eb0b4 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:14:48 -0500 Subject: [libata] sata_mv: Enable use of (basic) DMA for ATAPI on GEN_IIE chips This also gets rid of any need for mv_mode_filter(). Using basic DMA on GEN_IIE requires setting an undocumented bit in an undocumented register. For safety, we clear that bit again when switching back to EDMA mode. To avoid a performance penalty when switching modes, we cache the register in port_priv, as already done for other regs. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 52 +++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 146b8e67c44..3bfe721ba76 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -345,7 +345,7 @@ enum { EDMA_ARB_CFG_OFS = 0x38, EDMA_HALTCOND_OFS = 0x60, /* GenIIe halt conditions */ - + EDMA_UNKNOWN_RSVD_OFS = 0x6C, /* GenIIe unknown/reserved */ BMDMA_CMD_OFS = 0x224, /* bmdma command register */ BMDMA_STATUS_OFS = 0x228, /* bmdma status register */ @@ -447,6 +447,7 @@ struct mv_cached_regs { u32 fiscfg; u32 ltmode; u32 haltcond; + u32 unknown_rsvd; }; struct mv_port_priv { @@ -563,8 +564,6 @@ static void mv_pmp_error_handler(struct ata_port *ap); static void mv_process_crpb_entries(struct ata_port *ap, struct mv_port_priv *pp); -static unsigned long mv_mode_filter(struct ata_device *dev, - unsigned long xfer_mask); static void mv_sff_irq_clear(struct ata_port *ap); static int mv_check_atapi_dma(struct ata_queued_cmd *qc); static void mv_bmdma_setup(struct ata_queued_cmd *qc); @@ -626,7 +625,6 @@ static struct ata_port_operations mv6_ops = { .bmdma_start = mv_bmdma_start, .bmdma_stop = mv_bmdma_stop, .bmdma_status = mv_bmdma_status, - .mode_filter = mv_mode_filter, }; static struct ata_port_operations mv_iie_ops = { @@ -842,6 +840,7 @@ static void mv_save_cached_regs(struct ata_port *ap) pp->cached.fiscfg = readl(port_mmio + FISCFG_OFS); pp->cached.ltmode = readl(port_mmio + LTMODE_OFS); pp->cached.haltcond = readl(port_mmio + EDMA_HALTCOND_OFS); + pp->cached.unknown_rsvd = readl(port_mmio + EDMA_UNKNOWN_RSVD_OFS); } /** @@ -1252,6 +1251,30 @@ static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq) writel(new, hpriv->base + MV_GPIO_PORT_CTL_OFS); } +/** + * mv_bmdma_enable - set a magic bit on GEN_IIE to allow bmdma + * @ap: Port being initialized + * + * There are two DMA modes on these chips: basic DMA, and EDMA. + * + * Bit-0 of the "EDMA RESERVED" register enables/disables use + * of basic DMA on the GEN_IIE versions of the chips. + * + * This bit survives EDMA resets, and must be set for basic DMA + * to function, and should be cleared when EDMA is active. + */ +static void mv_bmdma_enable_iie(struct ata_port *ap, int enable_bmdma) +{ + struct mv_port_priv *pp = ap->private_data; + u32 new, *old = &pp->cached.unknown_rsvd; + + if (enable_bmdma) + new = *old | 1; + else + new = *old & ~1; + mv_write_cached_reg(mv_ap_base(ap) + EDMA_UNKNOWN_RSVD_OFS, old, new); +} + static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) { u32 cfg; @@ -1297,6 +1320,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) } if (hpriv->hp_flags & MV_HP_CUT_THROUGH) cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ + mv_bmdma_enable_iie(ap, !want_edma); } if (want_ncq) { @@ -1464,26 +1488,6 @@ static void mv_crqb_pack_cmd(__le16 *cmdw, u8 data, u8 addr, unsigned last) *cmdw = cpu_to_le16(tmp); } -/** - * mv_mode_filter - Allow ATAPI DMA only on GenII chips. - * @dev: device whose xfer modes are being configured. - * - * Only the GenII hardware can use DMA with ATAPI drives. - */ -static unsigned long mv_mode_filter(struct ata_device *adev, - unsigned long xfer_mask) -{ - if (adev->class == ATA_DEV_ATAPI) { - struct mv_host_priv *hpriv = adev->link->ap->host->private_data; - if (!IS_GEN_II(hpriv)) { - xfer_mask &= ~(ATA_MASK_MWDMA | ATA_MASK_UDMA); - ata_dev_printk(adev, KERN_INFO, - "ATAPI DMA not supported on this chipset\n"); - } - } - return xfer_mask; -} - /** * mv_sff_irq_clear - Clear hardware interrupt after DMA. * @ap: Port associated with this ATA transaction. -- cgit v1.2.3 From 42ed893d8011264f9945c2f54055b47c298ac53e Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:15:39 -0500 Subject: [libata] sata_mv: Tighten up interrupt masking in mv_qc_issue() so that it doesn't miss any protocols. Handle future cases where a qc is specially marked for polled issue or where a particular chip version prefers interrupts over polling for PIO. This mimics the polling decision logic from ata_sff_qc_issue(). Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 3bfe721ba76..b74af945a2f 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1809,7 +1809,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) void __iomem *port_mmio = mv_ap_base(ap); struct mv_port_priv *pp = ap->private_data; u32 in_index; - unsigned int port_irqs = DONE_IRQ | ERR_IRQ; + unsigned int port_irqs; switch (qc->tf.protocol) { case ATA_PROT_DMA: @@ -1842,20 +1842,28 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) "this may fail due to h/w errata\n"); } /* drop through */ + case ATA_PROT_NODATA: case ATAPI_PROT_PIO: - port_irqs = ERR_IRQ; /* leave DONE_IRQ masked for PIO */ - /* drop through */ - default: - /* - * We're about to send a non-EDMA capable command to the - * port. Turn off EDMA so there won't be problems accessing - * shadow block, etc registers. - */ - mv_stop_edma(ap); - mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); - mv_pmp_select(ap, qc->dev->link->pmp); - return ata_sff_qc_issue(qc); + case ATAPI_PROT_NODATA: + if (ap->flags & ATA_FLAG_PIO_POLLING) + qc->tf.flags |= ATA_TFLAG_POLLING; + break; } + + if (qc->tf.flags & ATA_TFLAG_POLLING) + port_irqs = ERR_IRQ; /* mask device interrupt when polling */ + else + port_irqs = ERR_IRQ | DONE_IRQ; /* unmask all interrupts */ + + /* + * We're about to send a non-EDMA capable command to the + * port. Turn off EDMA so there won't be problems accessing + * shadow block, etc registers. + */ + mv_stop_edma(ap); + mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); + mv_pmp_select(ap, qc->dev->link->pmp); + return ata_sff_qc_issue(qc); } static struct ata_queued_cmd *mv_get_active_qc(struct ata_port *ap) -- cgit v1.2.3 From d16ab3f633b75aac1cf42b00355cd9aa65033dcc Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:17:43 -0500 Subject: [libata] sata_mv: Add a new mv_sff_check_status() function to sata_mv. This is necessary for use with the upcoming "mv_qc_issue_fis()" patch, but is being added separately here for easier code review. When using command issue via the "mv_qc_issue_fis()" mechanism, the initial ATA_BUSY bit does not show in the ATA status (shadow) register. This can confuse libata! So here we add a hook to fake ATA_BUSY for that situation, until the first time a BUSY, DRQ, or ERR bit is seen. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index b74af945a2f..542e244f37a 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -370,6 +370,7 @@ enum { MV_PP_FLAG_NCQ_EN = (1 << 1), /* is EDMA set up for NCQ? */ MV_PP_FLAG_FBS_EN = (1 << 2), /* is EDMA set up for FBS? */ MV_PP_FLAG_DELAYED_EH = (1 << 3), /* delayed dev err handling */ + MV_PP_FLAG_FAKE_ATA_BUSY = (1 << 4), /* ignore initial ATA_DRDY */ }; #define IS_GEN_I(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_I) @@ -570,6 +571,7 @@ static void mv_bmdma_setup(struct ata_queued_cmd *qc); static void mv_bmdma_start(struct ata_queued_cmd *qc); static void mv_bmdma_stop(struct ata_queued_cmd *qc); static u8 mv_bmdma_status(struct ata_port *ap); +static u8 mv_sff_check_status(struct ata_port *ap); /* .sg_tablesize is (MV_MAX_SG_CT / 2) in the structures below * because we have to allow room for worst case splitting of @@ -619,6 +621,7 @@ static struct ata_port_operations mv6_ops = { .softreset = mv_softreset, .error_handler = mv_pmp_error_handler, + .sff_check_status = mv_sff_check_status, .sff_irq_clear = mv_sff_irq_clear, .check_atapi_dma = mv_check_atapi_dma, .bmdma_setup = mv_bmdma_setup, @@ -1284,7 +1287,8 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) /* set up non-NCQ EDMA configuration */ cfg = EDMA_CFG_Q_DEPTH; /* always 0x1f for *all* chips */ - pp->pp_flags &= ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN); + pp->pp_flags &= + ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN | MV_PP_FLAG_FAKE_ATA_BUSY); if (IS_GEN_I(hpriv)) cfg |= (1 << 8); /* enab config burst size mask */ @@ -1790,6 +1794,33 @@ static void mv_qc_prep_iie(struct ata_queued_cmd *qc) mv_fill_sg(qc); } +/** + * mv_sff_check_status - fetch device status, if valid + * @ap: ATA port to fetch status from + * + * When using command issue via mv_qc_issue_fis(), + * the initial ATA_BUSY state does not show up in the + * ATA status (shadow) register. This can confuse libata! + * + * So we have a hook here to fake ATA_BUSY for that situation, + * until the first time a BUSY, DRQ, or ERR bit is seen. + * + * The rest of the time, it simply returns the ATA status register. + */ +static u8 mv_sff_check_status(struct ata_port *ap) +{ + u8 stat = ioread8(ap->ioaddr.status_addr); + struct mv_port_priv *pp = ap->private_data; + + if (pp->pp_flags & MV_PP_FLAG_FAKE_ATA_BUSY) { + if (stat & (ATA_BUSY | ATA_DRQ | ATA_ERR)) + pp->pp_flags &= ~MV_PP_FLAG_FAKE_ATA_BUSY; + else + stat = ATA_BUSY; + } + return stat; +} + /** * mv_qc_issue - Initiate a command to the host * @qc: queued command to start @@ -1811,6 +1842,8 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) u32 in_index; unsigned int port_irqs; + pp->pp_flags &= ~MV_PP_FLAG_FAKE_ATA_BUSY; /* paranoia */ + switch (qc->tf.protocol) { case ATA_PROT_DMA: case ATA_PROT_NCQ: @@ -3038,6 +3071,8 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class, mv_reset_channel(hpriv, mmio, ap->port_no); pp->pp_flags &= ~MV_PP_FLAG_EDMA_EN; + pp->pp_flags &= + ~(MV_PP_FLAG_FBS_EN | MV_PP_FLAG_NCQ_EN | MV_PP_FLAG_FAKE_ATA_BUSY); /* Workaround for errata FEr SATA#10 (part 2) */ do { -- cgit v1.2.3 From 1a660164c291f41b2aa853a7269b310933574ef9 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:18:32 -0500 Subject: [libata] Export ata_pio_queue_task() so that it can be used from sata_mv. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 1 + drivers/ata/libata.h | 2 -- 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 060bcd601f5..d4a7b8a96ec 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -6709,6 +6709,7 @@ EXPORT_SYMBOL_GPL(ata_id_c_string); EXPORT_SYMBOL_GPL(ata_do_dev_read_id); EXPORT_SYMBOL_GPL(ata_scsi_simulate); +EXPORT_SYMBOL_GPL(ata_pio_queue_task); EXPORT_SYMBOL_GPL(ata_pio_need_iordy); EXPORT_SYMBOL_GPL(ata_timing_find_mode); EXPORT_SYMBOL_GPL(ata_timing_compute); diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index cea8014cd87..89a1e0018e7 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h @@ -79,8 +79,6 @@ extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, u64 block, u32 n_block, unsigned int tf_flags, unsigned int tag); extern u64 ata_tf_read_block(struct ata_taskfile *tf, struct ata_device *dev); -extern void ata_pio_queue_task(struct ata_port *ap, void *data, - unsigned long delay); extern void ata_port_flush_task(struct ata_port *ap); extern unsigned ata_exec_internal(struct ata_device *dev, struct ata_taskfile *tf, const u8 *cdb, -- cgit v1.2.3 From 70f8b79cf3a2eb892a01271fdfbb1903c0c982a8 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 25 Feb 2009 15:19:20 -0500 Subject: [libata] sata_mv: Implement direct FIS transmission via mv_qc_issue_fis(). This is initially needed to work around NCQ errata, whereby the READ_LOG_EXT command sometimes fails when issued in the traditional (sff) fashion. Portions of this code will likely be reused for implementation of the target mode feature later on. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 542e244f37a..8cad3b2fe55 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1821,6 +1821,105 @@ static u8 mv_sff_check_status(struct ata_port *ap) return stat; } +/** + * mv_send_fis - Send a FIS, using the "Vendor-Unique FIS" register + * @fis: fis to be sent + * @nwords: number of 32-bit words in the fis + */ +static unsigned int mv_send_fis(struct ata_port *ap, u32 *fis, int nwords) +{ + void __iomem *port_mmio = mv_ap_base(ap); + u32 ifctl, old_ifctl, ifstat; + int i, timeout = 200, final_word = nwords - 1; + + /* Initiate FIS transmission mode */ + old_ifctl = readl(port_mmio + SATA_IFCTL_OFS); + ifctl = 0x100 | (old_ifctl & 0xf); + writelfl(ifctl, port_mmio + SATA_IFCTL_OFS); + + /* Send all words of the FIS except for the final word */ + for (i = 0; i < final_word; ++i) + writel(fis[i], port_mmio + VENDOR_UNIQUE_FIS_OFS); + + /* Flag end-of-transmission, and then send the final word */ + writelfl(ifctl | 0x200, port_mmio + SATA_IFCTL_OFS); + writelfl(fis[final_word], port_mmio + VENDOR_UNIQUE_FIS_OFS); + + /* + * Wait for FIS transmission to complete. + * This typically takes just a single iteration. + */ + do { + ifstat = readl(port_mmio + SATA_IFSTAT_OFS); + } while (!(ifstat & 0x1000) && --timeout); + + /* Restore original port configuration */ + writelfl(old_ifctl, port_mmio + SATA_IFCTL_OFS); + + /* See if it worked */ + if ((ifstat & 0x3000) != 0x1000) { + ata_port_printk(ap, KERN_WARNING, + "%s transmission error, ifstat=%08x\n", + __func__, ifstat); + return AC_ERR_OTHER; + } + return 0; +} + +/** + * mv_qc_issue_fis - Issue a command directly as a FIS + * @qc: queued command to start + * + * Note that the ATA shadow registers are not updated + * after command issue, so the device will appear "READY" + * if polled, even while it is BUSY processing the command. + * + * So we use a status hook to fake ATA_BUSY until the drive changes state. + * + * Note: we don't get updated shadow regs on *completion* + * of non-data commands. So avoid sending them via this function, + * as they will appear to have completed immediately. + * + * GEN_IIE has special registers that we could get the result tf from, + * but earlier chipsets do not. For now, we ignore those registers. + */ +static unsigned int mv_qc_issue_fis(struct ata_queued_cmd *qc) +{ + struct ata_port *ap = qc->ap; + struct mv_port_priv *pp = ap->private_data; + struct ata_link *link = qc->dev->link; + u32 fis[5]; + int err = 0; + + ata_tf_to_fis(&qc->tf, link->pmp, 1, (void *)fis); + err = mv_send_fis(ap, fis, sizeof(fis) / sizeof(fis[0])); + if (err) + return err; + + switch (qc->tf.protocol) { + case ATAPI_PROT_PIO: + pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY; + /* fall through */ + case ATAPI_PROT_NODATA: + ap->hsm_task_state = HSM_ST_FIRST; + break; + case ATA_PROT_PIO: + pp->pp_flags |= MV_PP_FLAG_FAKE_ATA_BUSY; + if (qc->tf.flags & ATA_TFLAG_WRITE) + ap->hsm_task_state = HSM_ST_FIRST; + else + ap->hsm_task_state = HSM_ST; + break; + default: + ap->hsm_task_state = HSM_ST_LAST; + break; + } + + if (qc->tf.flags & ATA_TFLAG_POLLING) + ata_pio_queue_task(ap, qc, 0); + return 0; +} + /** * mv_qc_issue - Initiate a command to the host * @qc: queued command to start @@ -1896,6 +1995,23 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) mv_stop_edma(ap); mv_clear_and_enable_port_irqs(ap, mv_ap_base(ap), port_irqs); mv_pmp_select(ap, qc->dev->link->pmp); + + if (qc->tf.command == ATA_CMD_READ_LOG_EXT) { + struct mv_host_priv *hpriv = ap->host->private_data; + /* + * Workaround for 88SX60x1 FEr SATA#25 (part 2). + * + * After any NCQ error, the READ_LOG_EXT command + * from libata-eh *must* use mv_qc_issue_fis(). + * Otherwise it might fail, due to chip errata. + * + * Rather than special-case it, we'll just *always* + * use this method here for READ_LOG_EXT, making for + * easier testing. + */ + if (IS_GEN_II(hpriv)) + return mv_qc_issue_fis(qc); + } return ata_sff_qc_issue(qc); } -- cgit v1.2.3 From d2f9c0614e664708978c53eca4a5963e92830e88 Mon Sep 17 00:00:00 2001 From: Maciej Rutecki Date: Fri, 20 Mar 2009 00:06:46 +0100 Subject: ahci: Blacklist HP Compaq 6720s that spins off disks during ACPI power off Blacklist HP Compaq 6720s so that it doesn't play a "spin down, spin up, spin down" ping-pong with the hard disk during system power off. Signed-off-by: Maciej Rutecki Signed-off-by: Rafael J. Wysocki Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 98d7a9fbb7e..699789bc9ea 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -2565,6 +2565,15 @@ static bool ahci_broken_system_poweroff(struct pci_dev *pdev) /* PCI slot number of the controller */ .driver_data = (void *)0x1FUL, }, + { + .ident = "HP Compaq 6720s", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), + DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq 6720s"), + }, + /* PCI slot number of the controller */ + .driver_data = (void *)0x1FUL, + }, { } /* terminate list */ }; -- cgit v1.2.3 From 14bdef982caeda19afe34010482867c18217c641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Inge=20Bols=C3=B8?= Date: Sat, 14 Mar 2009 21:38:24 +0100 Subject: [libata] convert drivers to use ata.h mode mask defines MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No functional changes in this patch. Signed-off-by: Erik Inge Bolsø Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 16 +++++----- drivers/ata/ata_generic.c | 4 +-- drivers/ata/ata_piix.c | 60 +++++++++++++++++------------------ drivers/ata/pata_acpi.c | 6 ++-- drivers/ata/pata_ali.c | 28 ++++++++--------- drivers/ata/pata_amd.c | 70 ++++++++++++++++++++--------------------- drivers/ata/pata_artop.c | 16 +++++----- drivers/ata/pata_at32.c | 4 ++- drivers/ata/pata_atiixp.c | 6 ++-- drivers/ata/pata_bf54x.c | 2 +- drivers/ata/pata_cmd640.c | 2 +- drivers/ata/pata_cmd64x.c | 24 +++++++------- drivers/ata/pata_cs5520.c | 2 +- drivers/ata/pata_cs5530.c | 8 ++--- drivers/ata/pata_cs5535.c | 4 +-- drivers/ata/pata_cs5536.c | 4 +-- drivers/ata/pata_cypress.c | 4 +-- drivers/ata/pata_efar.c | 6 ++-- drivers/ata/pata_hpt366.c | 4 +-- drivers/ata/pata_hpt37x.c | 28 ++++++++--------- drivers/ata/pata_hpt3x2n.c | 4 +-- drivers/ata/pata_hpt3x3.c | 6 ++-- drivers/ata/pata_icside.c | 4 +-- drivers/ata/pata_isapnp.c | 2 +- drivers/ata/pata_it8213.c | 4 +-- drivers/ata/pata_it821x.c | 16 +++++----- drivers/ata/pata_ixp4xx_cf.c | 2 +- drivers/ata/pata_jmicron.c | 4 +-- drivers/ata/pata_legacy.c | 2 +- drivers/ata/pata_marvell.c | 8 ++--- drivers/ata/pata_mpc52xx.c | 4 +-- drivers/ata/pata_mpiix.c | 2 +- drivers/ata/pata_netcell.c | 4 +-- drivers/ata/pata_ninja32.c | 2 +- drivers/ata/pata_ns87410.c | 2 +- drivers/ata/pata_ns87415.c | 8 ++--- drivers/ata/pata_octeon_cf.c | 4 +-- drivers/ata/pata_oldpiix.c | 4 +-- drivers/ata/pata_opti.c | 2 +- drivers/ata/pata_optidma.c | 10 +++--- drivers/ata/pata_pcmcia.c | 2 +- drivers/ata/pata_pdc2027x.c | 12 +++---- drivers/ata/pata_pdc202xx_old.c | 12 +++---- drivers/ata/pata_qdi.c | 4 +-- drivers/ata/pata_radisys.c | 6 ++-- drivers/ata/pata_rb532_cf.c | 2 +- drivers/ata/pata_rz1000.c | 2 +- drivers/ata/pata_sc1200.c | 6 ++-- drivers/ata/pata_scc.c | 4 +-- drivers/ata/pata_sch.c | 6 ++-- drivers/ata/pata_serverworks.c | 20 ++++++------ drivers/ata/pata_sil680.c | 8 ++--- drivers/ata/pata_sis.c | 32 +++++++++++-------- drivers/ata/pata_sl82c105.c | 6 ++-- drivers/ata/pata_triflex.c | 4 +-- drivers/ata/pata_via.c | 24 +++++++------- drivers/ata/pata_winbond.c | 2 +- drivers/ata/pdc_adma.c | 2 +- drivers/ata/sata_fsl.c | 4 +-- drivers/ata/sata_inic162x.c | 4 +-- drivers/ata/sata_nv.c | 6 ++-- drivers/ata/sata_promise.c | 28 ++++++++--------- drivers/ata/sata_qstor.c | 2 +- drivers/ata/sata_sil.c | 16 +++++----- drivers/ata/sata_sil24.c | 18 +++++------ drivers/ata/sata_sis.c | 4 +-- drivers/ata/sata_svw.c | 16 +++++----- drivers/ata/sata_sx4.c | 4 +-- drivers/ata/sata_uli.c | 2 +- drivers/ata/sata_via.c | 16 +++++----- drivers/ata/sata_vsc.c | 4 +-- 71 files changed, 339 insertions(+), 331 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 699789bc9ea..ec2922ad2dc 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -404,7 +404,7 @@ static const struct ata_port_info ahci_port_info[] = { /* board_ahci */ { .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, @@ -412,7 +412,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_vt8251_ops, }, @@ -420,7 +420,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, @@ -430,7 +430,7 @@ static const struct ata_port_info ahci_port_info[] = { AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_sb600_ops, }, @@ -440,7 +440,7 @@ static const struct ata_port_info ahci_port_info[] = { AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, @@ -448,7 +448,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_sb600_ops, }, @@ -456,7 +456,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, @@ -464,7 +464,7 @@ static const struct ata_port_info ahci_port_info[] = { { AHCI_HFLAGS (AHCI_HFLAG_NO_PMP), .flags = AHCI_FLAG_COMMON, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &ahci_ops, }, diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c index dc48a6398ab..ecfd22b4f1c 100644 --- a/drivers/ata/ata_generic.c +++ b/drivers/ata/ata_generic.c @@ -118,8 +118,8 @@ static int ata_generic_init_one(struct pci_dev *dev, const struct pci_device_id u16 command; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &generic_port_ops }; diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index ef8b30d577b..e5cbe80ce17 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -446,34 +446,34 @@ static struct ata_port_info piix_port_info[] = { [piix_pata_mwdma] = /* PIIX3 MWDMA only */ { .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ .port_ops = &piix_pata_ops, }, [piix_pata_33] = /* PIIX4 at 33MHz */ { .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ - .udma_mask = ATA_UDMA_MASK_40C, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .udma_mask = ATA_UDMA2, .port_ops = &piix_pata_ops, }, [ich_pata_33] = /* ICH0 - ICH at 33Mhz*/ { .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio 0-4 */ - .mwdma_mask = 0x06, /* Check: maybe 0x07 */ - .udma_mask = ATA_UDMA2, /* UDMA33 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* Check: maybe MWDMA0 is ok */ + .udma_mask = ATA_UDMA2, .port_ops = &ich_pata_ops, }, [ich_pata_66] = /* ICH controllers up to 66MHz */ { .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio 0-4 */ - .mwdma_mask = 0x06, /* MWDMA0 is broken on chip */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* MWDMA0 is broken on chip */ .udma_mask = ATA_UDMA4, .port_ops = &ich_pata_ops, }, @@ -481,17 +481,17 @@ static struct ata_port_info piix_port_info[] = { [ich_pata_100] = { .flags = PIIX_PATA_FLAGS | PIIX_FLAG_CHECKINTR, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, + .udma_mask = ATA_UDMA5, .port_ops = &ich_pata_ops, }, [ich5_sata] = { .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -499,8 +499,8 @@ static struct ata_port_info piix_port_info[] = { [ich6_sata] = { .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -508,8 +508,8 @@ static struct ata_port_info piix_port_info[] = { [ich6m_sata] = { .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -517,8 +517,8 @@ static struct ata_port_info piix_port_info[] = { [ich8_sata] = { .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -526,8 +526,8 @@ static struct ata_port_info piix_port_info[] = { [ich8_2port_sata] = { .flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -535,8 +535,8 @@ static struct ata_port_info piix_port_info[] = { [tolapai_sata] = { .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -544,8 +544,8 @@ static struct ata_port_info piix_port_info[] = { [ich8m_apple_sata] = { .flags = PIIX_SATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &piix_sata_ops, }, @@ -553,9 +553,9 @@ static struct ata_port_info piix_port_info[] = { [piix_pata_vmw] = { .flags = PIIX_PATA_FLAGS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x06, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ - .udma_mask = ATA_UDMA_MASK_40C, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, /* mwdma1-2 ?? CHECK 0 should be ok but slow */ + .udma_mask = ATA_UDMA2, .port_ops = &piix_vmw_ops, }, diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index 8b77a9802df..d8f35fe4442 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -246,9 +246,9 @@ static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id) static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x7f, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, .port_ops = &pacpi_ops, }; diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index eb99dbe7808..751b7ea4816 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c @@ -492,53 +492,53 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info_early = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &ali_early_port_ops }; /* Revision 0x20 added DMA */ static const struct ata_port_info info_20 = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &ali_20_port_ops }; /* Revision 0x20 with support logic added UDMA */ static const struct ata_port_info info_20_udma = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, /* UDMA33 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &ali_20_port_ops }; /* Revision 0xC2 adds UDMA66 */ static const struct ata_port_info info_c2 = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &ali_c2_port_ops }; /* Revision 0xC3 is UDMA66 for now */ static const struct ata_port_info info_c3 = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &ali_c2_port_ops }; /* Revision 0xC4 is UDMA100 */ static const struct ata_port_info info_c4 = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &ali_c4_port_ops }; /* Revision 0xC5 is UDMA133 with LBA48 DMA */ static const struct ata_port_info info_c5 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &ali_c5_port_ops }; diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c index 115b1cd6dcf..33a74f11171 100644 --- a/drivers/ata/pata_amd.c +++ b/drivers/ata/pata_amd.c @@ -455,74 +455,74 @@ static void amd_clear_fifo(struct pci_dev *pdev) static int amd_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info[10] = { - { /* 0: AMD 7401 */ + { /* 0: AMD 7401 - no swdma */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, /* No SWDMA */ - .udma_mask = 0x07, /* UDMA 33 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &amd33_port_ops }, { /* 1: Early AMD7409 - no swdma */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, /* UDMA 66 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA4, .port_ops = &amd66_port_ops }, - { /* 2: AMD 7409, no swdma errata */ + { /* 2: AMD 7409 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA4, /* UDMA 66 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA4, .port_ops = &amd66_port_ops }, { /* 3: AMD 7411 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &amd100_port_ops }, { /* 4: AMD 7441 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &amd100_port_ops }, - { /* 5: AMD 8111*/ + { /* 5: AMD 8111 - no swdma */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, .port_ops = &amd133_port_ops }, - { /* 6: AMD 8111 UDMA 100 (Serenade) */ + { /* 6: AMD 8111 UDMA 100 (Serenade) - no swdma */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100, no swdma */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &amd133_port_ops }, { /* 7: Nvidia Nforce */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &nv100_port_ops }, - { /* 8: Nvidia Nforce2 and later */ + { /* 8: Nvidia Nforce2 and later - no swdma */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA6, /* UDMA 133, no swdma */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, .port_ops = &nv133_port_ops }, { /* 9: AMD CS5536 (Geode companion) */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA5, /* UDMA 100 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &amd100_port_ops } }; diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 6b3092c75ff..07c7fae6da1 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c @@ -323,29 +323,29 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) static int printed_version; static const struct ata_port_info info_6210 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, .port_ops = &artop6210_ops, }; static const struct ata_port_info info_626x = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &artop6260_ops, }; static const struct ata_port_info info_628x = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &artop6260_ops, }; static const struct ata_port_info info_628x_fast = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &artop6260_ops, }; diff --git a/drivers/ata/pata_at32.c b/drivers/ata/pata_at32.c index ab61095093b..5c129f99a7e 100644 --- a/drivers/ata/pata_at32.c +++ b/drivers/ata/pata_at32.c @@ -67,7 +67,9 @@ * * Alter PIO_MASK below according to table to set maximal PIO mode. */ -#define PIO_MASK (0x1f) +enum { + PIO_MASK = ATA_PIO4, +}; /* * Struct containing private information about device. diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index 506adde8ebb..bec0b8ade66 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -220,9 +220,9 @@ static int atiixp_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x06, /* No MWDMA0 support */ - .udma_mask = 0x3F, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA12_ONLY, + .udma_mask = ATA_UDMA5, .port_ops = &atiixp_port_ops }; static const struct pci_bits atiixp_enable_bits[] = { diff --git a/drivers/ata/pata_bf54x.c b/drivers/ata/pata_bf54x.c index 1050fed96b2..c4b47a3e544 100644 --- a/drivers/ata/pata_bf54x.c +++ b/drivers/ata/pata_bf54x.c @@ -1502,7 +1502,7 @@ static struct ata_port_info bfin_port_info[] = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .mwdma_mask = 0, .udma_mask = 0, .port_ops = &bfin_pata_ops, diff --git a/drivers/ata/pata_cmd640.c b/drivers/ata/pata_cmd640.c index 34a394264c3..5acf9fa9b39 100644 --- a/drivers/ata/pata_cmd640.c +++ b/drivers/ata/pata_cmd640.c @@ -211,7 +211,7 @@ static int cmd640_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &cmd640_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_cmd64x.c b/drivers/ata/pata_cmd64x.c index 3167d8fed2f..f98dffedf4b 100644 --- a/drivers/ata/pata_cmd64x.c +++ b/drivers/ata/pata_cmd64x.c @@ -299,40 +299,40 @@ static int cmd64x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static const struct ata_port_info cmd_info[6] = { { /* CMD 643 - no UDMA */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &cmd64x_port_ops }, { /* CMD 646 with broken UDMA */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &cmd64x_port_ops }, { /* CMD 646 with working UDMA */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, .port_ops = &cmd64x_port_ops }, { /* CMD 646 rev 1 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &cmd646r1_port_ops }, { /* CMD 648 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &cmd648_port_ops }, { /* CMD 649 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &cmd648_port_ops } diff --git a/drivers/ata/pata_cs5520.c b/drivers/ata/pata_cs5520.c index 1186bcd2781..db6a96984f3 100644 --- a/drivers/ata/pata_cs5520.c +++ b/drivers/ata/pata_cs5520.c @@ -158,7 +158,7 @@ static int __devinit cs5520_init_one(struct pci_dev *pdev, const struct pci_devi static const unsigned int ctl_port[] = { 0x3F6, 0x376 }; struct ata_port_info pi = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &cs5520_port_ops, }; const struct ata_port_info *ppi[2]; diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index bba453381f4..c974b05e412 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -298,15 +298,15 @@ static int cs5530_init_one(struct pci_dev *pdev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &cs5530_port_ops }; /* The docking connector doesn't do UDMA, and it seems not MWDMA */ static const struct ata_port_info info_palmax_secondary = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &cs5530_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_cs5535.c b/drivers/ata/pata_cs5535.c index 8b236af84c2..d33aa28239a 100644 --- a/drivers/ata/pata_cs5535.c +++ b/drivers/ata/pata_cs5535.c @@ -181,8 +181,8 @@ static int cs5535_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &cs5535_port_ops }; diff --git a/drivers/ata/pata_cs5536.c b/drivers/ata/pata_cs5536.c index afed9297619..6da4cb486c8 100644 --- a/drivers/ata/pata_cs5536.c +++ b/drivers/ata/pata_cs5536.c @@ -241,8 +241,8 @@ static int cs5536_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &cs5536_port_ops, }; diff --git a/drivers/ata/pata_cypress.c b/drivers/ata/pata_cypress.c index d546425cd38..8fb040bf736 100644 --- a/drivers/ata/pata_cypress.c +++ b/drivers/ata/pata_cypress.c @@ -124,8 +124,8 @@ static int cy82c693_init_one(struct pci_dev *pdev, const struct pci_device_id *i { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &cy82c693_port_ops }; const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index ac6392ea35b..bd498cc3920 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c @@ -251,9 +251,9 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma1-2 */ - .udma_mask = 0x0f, /* UDMA 66 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, /* mwdma1-2 */ + .udma_mask = ATA_UDMA3, /* UDMA 66 */ .port_ops = &efar_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_hpt366.c b/drivers/ata/pata_hpt366.c index 65c28e5a6cd..d7f2da127d1 100644 --- a/drivers/ata/pata_hpt366.c +++ b/drivers/ata/pata_hpt366.c @@ -336,8 +336,8 @@ static int hpt36x_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info_hpt366 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &hpt366_port_ops }; diff --git a/drivers/ata/pata_hpt37x.c b/drivers/ata/pata_hpt37x.c index 42163998de9..81ab57003ab 100644 --- a/drivers/ata/pata_hpt37x.c +++ b/drivers/ata/pata_hpt37x.c @@ -753,55 +753,55 @@ static int hpt37x_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* HPT370 - UDMA100 */ static const struct ata_port_info info_hpt370 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt370_port_ops }; /* HPT370A - UDMA100 */ static const struct ata_port_info info_hpt370a = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt370a_port_ops }; /* HPT370 - UDMA100 */ static const struct ata_port_info info_hpt370_33 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt370_port_ops }; /* HPT370A - UDMA100 */ static const struct ata_port_info info_hpt370a_33 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt370a_port_ops }; /* HPT371, 372 and friends - UDMA133 */ static const struct ata_port_info info_hpt372 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &hpt372_port_ops }; /* HPT374 - UDMA100, function 1 uses different prereset method */ static const struct ata_port_info info_hpt374_fn0 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt372_port_ops }; static const struct ata_port_info info_hpt374_fn1 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &hpt374_fn1_port_ops }; diff --git a/drivers/ata/pata_hpt3x2n.c b/drivers/ata/pata_hpt3x2n.c index d5c9fd7b82b..3d59fe0a408 100644 --- a/drivers/ata/pata_hpt3x2n.c +++ b/drivers/ata/pata_hpt3x2n.c @@ -441,8 +441,8 @@ static int hpt3x2n_init_one(struct pci_dev *dev, const struct pci_device_id *id) /* HPT372N and friends - UDMA133 */ static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &hpt3x2n_port_ops }; diff --git a/drivers/ata/pata_hpt3x3.c b/drivers/ata/pata_hpt3x3.c index f19cc645881..7e310253b36 100644 --- a/drivers/ata/pata_hpt3x3.c +++ b/drivers/ata/pata_hpt3x3.c @@ -188,11 +188,11 @@ static int hpt3x3_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, #if defined(CONFIG_PATA_HPT3X3_DMA) /* Further debug needed */ - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, #endif .port_ops = &hpt3x3_port_ops }; diff --git a/drivers/ata/pata_icside.c b/drivers/ata/pata_icside.c index cf9e9848f8b..e7347db5b6c 100644 --- a/drivers/ata/pata_icside.c +++ b/drivers/ata/pata_icside.c @@ -297,7 +297,7 @@ static int icside_dma_init(struct pata_icside_info *info) if (ec->dma != NO_DMA && !request_dma(ec->dma, DRV_NAME)) { state->dma = ec->dma; - info->mwdma_mask = 0x07; /* MW0..2 */ + info->mwdma_mask = ATA_MWDMA2; } return 0; @@ -473,7 +473,7 @@ static int __devinit pata_icside_add_ports(struct pata_icside_info *info) for (i = 0; i < info->nr_ports; i++) { struct ata_port *ap = host->ports[i]; - ap->pio_mask = 0x1f; + ap->pio_mask = ATA_PIO4; ap->mwdma_mask = info->mwdma_mask; ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ops = &pata_icside_port_ops; diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index 15cdb9148aa..afa8f704271 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -66,7 +66,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev ap = host->ports[0]; ap->ops = &isapnp_port_ops; - ap->pio_mask = 1; + ap->pio_mask = ATA_PIO0; ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ioaddr.cmd_addr = cmd_addr; diff --git a/drivers/ata/pata_it8213.c b/drivers/ata/pata_it8213.c index c113d7c079c..f156da8076f 100644 --- a/drivers/ata/pata_it8213.c +++ b/drivers/ata/pata_it8213.c @@ -262,8 +262,8 @@ static int it8213_init_one (struct pci_dev *pdev, const struct pci_device_id *en static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, /* FIXME: want UDMA 100? */ .port_ops = &it8213_ops, }; diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index b05b86a912c..188bc2fcd22 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -875,29 +875,29 @@ static int it821x_init_one(struct pci_dev *pdev, const struct pci_device_id *id) static const struct ata_port_info info_smart = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &it821x_smart_port_ops }; static const struct ata_port_info info_passthru = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &it821x_passthru_port_ops }; static const struct ata_port_info info_rdc = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &it821x_rdc_port_ops }; static const struct ata_port_info info_rdc_11 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, /* No UDMA */ .port_ops = &it821x_rdc_port_ops }; diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index b173c157ab0..19fdecf319a 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -176,7 +176,7 @@ static __devinit int ixp4xx_pata_probe(struct platform_device *pdev) ap = host->ports[0]; ap->ops = &ixp4xx_port_ops; - ap->pio_mask = 0x1f; /* PIO4 */ + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI; ixp4xx_setup_port(ap, data, cs0->start, cs1->start); diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c index 38cf1ab2d28..3a1474ac883 100644 --- a/drivers/ata/pata_jmicron.c +++ b/drivers/ata/pata_jmicron.c @@ -136,8 +136,8 @@ static int jmicron_init_one (struct pci_dev *pdev, const struct pci_device_id *i static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &jmicron_ops, diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index e3bc1b43628..3f830f0fe2c 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c @@ -129,7 +129,7 @@ static int qdi; /* Set to probe QDI controllers */ static int winbond; /* Set to probe Winbond controllers, give I/O port if non standard */ static int autospeed; /* Chip present which snoops speed changes */ -static int pio_mask = 0x1F; /* PIO range for autospeed devices */ +static int pio_mask = ATA_PIO4; /* PIO range for autospeed devices */ static int iordy_mask = 0xFFFFFFFF; /* Use iordy if available */ /** diff --git a/drivers/ata/pata_marvell.c b/drivers/ata/pata_marvell.c index 76e399bf8c1..2096fb737f8 100644 --- a/drivers/ata/pata_marvell.c +++ b/drivers/ata/pata_marvell.c @@ -126,8 +126,8 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &marvell_ops, @@ -136,8 +136,8 @@ static int marvell_init_one (struct pci_dev *pdev, const struct pci_device_id *i /* Slave possible as its magically mapped not real */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &marvell_ops, diff --git a/drivers/ata/pata_mpc52xx.c b/drivers/ata/pata_mpc52xx.c index 50ae6d13078..68d27bc70d0 100644 --- a/drivers/ata/pata_mpc52xx.c +++ b/drivers/ata/pata_mpc52xx.c @@ -737,10 +737,10 @@ mpc52xx_ata_probe(struct of_device *op, const struct of_device_id *match) */ prop = of_get_property(op->node, "mwdma-mode", &proplen); if ((prop) && (proplen >= 4)) - mwdma_mask = 0x7 & ((1 << (*prop + 1)) - 1); + mwdma_mask = ATA_MWDMA2 & ((1 << (*prop + 1)) - 1); prop = of_get_property(op->node, "udma-mode", &proplen); if ((prop) && (proplen >= 4)) - udma_mask = 0x7 & ((1 << (*prop + 1)) - 1); + udma_mask = ATA_UDMA2 & ((1 << (*prop + 1)) - 1); ata_irq = irq_of_parse_and_map(op->node, 0); if (ata_irq == NO_IRQ) { diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c index aa576cac4d1..b21f0021f54 100644 --- a/drivers/ata/pata_mpiix.c +++ b/drivers/ata/pata_mpiix.c @@ -200,7 +200,7 @@ static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id) the MPIIX your box goes castors up */ ap->ops = &mpiix_port_ops; - ap->pio_mask = 0x1F; + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ioaddr.cmd_addr = cmd_addr; diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index 9dc05e1656a..bdb236957cb 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c @@ -51,8 +51,8 @@ static int netcell_init_one (struct pci_dev *pdev, const struct pci_device_id *e .flags = ATA_FLAG_SLAVE_POSS, /* Actually we don't really care about these as the firmware deals with it */ - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, /* UDMA 133 */ .port_ops = &netcell_ops, }; diff --git a/drivers/ata/pata_ninja32.c b/drivers/ata/pata_ninja32.c index 4dd9a3b031e..0fb6b1b1e63 100644 --- a/drivers/ata/pata_ninja32.c +++ b/drivers/ata/pata_ninja32.c @@ -136,7 +136,7 @@ static int ninja32_init_one(struct pci_dev *dev, const struct pci_device_id *id) if (!base) return -ENOMEM; ap->ops = &ninja32_port_ops; - ap->pio_mask = 0x1F; + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ioaddr.cmd_addr = base + 0x10; diff --git a/drivers/ata/pata_ns87410.c b/drivers/ata/pata_ns87410.c index 40d411c460d..ca53fac0671 100644 --- a/drivers/ata/pata_ns87410.c +++ b/drivers/ata/pata_ns87410.c @@ -144,7 +144,7 @@ static int ns87410_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x0F, + .pio_mask = ATA_PIO3, .port_ops = &ns87410_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_ns87415.c b/drivers/ata/pata_ns87415.c index 89bf5f865d6..773b1590b49 100644 --- a/drivers/ata/pata_ns87415.c +++ b/drivers/ata/pata_ns87415.c @@ -346,8 +346,8 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &ns87415_pata_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; @@ -355,8 +355,8 @@ static int ns87415_init_one (struct pci_dev *pdev, const struct pci_device_id *e #if defined(CONFIG_SUPERIO) static const struct ata_port_info info87560 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &ns87560_pata_ops, }; diff --git a/drivers/ata/pata_octeon_cf.c b/drivers/ata/pata_octeon_cf.c index 0fe4ef309c6..efe2c1985af 100644 --- a/drivers/ata/pata_octeon_cf.c +++ b/drivers/ata/pata_octeon_cf.c @@ -871,7 +871,7 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev) ap->private_data = cf_port; cf_port->ap = ap; ap->ops = &octeon_cf_ops; - ap->pio_mask = 0x7f; /* Support PIO 0-6 */ + ap->pio_mask = ATA_PIO6; ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING; @@ -900,7 +900,7 @@ static int __devinit octeon_cf_probe(struct platform_device *pdev) ap->ioaddr.ctl_addr = cs1 + (6 << 1) + 1; octeon_cf_ops.sff_data_xfer = octeon_cf_data_xfer16; - ap->mwdma_mask = 0x1f; /* Support MWDMA 0-4 */ + ap->mwdma_mask = ATA_MWDMA4; irq = platform_get_irq(pdev, 0); irq_handler = octeon_cf_interrupt; diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index 2c1a91c40c1..84ac5033ac8 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -238,8 +238,8 @@ static int oldpiix_init_one (struct pci_dev *pdev, const struct pci_device_id *e static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma1-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &oldpiix_pata_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_opti.c b/drivers/ata/pata_opti.c index e4fa4d565e9..99eddda2d2e 100644 --- a/drivers/ata/pata_opti.c +++ b/drivers/ata/pata_opti.c @@ -163,7 +163,7 @@ static int opti_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &opti_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_optidma.c b/drivers/ata/pata_optidma.c index 93bb6e91973..86885a445f9 100644 --- a/drivers/ata/pata_optidma.c +++ b/drivers/ata/pata_optidma.c @@ -399,15 +399,15 @@ static int optidma_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info_82c700 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &optidma_port_ops }; static const struct ata_port_info info_82c700_udma = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &optiplus_port_ops }; const struct ata_port_info *ppi[] = { &info_82c700, NULL }; diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 64b2e2281ee..a5cbcc280b2 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -299,7 +299,7 @@ static int pcmcia_init_one(struct pcmcia_device *pdev) ap = host->ports[p]; ap->ops = ops; - ap->pio_mask = 1; /* ISA so PIO 0 cycles */ + ap->pio_mask = ATA_PIO0; /* ISA so PIO 0 cycles */ ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ioaddr.cmd_addr = io_addr + 0x10 * p; ap->ioaddr.altstatus_addr = ctl_addr + 0x10 * p; diff --git a/drivers/ata/pata_pdc2027x.c b/drivers/ata/pata_pdc2027x.c index e94efccaa48..ca5cad0fd80 100644 --- a/drivers/ata/pata_pdc2027x.c +++ b/drivers/ata/pata_pdc2027x.c @@ -152,18 +152,18 @@ static struct ata_port_info pdc2027x_port_info[] = { { .flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &pdc2027x_pata100_ops, }, /* PDC_UDMA_133 */ { .flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA6, /* udma0-6 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA6, .port_ops = &pdc2027x_pata133_ops, }, }; diff --git a/drivers/ata/pata_pdc202xx_old.c b/drivers/ata/pata_pdc202xx_old.c index 799a6a09871..5fedb3d4032 100644 --- a/drivers/ata/pata_pdc202xx_old.c +++ b/drivers/ata/pata_pdc202xx_old.c @@ -291,22 +291,22 @@ static int pdc202xx_init_one(struct pci_dev *dev, const struct pci_device_id *id static const struct ata_port_info info[3] = { { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, .port_ops = &pdc2024x_port_ops }, { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &pdc2026x_port_ops }, { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &pdc2026x_port_ops } diff --git a/drivers/ata/pata_qdi.c b/drivers/ata/pata_qdi.c index f1b26f7c8e4..45879dc6fa4 100644 --- a/drivers/ata/pata_qdi.c +++ b/drivers/ata/pata_qdi.c @@ -212,11 +212,11 @@ static __init int qdi_init_one(unsigned long port, int type, unsigned long io, i if (type == 6580) { ap->ops = &qdi6580_port_ops; - ap->pio_mask = 0x1F; + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_SLAVE_POSS; } else { ap->ops = &qdi6500_port_ops; - ap->pio_mask = 0x07; /* Actually PIO3 !IORDY is possible */ + ap->pio_mask = ATA_PIO2; /* Actually PIO3 !IORDY is possible */ ap->flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_IORDY; } diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 695d44ae52c..1956d5c03a7 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -216,9 +216,9 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma1-2 */ - .udma_mask = 0x14, /* UDMA33/66 only */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, /* mwdma1-2 */ + .udma_mask = ATA_UDMA24_ONLY, .port_ops = &radisys_pata_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index fbfee1bd85f..2f3b49cc497 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -89,7 +89,7 @@ static void rb532_pata_setup_ports(struct ata_host *ah) ap = ah->ports[0]; ap->ops = &rb532_pata_port_ops; - ap->pio_mask = 0x1f; /* PIO4 */ + ap->pio_mask = ATA_PIO4; ap->flags = ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO; ap->ioaddr.cmd_addr = info->iobase + RB500_CF_REG_BASE; diff --git a/drivers/ata/pata_rz1000.c b/drivers/ata/pata_rz1000.c index 46d6bc1bf1e..0c574c065c6 100644 --- a/drivers/ata/pata_rz1000.c +++ b/drivers/ata/pata_rz1000.c @@ -88,7 +88,7 @@ static int rz1000_init_one (struct pci_dev *pdev, const struct pci_device_id *en static int printed_version; static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &rz1000_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 9a4bdca5461..36a0c359329 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -205,9 +205,9 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &sc1200_port_ops }; /* Can't enable port 2 yet, see top comments */ diff --git a/drivers/ata/pata_scc.c b/drivers/ata/pata_scc.c index d447f1cb46e..4257d6b40af 100644 --- a/drivers/ata/pata_scc.c +++ b/drivers/ata/pata_scc.c @@ -1001,8 +1001,8 @@ static struct ata_port_operations scc_pata_ops = { static struct ata_port_info scc_port_info[] = { { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x00, + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA6, .port_ops = &scc_pata_ops, }, diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c index 6aeeeeb3412..99cceb458e2 100644 --- a/drivers/ata/pata_sch.c +++ b/drivers/ata/pata_sch.c @@ -84,9 +84,9 @@ static struct ata_port_operations sch_pata_ops = { static struct ata_port_info sch_port_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = ATA_PIO4, /* pio0-4 */ - .mwdma_mask = ATA_MWDMA2, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &sch_pata_ops, }; diff --git a/drivers/ata/pata_serverworks.c b/drivers/ata/pata_serverworks.c index 8d2fd9dd40c..beaed12d50e 100644 --- a/drivers/ata/pata_serverworks.c +++ b/drivers/ata/pata_serverworks.c @@ -398,26 +398,26 @@ static int serverworks_init_one(struct pci_dev *pdev, const struct pci_device_id static const struct ata_port_info info[4] = { { /* OSB4 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &serverworks_osb4_port_ops }, { /* OSB4 no UDMA */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, - .udma_mask = 0x00, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + /* No UDMA */ .port_ops = &serverworks_osb4_port_ops }, { /* CSB5 */ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &serverworks_csb_port_ops }, { /* CSB5 - later revisions*/ .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &serverworks_csb_port_ops } diff --git a/drivers/ata/pata_sil680.c b/drivers/ata/pata_sil680.c index 9e764e5747e..4cb649d8d38 100644 --- a/drivers/ata/pata_sil680.c +++ b/drivers/ata/pata_sil680.c @@ -282,15 +282,15 @@ static int __devinit sil680_init_one(struct pci_dev *pdev, { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &sil680_port_ops }; static const struct ata_port_info info_slow = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &sil680_port_ops }; diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c index 27ceb42a774..488e77bcd22 100644 --- a/drivers/ata/pata_sis.c +++ b/drivers/ata/pata_sis.c @@ -552,51 +552,57 @@ static struct ata_port_operations sis_old_ops = { static const struct ata_port_info sis_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, - .udma_mask = 0, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + /* No UDMA */ .port_ops = &sis_old_ops, }; static const struct ata_port_info sis_info33 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, - .udma_mask = ATA_UDMA2, /* UDMA 33 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA2, .port_ops = &sis_old_ops, }; static const struct ata_port_info sis_info66 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .udma_mask = ATA_UDMA4, /* UDMA 66 */ + .pio_mask = ATA_PIO4, + /* No MWDMA */ + .udma_mask = ATA_UDMA4, .port_ops = &sis_66_ops, }; static const struct ata_port_info sis_info100 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA5, .port_ops = &sis_100_ops, }; static const struct ata_port_info sis_info100_early = { .flags = ATA_FLAG_SLAVE_POSS, + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA5, - .pio_mask = 0x1f, /* pio0-4 */ .port_ops = &sis_66_ops, }; static const struct ata_port_info sis_info133 = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA6, .port_ops = &sis_133_ops, }; const struct ata_port_info sis_info133_for_sata = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA6, .port_ops = &sis_133_for_sata_ops, }; static const struct ata_port_info sis_info133_early = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA6, .port_ops = &sis_133_early_ops, }; diff --git a/drivers/ata/pata_sl82c105.c b/drivers/ata/pata_sl82c105.c index 1b0e7b6d8ef..29f733c3206 100644 --- a/drivers/ata/pata_sl82c105.c +++ b/drivers/ata/pata_sl82c105.c @@ -283,13 +283,13 @@ static int sl82c105_init_one(struct pci_dev *dev, const struct pci_device_id *id { static const struct ata_port_info info_dma = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &sl82c105_port_ops }; static const struct ata_port_info info_early = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, + .pio_mask = ATA_PIO4, .port_ops = &sl82c105_port_ops }; /* for now use only the first port */ diff --git a/drivers/ata/pata_triflex.c b/drivers/ata/pata_triflex.c index ef9597517cd..f1f13ff222f 100644 --- a/drivers/ata/pata_triflex.c +++ b/drivers/ata/pata_triflex.c @@ -191,8 +191,8 @@ static int triflex_init_one(struct pci_dev *dev, const struct pci_device_id *id) { static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &triflex_port_ops }; const struct ata_port_info *ppi[] = { &info, NULL }; diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index ba556d3e696..b08e6e0f82b 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -422,46 +422,46 @@ static int via_init_one(struct pci_dev *pdev, const struct pci_device_id *id) /* Early VIA without UDMA support */ static const struct ata_port_info via_mwdma_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &via_port_ops }; /* Ditto with IRQ masking required */ static const struct ata_port_info via_mwdma_info_borked = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .port_ops = &via_port_ops_noirq, }; /* VIA UDMA 33 devices (and borked 66) */ static const struct ata_port_info via_udma33_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA2, .port_ops = &via_port_ops }; /* VIA UDMA 66 devices */ static const struct ata_port_info via_udma66_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA4, .port_ops = &via_port_ops }; /* VIA UDMA 100 devices */ static const struct ata_port_info via_udma100_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &via_port_ops }; /* UDMA133 with bad AST (All current 133) */ static const struct ata_port_info via_udma133_info = { .flags = ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, /* FIXME: should check north bridge */ .port_ops = &via_port_ops }; diff --git a/drivers/ata/pata_winbond.c b/drivers/ata/pata_winbond.c index 319e164a3d7..6d8619b6f67 100644 --- a/drivers/ata/pata_winbond.c +++ b/drivers/ata/pata_winbond.c @@ -193,7 +193,7 @@ static __init int winbond_init_one(unsigned long port) ata_port_desc(ap, "cmd 0x%lx ctl 0x%lx", cmd_port, ctl_port); ap->ops = &winbond_port_ops; - ap->pio_mask = 0x1F; + ap->pio_mask = ATA_PIO4; ap->flags |= ATA_FLAG_SLAVE_POSS; ap->ioaddr.cmd_addr = cmd_addr; ap->ioaddr.altstatus_addr = ctl_addr; diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index be53545c9f6..c509c206a45 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -166,7 +166,7 @@ static struct ata_port_info adma_port_info[] = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, - .pio_mask = 0x10, /* pio4 */ + .pio_mask = ATA_PIO4_ONLY, .udma_mask = ATA_UDMA4, .port_ops = &adma_ata_ops, }, diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 55bc88c1707..c2e90e1fece 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c @@ -1279,8 +1279,8 @@ static struct ata_port_operations sata_fsl_ops = { static const struct ata_port_info sata_fsl_port_info[] = { { .flags = SATA_FSL_HOST_FLAGS, - .pio_mask = 0x1f, /* pio 0-4 */ - .udma_mask = 0x7f, /* udma 0-6 */ + .pio_mask = ATA_PIO4, + .udma_mask = ATA_UDMA6, .port_ops = &sata_fsl_ops, }, }; diff --git a/drivers/ata/sata_inic162x.c b/drivers/ata/sata_inic162x.c index fbbd87c96f1..305a4f825f5 100644 --- a/drivers/ata/sata_inic162x.c +++ b/drivers/ata/sata_inic162x.c @@ -744,8 +744,8 @@ static struct ata_port_operations inic_port_ops = { static struct ata_port_info inic_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &inic_port_ops }; diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index f65b53785a8..2f523f8c27f 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -57,9 +57,9 @@ enum { NV_MMIO_BAR = 5, NV_PORTS = 2, - NV_PIO_MASK = 0x1f, - NV_MWDMA_MASK = 0x07, - NV_UDMA_MASK = 0x7f, + NV_PIO_MASK = ATA_PIO4, + NV_MWDMA_MASK = ATA_MWDMA2, + NV_UDMA_MASK = ATA_UDMA6, NV_PORT0_SCR_REG_OFFSET = 0x00, NV_PORT1_SCR_REG_OFFSET = 0x40, diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index ba9a2570a74..3ad2b886363 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -213,8 +213,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_SATA_PATA, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_old_sata_ops, }, @@ -222,8 +222,8 @@ static const struct ata_port_info pdc_port_info[] = { [board_2037x_pata] = { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_pata_ops, }, @@ -232,8 +232,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_4_PORTS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_old_sata_ops, }, @@ -242,8 +242,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | PDC_FLAG_4_PORTS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_pata_ops, }, @@ -252,8 +252,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_GEN_II | PDC_FLAG_SATA_PATA, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_sata_ops, }, @@ -262,8 +262,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SLAVE_POSS | PDC_FLAG_GEN_II, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_pata_ops, }, @@ -272,8 +272,8 @@ static const struct ata_port_info pdc_port_info[] = { { .flags = PDC_COMMON_FLAGS | ATA_FLAG_SATA | PDC_FLAG_GEN_II | PDC_FLAG_4_PORTS, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_sata_ops, }, diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index a000c86ac85..7112d89fd9f 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -160,7 +160,7 @@ static const struct ata_port_info qs_port_info[] = { { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, - .pio_mask = 0x10, /* pio4 */ + .pio_mask = ATA_PIO4_ONLY, .udma_mask = ATA_UDMA6, .port_ops = &qs_ata_ops, }, diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index d0091609e21..e67ce8e5caa 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c @@ -200,8 +200,8 @@ static const struct ata_port_info sil_port_info[] = { /* sil_3112 */ { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &sil_ops, }, @@ -209,24 +209,24 @@ static const struct ata_port_info sil_port_info[] = { { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_MOD15WRITE | SIL_FLAG_NO_SATA_IRQ, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &sil_ops, }, /* sil_3512 */ { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &sil_ops, }, /* sil_3114 */ { .flags = SIL_DFL_PORT_FLAGS | SIL_FLAG_RERR_ON_DMA_ACT, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA5, .port_ops = &sil_ops, }, diff --git a/drivers/ata/sata_sil24.c b/drivers/ata/sata_sil24.c index 2590c2279fa..0d8990dcdfc 100644 --- a/drivers/ata/sata_sil24.c +++ b/drivers/ata/sata_sil24.c @@ -429,25 +429,25 @@ static const struct ata_port_info sil24_port_info[] = { { .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(4) | SIL24_FLAG_PCIX_IRQ_WOC, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &sil24_ops, }, /* sil_3132 */ { .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(2), - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &sil24_ops, }, /* sil_3131/sil_3531 */ { .flags = SIL24_COMMON_FLAGS | SIL24_NPORTS2FLAG(1), - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ - .udma_mask = ATA_UDMA5, /* udma0-5 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA5, .port_ops = &sil24_ops, }, }; diff --git a/drivers/ata/sata_sis.c b/drivers/ata/sata_sis.c index 9c43b4e7c4a..8f983322861 100644 --- a/drivers/ata/sata_sis.c +++ b/drivers/ata/sata_sis.c @@ -97,8 +97,8 @@ static struct ata_port_operations sis_ops = { static const struct ata_port_info sis_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, - .mwdma_mask = 0x7, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &sis_ops, }; diff --git a/drivers/ata/sata_svw.c b/drivers/ata/sata_svw.c index 609d147813a..7257f2d5c52 100644 --- a/drivers/ata/sata_svw.c +++ b/drivers/ata/sata_svw.c @@ -361,8 +361,8 @@ static const struct ata_port_info k2_port_info[] = { { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &k2_sata_ops, }, @@ -371,8 +371,8 @@ static const struct ata_port_info k2_port_info[] = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA | K2_FLAG_SATA_8_PORTS, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &k2_sata_ops, }, @@ -380,8 +380,8 @@ static const struct ata_port_info k2_port_info[] = { { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | K2_FLAG_BAR_POS_3, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &k2_sata_ops, }, @@ -389,8 +389,8 @@ static const struct ata_port_info k2_port_info[] = { { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &k2_sata_ops, }, diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index ec04b8d3c79..dce3dccced3 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c @@ -265,8 +265,8 @@ static const struct ata_port_info pdc_port_info[] = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SRST | ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING, - .pio_mask = 0x1f, /* pio0-4 */ - .mwdma_mask = 0x07, /* mwdma0-2 */ + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &pdc_20621_ops, }, diff --git a/drivers/ata/sata_uli.c b/drivers/ata/sata_uli.c index 019575bb3e0..e5bff47e8aa 100644 --- a/drivers/ata/sata_uli.c +++ b/drivers/ata/sata_uli.c @@ -89,7 +89,7 @@ static struct ata_port_operations uli_ops = { static const struct ata_port_info uli_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_IGN_SIMPLEX, - .pio_mask = 0x1f, /* pio0-4 */ + .pio_mask = ATA_PIO4, .udma_mask = ATA_UDMA6, .port_ops = &uli_ops, }; diff --git a/drivers/ata/sata_via.c b/drivers/ata/sata_via.c index 5c62da9cd49..98e8c50703b 100644 --- a/drivers/ata/sata_via.c +++ b/drivers/ata/sata_via.c @@ -146,24 +146,24 @@ static struct ata_port_operations vt8251_ops = { static const struct ata_port_info vt6420_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &vt6420_sata_ops, }; static struct ata_port_info vt6421_sport_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &vt6421_sata_ops, }; static struct ata_port_info vt6421_pport_info = { .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, - .mwdma_mask = 0, + .pio_mask = ATA_PIO4, + /* No MWDMA */ .udma_mask = ATA_UDMA6, .port_ops = &vt6421_pata_ops, }; @@ -171,8 +171,8 @@ static struct ata_port_info vt6421_pport_info = { static struct ata_port_info vt8251_port_info = { .flags = ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &vt8251_ops, }; diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index c57cdff9e6b..ef211f333d7 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -345,8 +345,8 @@ static int __devinit vsc_sata_init_one(struct pci_dev *pdev, static const struct ata_port_info pi = { .flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO, - .pio_mask = 0x1f, - .mwdma_mask = 0x07, + .pio_mask = ATA_PIO4, + .mwdma_mask = ATA_MWDMA2, .udma_mask = ATA_UDMA6, .port_ops = &vsc_sata_ops, }; -- cgit v1.2.3 From aef37d8d80d8c027f03d362a97afe3f6a42bfbb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Inge=20Bols=C3=B8?= Date: Sat, 14 Mar 2009 23:07:33 +0100 Subject: pata_radisys: fix mwdma_mask to exclude mwdma0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As noted by Alan: >Your suspicions are correct here btw - the device can only do MWDMA1 and >MWDMA2 (much like some PIIX devices) Signed-off-by: Erik Inge Bolsø Signed-off-by: Jeff Garzik --- drivers/ata/pata_radisys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_radisys.c b/drivers/ata/pata_radisys.c index 1956d5c03a7..4401b332eaa 100644 --- a/drivers/ata/pata_radisys.c +++ b/drivers/ata/pata_radisys.c @@ -217,7 +217,7 @@ static int radisys_init_one (struct pci_dev *pdev, const struct pci_device_id *e static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, /* mwdma1-2 */ + .mwdma_mask = ATA_MWDMA12_ONLY, .udma_mask = ATA_UDMA24_ONLY, .port_ops = &radisys_pata_ops, }; -- cgit v1.2.3 From b2a034cf16a1642e647497c70c1cd9c09bf39412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Inge=20Bols=C3=B8?= Date: Sat, 14 Mar 2009 23:08:20 +0100 Subject: pata_efar: fix *dma_mask MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to Alan: >and yes the EFAR does UDMA66. mwdma: >Yep - wrong comment. The EFAR is a sort of clone of the PIIX and I >copied the comment while EFAR don't appear to have copied the >limitation Signed-off-by: Erik Inge Bolsø Signed-off-by: Jeff Garzik --- drivers/ata/pata_efar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index bd498cc3920..2085e0a3a05 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c @@ -252,8 +252,8 @@ static int efar_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static const struct ata_port_info info = { .flags = ATA_FLAG_SLAVE_POSS, .pio_mask = ATA_PIO4, - .mwdma_mask = ATA_MWDMA2, /* mwdma1-2 */ - .udma_mask = ATA_UDMA3, /* UDMA 66 */ + .mwdma_mask = ATA_MWDMA2, + .udma_mask = ATA_UDMA4, .port_ops = &efar_ops, }; const struct ata_port_info *ppi[] = { &info, NULL }; -- cgit v1.2.3 From 9223d01b2fdf638a73888ad73a1784fca3454c1e Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 13 Mar 2009 15:41:43 +0100 Subject: pata-rb532-cf: platform_get_irq() fix ignored failure platform_get_irq() can return -ENXIO, but since 'irq' is an unsigned int, it does not show when the IRQ resource wasn't found. Make irq an int so that we can use a single variable to test the platform_get_irq() return value. Signed-off-by: Roel Kluin Signed-off-by: Phil Sutter Signed-off-by: Florian Fainelli Signed-off-by: Jeff Garzik --- drivers/ata/pata_rb532_cf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_rb532_cf.c b/drivers/ata/pata_rb532_cf.c index 2f3b49cc497..8e3cdef8a25 100644 --- a/drivers/ata/pata_rb532_cf.c +++ b/drivers/ata/pata_rb532_cf.c @@ -104,7 +104,7 @@ static void rb532_pata_setup_ports(struct ata_host *ah) static __devinit int rb532_pata_driver_probe(struct platform_device *pdev) { - unsigned int irq; + int irq; int gpio; struct resource *res; struct ata_host *ah; -- cgit v1.2.3 From 40f21b1124a9552bc093469280eb8239dc5f73d7 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Tue, 10 Mar 2009 18:51:04 -0400 Subject: sata_mv: cosmetic preparations for IRQ coalescing Various cosmetic changes in preparation for the IRQ coalescing feature. Note that the various MV_IRQ_COAL_* definitions are restored/renamed in the folloup patch which adds IRQ coalescing to the driver. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 62 ++++++++++++++++++++++----------------------------- 1 file changed, 27 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 8cad3b2fe55..206220ec582 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1,10 +1,13 @@ /* * sata_mv.c - Marvell SATA support * - * Copyright 2008: Marvell Corporation, all rights reserved. + * Copyright 2008-2009: Marvell Corporation, all rights reserved. * Copyright 2005: EMC Corporation, all rights reserved. * Copyright 2005 Red Hat, Inc. All rights reserved. * + * Originally written by Brett Russ. + * Extensive overhaul and enhancement by Mark Lord . + * * Please ALWAYS copy linux-ide@vger.kernel.org on emails. * * This program is free software; you can redistribute it and/or modify @@ -25,8 +28,6 @@ /* * sata_mv TODO list: * - * --> Errata workaround for NCQ device errors. - * * --> More errata workarounds for PCI-X. * * --> Complete a full errata audit for all chipsets to identify others. @@ -68,6 +69,16 @@ #define DRV_NAME "sata_mv" #define DRV_VERSION "1.26" +/* + * module options + */ + +static int msi; +#ifdef CONFIG_PCI +module_param(msi, int, S_IRUGO); +MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); +#endif + enum { /* BAR's are enumerated in terms of pci_resource_start() terms */ MV_PRIMARY_BAR = 0, /* offset 0x10: memory space */ @@ -78,12 +89,6 @@ enum { MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */ MV_PCI_REG_BASE = 0, - MV_IRQ_COAL_REG_BASE = 0x18000, /* 6xxx part only */ - MV_IRQ_COAL_CAUSE = (MV_IRQ_COAL_REG_BASE + 0x08), - MV_IRQ_COAL_CAUSE_LO = (MV_IRQ_COAL_REG_BASE + 0x88), - MV_IRQ_COAL_CAUSE_HI = (MV_IRQ_COAL_REG_BASE + 0x8c), - MV_IRQ_COAL_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xcc), - MV_IRQ_COAL_TIME_THRESHOLD = (MV_IRQ_COAL_REG_BASE + 0xd0), MV_SATAHC0_REG_BASE = 0x20000, MV_FLASH_CTL_OFS = 0x1046c, @@ -115,16 +120,14 @@ enum { /* Host Flags */ MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */ - MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */ MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING, MV_GEN_I_FLAGS = MV_COMMON_FLAGS | ATA_FLAG_NO_ATAPI, - MV_GEN_II_FLAGS = MV_COMMON_FLAGS | MV_FLAG_IRQ_COALESCE | - ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA | - ATA_FLAG_NCQ, + MV_GEN_II_FLAGS = MV_COMMON_FLAGS | ATA_FLAG_NCQ | + ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA, MV_GEN_IIE_FLAGS = MV_GEN_II_FLAGS | ATA_FLAG_AN, @@ -179,16 +182,16 @@ enum { PCI_HC_MAIN_IRQ_MASK_OFS = 0x1d64, SOC_HC_MAIN_IRQ_CAUSE_OFS = 0x20020, SOC_HC_MAIN_IRQ_MASK_OFS = 0x20024, - ERR_IRQ = (1 << 0), /* shift by port # */ - DONE_IRQ = (1 << 1), /* shift by port # */ + ERR_IRQ = (1 << 0), /* shift by (2 * port #) */ + DONE_IRQ = (1 << 1), /* shift by (2 * port #) */ HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */ HC_SHIFT = 9, /* bits 9-17 = HC1's ports */ PCI_ERR = (1 << 18), - TRAN_LO_DONE = (1 << 19), /* 6xxx: IRQ coalescing */ - TRAN_HI_DONE = (1 << 20), /* 6xxx: IRQ coalescing */ - PORTS_0_3_COAL_DONE = (1 << 8), - PORTS_4_7_COAL_DONE = (1 << 17), - PORTS_0_7_COAL_DONE = (1 << 21), /* 6xxx: IRQ coalescing */ + TRAN_COAL_LO_DONE = (1 << 19), /* transaction coalescing */ + TRAN_COAL_HI_DONE = (1 << 20), /* transaction coalescing */ + PORTS_0_3_COAL_DONE = (1 << 8), /* HC0 IRQ coalescing */ + PORTS_4_7_COAL_DONE = (1 << 17), /* HC1 IRQ coalescing */ + ALL_PORTS_COAL_DONE = (1 << 21), /* GEN_II(E) IRQ coalescing */ GPIO_INT = (1 << 22), SELF_INT = (1 << 23), TWSI_INT = (1 << 24), @@ -621,7 +624,7 @@ static struct ata_port_operations mv6_ops = { .softreset = mv_softreset, .error_handler = mv_pmp_error_handler, - .sff_check_status = mv_sff_check_status, + .sff_check_status = mv_sff_check_status, .sff_irq_clear = mv_sff_irq_clear, .check_atapi_dma = mv_check_atapi_dma, .bmdma_setup = mv_bmdma_setup, @@ -1255,8 +1258,8 @@ static void mv_60x1_errata_sata25(struct ata_port *ap, int want_ncq) } /** - * mv_bmdma_enable - set a magic bit on GEN_IIE to allow bmdma - * @ap: Port being initialized + * mv_bmdma_enable - set a magic bit on GEN_IIE to allow bmdma + * @ap: Port being initialized * * There are two DMA modes on these chips: basic DMA, and EDMA. * @@ -2000,7 +2003,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc) struct mv_host_priv *hpriv = ap->host->private_data; /* * Workaround for 88SX60x1 FEr SATA#25 (part 2). - * + * * After any NCQ error, the READ_LOG_EXT command * from libata-eh *must* use mv_qc_issue_fis(). * Otherwise it might fail, due to chip errata. @@ -3704,12 +3707,6 @@ static struct pci_driver mv_pci_driver = { .remove = ata_pci_remove_one, }; -/* - * module options - */ -static int msi; /* Use PCI msi; either zero (off, default) or non-zero */ - - /* move to PCI layer or libata core? */ static int pci_go_64(struct pci_dev *pdev) { @@ -3891,10 +3888,5 @@ MODULE_DEVICE_TABLE(pci, mv_pci_tbl); MODULE_VERSION(DRV_VERSION); MODULE_ALIAS("platform:" DRV_NAME); -#ifdef CONFIG_PCI -module_param(msi, int, 0444); -MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); -#endif - module_init(mv_init); module_exit(mv_exit); -- cgit v1.2.3 From 2b748a0a344847fe6b924407bbe153e1878c9f09 Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Tue, 10 Mar 2009 22:01:17 -0400 Subject: sata_mv: implement IRQ coalescing (v2) Add IRQ coalescing to sata_mv (off by default). This feature can reduce total interrupt overhead for RAID setups in some situations, by deferring the interrupt signal until one or both of: a) a specified io_count (completed SATA commands) is achieved, or b) a specified time interval elapses after an IO completion. For now, module parameters are used to set the irq_coalescing_io_count and irq_coalescing_usecs (timeout) globally. These may eventually be supplemented with sysfs attributes, so that thresholds can be set on-the-fly and on a per-chip (or even per-host_controller) basis. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 135 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 206220ec582..ef385451ffd 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -34,10 +34,7 @@ * * --> Develop a low-power-consumption strategy, and implement it. * - * --> [Experiment, low priority] Investigate interrupt coalescing. - * Quite often, especially with PCI Message Signalled Interrupts (MSI), - * the overhead reduced by interrupt mitigation is quite often not - * worth the latency cost. + * --> Add sysfs attributes for per-chip / per-HC IRQ coalescing thresholds. * * --> [Experiment, Marvell value added] Is it possible to use target * mode to cross-connect two Linux boxes with Marvell cards? If so, @@ -67,7 +64,7 @@ #include #define DRV_NAME "sata_mv" -#define DRV_VERSION "1.26" +#define DRV_VERSION "1.27" /* * module options @@ -79,6 +76,16 @@ module_param(msi, int, S_IRUGO); MODULE_PARM_DESC(msi, "Enable use of PCI MSI (0=off, 1=on)"); #endif +static int irq_coalescing_io_count; +module_param(irq_coalescing_io_count, int, S_IRUGO); +MODULE_PARM_DESC(irq_coalescing_io_count, + "IRQ coalescing I/O count threshold (0..255)"); + +static int irq_coalescing_usecs; +module_param(irq_coalescing_usecs, int, S_IRUGO); +MODULE_PARM_DESC(irq_coalescing_usecs, + "IRQ coalescing time threshold in usecs"); + enum { /* BAR's are enumerated in terms of pci_resource_start() terms */ MV_PRIMARY_BAR = 0, /* offset 0x10: memory space */ @@ -88,8 +95,33 @@ enum { MV_MAJOR_REG_AREA_SZ = 0x10000, /* 64KB */ MV_MINOR_REG_AREA_SZ = 0x2000, /* 8KB */ + /* For use with both IRQ coalescing methods ("all ports" or "per-HC" */ + COAL_CLOCKS_PER_USEC = 150, /* for calculating COAL_TIMEs */ + MAX_COAL_TIME_THRESHOLD = ((1 << 24) - 1), /* internal clocks count */ + MAX_COAL_IO_COUNT = 255, /* completed I/O count */ + MV_PCI_REG_BASE = 0, + /* + * Per-chip ("all ports") interrupt coalescing feature. + * This is only for GEN_II / GEN_IIE hardware. + * + * Coalescing defers the interrupt until either the IO_THRESHOLD + * (count of completed I/Os) is met, or the TIME_THRESHOLD is met. + */ + MV_COAL_REG_BASE = 0x18000, + MV_IRQ_COAL_CAUSE = (MV_COAL_REG_BASE + 0x08), + ALL_PORTS_COAL_IRQ = (1 << 4), /* all ports irq event */ + + MV_IRQ_COAL_IO_THRESHOLD = (MV_COAL_REG_BASE + 0xcc), + MV_IRQ_COAL_TIME_THRESHOLD = (MV_COAL_REG_BASE + 0xd0), + + /* + * Registers for the (unused here) transaction coalescing feature: + */ + MV_TRAN_COAL_CAUSE_LO = (MV_COAL_REG_BASE + 0x88), + MV_TRAN_COAL_CAUSE_HI = (MV_COAL_REG_BASE + 0x8c), + MV_SATAHC0_REG_BASE = 0x20000, MV_FLASH_CTL_OFS = 0x1046c, MV_GPIO_PORT_CTL_OFS = 0x104f0, @@ -186,6 +218,8 @@ enum { DONE_IRQ = (1 << 1), /* shift by (2 * port #) */ HC0_IRQ_PEND = 0x1ff, /* bits 0-8 = HC0's ports */ HC_SHIFT = 9, /* bits 9-17 = HC1's ports */ + DONE_IRQ_0_3 = 0x000000aa, /* DONE_IRQ ports 0,1,2,3 */ + DONE_IRQ_4_7 = (DONE_IRQ_0_3 << HC_SHIFT), /* 4,5,6,7 */ PCI_ERR = (1 << 18), TRAN_COAL_LO_DONE = (1 << 19), /* transaction coalescing */ TRAN_COAL_HI_DONE = (1 << 20), /* transaction coalescing */ @@ -207,6 +241,16 @@ enum { HC_COAL_IRQ = (1 << 4), /* IRQ coalescing */ DEV_IRQ = (1 << 8), /* shift by port # */ + /* + * Per-HC (Host-Controller) interrupt coalescing feature. + * This is present on all chip generations. + * + * Coalescing defers the interrupt until either the IO_THRESHOLD + * (count of completed I/Os) is met, or the TIME_THRESHOLD is met. + */ + HC_IRQ_COAL_IO_THRESHOLD_OFS = 0x000c, + HC_IRQ_COAL_TIME_THRESHOLD_OFS = 0x0010, + /* Shadow block registers */ SHD_BLK_OFS = 0x100, SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */ @@ -897,6 +941,23 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio, port_mmio + EDMA_RSP_Q_OUT_PTR_OFS); } +static void mv_write_main_irq_mask(u32 mask, struct mv_host_priv *hpriv) +{ + /* + * When writing to the main_irq_mask in hardware, + * we must ensure exclusivity between the interrupt coalescing bits + * and the corresponding individual port DONE_IRQ bits. + * + * Note that this register is really an "IRQ enable" register, + * not an "IRQ mask" register as Marvell's naming might suggest. + */ + if (mask & (ALL_PORTS_COAL_DONE | PORTS_0_3_COAL_DONE)) + mask &= ~DONE_IRQ_0_3; + if (mask & (ALL_PORTS_COAL_DONE | PORTS_4_7_COAL_DONE)) + mask &= ~DONE_IRQ_4_7; + writelfl(mask, hpriv->main_irq_mask_addr); +} + static void mv_set_main_irq_mask(struct ata_host *host, u32 disable_bits, u32 enable_bits) { @@ -907,7 +968,7 @@ static void mv_set_main_irq_mask(struct ata_host *host, new_mask = (old_mask & ~disable_bits) | enable_bits; if (new_mask != old_mask) { hpriv->main_irq_mask = new_mask; - writelfl(new_mask, hpriv->main_irq_mask_addr); + mv_write_main_irq_mask(new_mask, hpriv); } } @@ -948,6 +1009,64 @@ static void mv_clear_and_enable_port_irqs(struct ata_port *ap, mv_enable_port_irqs(ap, port_irqs); } +static void mv_set_irq_coalescing(struct ata_host *host, + unsigned int count, unsigned int usecs) +{ + struct mv_host_priv *hpriv = host->private_data; + void __iomem *mmio = hpriv->base, *hc_mmio; + u32 coal_enable = 0; + unsigned long flags; + unsigned int clks; + const u32 coal_disable = PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE | + ALL_PORTS_COAL_DONE; + + /* Disable IRQ coalescing if either threshold is zero */ + if (!usecs || !count) { + clks = count = 0; + } else { + /* Respect maximum limits of the hardware */ + clks = usecs * COAL_CLOCKS_PER_USEC; + if (clks > MAX_COAL_TIME_THRESHOLD) + clks = MAX_COAL_TIME_THRESHOLD; + if (count > MAX_COAL_IO_COUNT) + count = MAX_COAL_IO_COUNT; + } + + spin_lock_irqsave(&host->lock, flags); + +#if 0 /* disabled pending functional clarification from Marvell */ + if (!IS_GEN_I(hpriv)) { + /* + * GEN_II/GEN_IIE: global thresholds for the entire chip. + */ + writel(clks, mmio + MV_IRQ_COAL_TIME_THRESHOLD); + writel(count, mmio + MV_IRQ_COAL_IO_THRESHOLD); + /* clear leftover coal IRQ bit */ + writelfl(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE); + clks = count = 0; /* so as to clear the alternate regs below */ + coal_enable = ALL_PORTS_COAL_DONE; + } +#endif + /* + * All chips: independent thresholds for each HC on the chip. + */ + hc_mmio = mv_hc_base_from_port(mmio, 0); + writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS); + writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS); + coal_enable |= PORTS_0_3_COAL_DONE; + if (hpriv->n_ports > 4) { + hc_mmio = mv_hc_base_from_port(mmio, MV_PORTS_PER_HC); + writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS); + writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS); + coal_enable |= PORTS_4_7_COAL_DONE; + } + if (!count) + coal_enable = 0; + mv_set_main_irq_mask(host, coal_disable, coal_enable); + + spin_unlock_irqrestore(&host->lock, flags); +} + /** * mv_start_edma - Enable eDMA engine * @base: port base address @@ -2500,6 +2619,10 @@ static int mv_host_intr(struct ata_host *host, u32 main_irq_cause) void __iomem *mmio = hpriv->base, *hc_mmio; unsigned int handled = 0, port; + /* If asserted, clear the "all ports" IRQ coalescing bit */ + if (main_irq_cause & ALL_PORTS_COAL_DONE) + writel(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE); + for (port = 0; port < hpriv->n_ports; port++) { struct ata_port *ap = host->ports[port]; unsigned int p, shift, hardport, port_cause; @@ -2532,6 +2655,8 @@ static int mv_host_intr(struct ata_host *host, u32 main_irq_cause) * to ack (only) those ports via hc_irq_cause. */ ack_irqs = 0; + if (hc_cause & PORTS_0_3_COAL_DONE) + ack_irqs = HC_COAL_IRQ; for (p = 0; p < MV_PORTS_PER_HC; ++p) { if ((port + p) >= hpriv->n_ports) break; @@ -2620,7 +2745,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) /* for MSI: block new interrupts while in here */ if (using_msi) - writel(0, hpriv->main_irq_mask_addr); + mv_write_main_irq_mask(0, hpriv); main_irq_cause = readl(hpriv->main_irq_cause_addr); pending_irqs = main_irq_cause & hpriv->main_irq_mask; @@ -2637,7 +2762,7 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance) /* for MSI: unmask; interrupt cause bits will retrigger now */ if (using_msi) - writel(hpriv->main_irq_mask, hpriv->main_irq_mask_addr); + mv_write_main_irq_mask(hpriv->main_irq_mask, hpriv); spin_unlock(&host->lock); @@ -3546,6 +3671,8 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx) * The per-port interrupts get done later as ports are set up. */ mv_set_main_irq_mask(host, 0, PCI_ERR); + mv_set_irq_coalescing(host, irq_coalescing_io_count, + irq_coalescing_usecs); done: return rc; } -- cgit v1.2.3 From 6abf4678261218938ccdac90767d34ce9937634f Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Wed, 11 Mar 2009 00:56:00 -0400 Subject: sata_mv: optimize IRQ coalescing for 8-port chips Enable use of the "all ports" IRQ coalescing optimization for GEN_II / GEN_IIE chips that have dual host-controllers (8-ports). Currently only the 6081 chip qualifies, but other chips may come along someday. Rather than each half of the chip having to satisfy a local set of coalescing thresholds, use of this feature groups all ports together under a single set of thresholds. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index ef385451ffd..47184567248 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1016,7 +1016,7 @@ static void mv_set_irq_coalescing(struct ata_host *host, void __iomem *mmio = hpriv->base, *hc_mmio; u32 coal_enable = 0; unsigned long flags; - unsigned int clks; + unsigned int clks, is_dual_hc = hpriv->n_ports > MV_PORTS_PER_HC; const u32 coal_disable = PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE | ALL_PORTS_COAL_DONE; @@ -1033,37 +1033,41 @@ static void mv_set_irq_coalescing(struct ata_host *host, } spin_lock_irqsave(&host->lock, flags); + mv_set_main_irq_mask(host, coal_disable, 0); -#if 0 /* disabled pending functional clarification from Marvell */ - if (!IS_GEN_I(hpriv)) { + if (is_dual_hc && !IS_GEN_I(hpriv)) { /* - * GEN_II/GEN_IIE: global thresholds for the entire chip. + * GEN_II/GEN_IIE with dual host controllers: + * one set of global thresholds for the entire chip. */ writel(clks, mmio + MV_IRQ_COAL_TIME_THRESHOLD); writel(count, mmio + MV_IRQ_COAL_IO_THRESHOLD); /* clear leftover coal IRQ bit */ - writelfl(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE); - clks = count = 0; /* so as to clear the alternate regs below */ - coal_enable = ALL_PORTS_COAL_DONE; + writel(~ALL_PORTS_COAL_IRQ, mmio + MV_IRQ_COAL_CAUSE); + if (count) + coal_enable = ALL_PORTS_COAL_DONE; + clks = count = 0; /* force clearing of regular regs below */ } -#endif + /* * All chips: independent thresholds for each HC on the chip. */ hc_mmio = mv_hc_base_from_port(mmio, 0); writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS); writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS); - coal_enable |= PORTS_0_3_COAL_DONE; - if (hpriv->n_ports > 4) { + writel(~HC_COAL_IRQ, hc_mmio + HC_IRQ_CAUSE_OFS); + if (count) + coal_enable |= PORTS_0_3_COAL_DONE; + if (is_dual_hc) { hc_mmio = mv_hc_base_from_port(mmio, MV_PORTS_PER_HC); writel(clks, hc_mmio + HC_IRQ_COAL_TIME_THRESHOLD_OFS); writel(count, hc_mmio + HC_IRQ_COAL_IO_THRESHOLD_OFS); - coal_enable |= PORTS_4_7_COAL_DONE; + writel(~HC_COAL_IRQ, hc_mmio + HC_IRQ_CAUSE_OFS); + if (count) + coal_enable |= PORTS_4_7_COAL_DONE; } - if (!count) - coal_enable = 0; - mv_set_main_irq_mask(host, coal_disable, coal_enable); + mv_set_main_irq_mask(host, 0, coal_enable); spin_unlock_irqrestore(&host->lock, flags); } -- cgit v1.2.3 From 000b344f4ca7828ee43940255c8bbb32e2c7dbec Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Sun, 15 Mar 2009 11:33:19 -0400 Subject: sata_mv: fix LED blinking for SoC+NCQ For Marvell SoC chips, the HDD LED does not blink when there is disk I/O if NCQ is enabled. Add a quirk that enables blink mode for the LED while NCQ is enabled on any port of a SoC host controller. Normal LED function is restored when NCQ is not enabled on any port. The code to enable the blink mode is based on earlier code and suggestions from Frans Pop, Saeed Bishara, and possibly others. Signed-off-by: Mark Lord Tested-by: Frans Pop Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 47184567248..8a751054c8a 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -251,6 +251,11 @@ enum { HC_IRQ_COAL_IO_THRESHOLD_OFS = 0x000c, HC_IRQ_COAL_TIME_THRESHOLD_OFS = 0x0010, + SOC_LED_CTRL_OFS = 0x2c, + SOC_LED_CTRL_BLINK = (1 << 0), /* Active LED blink */ + SOC_LED_CTRL_ACT_PRESENCE = (1 << 2), /* Multiplex dev presence */ + /* with dev activity LED */ + /* Shadow block registers */ SHD_BLK_OFS = 0x100, SHD_CTL_AST_OFS = 0x20, /* ofs from SHD_BLK_OFS */ @@ -411,6 +416,7 @@ enum { MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */ MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */ MV_HP_FLAG_SOC = (1 << 11), /* SystemOnChip, no PCI */ + MV_HP_QUIRK_LED_BLINK_EN = (1 << 12), /* is led blinking enabled? */ /* Port private flags (pp_flags) */ MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */ @@ -1404,6 +1410,61 @@ static void mv_bmdma_enable_iie(struct ata_port *ap, int enable_bmdma) mv_write_cached_reg(mv_ap_base(ap) + EDMA_UNKNOWN_RSVD_OFS, old, new); } +/* + * SOC chips have an issue whereby the HDD LEDs don't always blink + * during I/O when NCQ is enabled. Enabling a special "LED blink" mode + * of the SOC takes care of it, generating a steady blink rate when + * any drive on the chip is active. + * + * Unfortunately, the blink mode is a global hardware setting for the SOC, + * so we must use it whenever at least one port on the SOC has NCQ enabled. + * + * We turn "LED blink" off when NCQ is not in use anywhere, because the normal + * LED operation works then, and provides better (more accurate) feedback. + * + * Note that this code assumes that an SOC never has more than one HC onboard. + */ +static void mv_soc_led_blink_enable(struct ata_port *ap) +{ + struct ata_host *host = ap->host; + struct mv_host_priv *hpriv = host->private_data; + void __iomem *hc_mmio; + u32 led_ctrl; + + if (hpriv->hp_flags & MV_HP_QUIRK_LED_BLINK_EN) + return; + hpriv->hp_flags |= MV_HP_QUIRK_LED_BLINK_EN; + hc_mmio = mv_hc_base_from_port(mv_host_base(host), ap->port_no); + led_ctrl = readl(hc_mmio + SOC_LED_CTRL_OFS); + writel(led_ctrl | SOC_LED_CTRL_BLINK, hc_mmio + SOC_LED_CTRL_OFS); +} + +static void mv_soc_led_blink_disable(struct ata_port *ap) +{ + struct ata_host *host = ap->host; + struct mv_host_priv *hpriv = host->private_data; + void __iomem *hc_mmio; + u32 led_ctrl; + unsigned int port; + + if (!(hpriv->hp_flags & MV_HP_QUIRK_LED_BLINK_EN)) + return; + + /* disable led-blink only if no ports are using NCQ */ + for (port = 0; port < hpriv->n_ports; port++) { + struct ata_port *this_ap = host->ports[port]; + struct mv_port_priv *pp = this_ap->private_data; + + if (pp->pp_flags & MV_PP_FLAG_NCQ_EN) + return; + } + + hpriv->hp_flags &= ~MV_HP_QUIRK_LED_BLINK_EN; + hc_mmio = mv_hc_base_from_port(mv_host_base(host), ap->port_no); + led_ctrl = readl(hc_mmio + SOC_LED_CTRL_OFS); + writel(led_ctrl & ~SOC_LED_CTRL_BLINK, hc_mmio + SOC_LED_CTRL_OFS); +} + static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) { u32 cfg; @@ -1451,6 +1512,13 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq, int want_edma) if (hpriv->hp_flags & MV_HP_CUT_THROUGH) cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */ mv_bmdma_enable_iie(ap, !want_edma); + + if (IS_SOC(hpriv)) { + if (want_ncq) + mv_soc_led_blink_enable(ap); + else + mv_soc_led_blink_disable(ap); + } } if (want_ncq) { -- cgit v1.2.3 From e18086d69cb5bb864749a0637f6ac573aa89d5ea Mon Sep 17 00:00:00 2001 From: Mark Lord Date: Thu, 19 Mar 2009 13:32:21 -0400 Subject: [libata] More robust parsing for IDENTIFY DEVICE multi_count field Make libata more robust when parsing the multi_count field from a drive's identify data. This prevents us from attempting to use dubious multi_count values ad infinitum. Reset dev->multi_count to zero and reprobe it each time through this routine, as it can change on device reset. Also ensure that the reported "maximum" value is valid and is a power of two, and that the reported "count" value is valid and also a power of two. And that the "count" value is not greater than the "maximum" value. Signed-off-by: Mark Lord Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index d4a7b8a96ec..e7ea77cf606 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -2389,6 +2390,7 @@ int ata_dev_configure(struct ata_device *dev) dev->cylinders = 0; dev->heads = 0; dev->sectors = 0; + dev->multi_count = 0; /* * common ATA, ATAPI feature tests @@ -2426,8 +2428,15 @@ int ata_dev_configure(struct ata_device *dev) dev->n_sectors = ata_id_n_sectors(id); - if (dev->id[59] & 0x100) - dev->multi_count = dev->id[59] & 0xff; + /* get current R/W Multiple count setting */ + if ((dev->id[47] >> 8) == 0x80 && (dev->id[59] & 0x100)) { + unsigned int max = dev->id[47] & 0xff; + unsigned int cnt = dev->id[59] & 0xff; + /* only recognize/allow powers of two here */ + if (is_power_of_2(max) && is_power_of_2(cnt)) + if (cnt <= max) + dev->multi_count = cnt; + } if (ata_id_has_lba(id)) { const char *lba_desc; -- cgit v1.2.3 From 208f2a886a2f6cf329c9fcbf8d29a0dd245cc763 Mon Sep 17 00:00:00 2001 From: David Milburn Date: Fri, 20 Mar 2009 14:14:23 -0500 Subject: [libata] ahci: correct enclosure LED state save ahci_transmit_led_message saves off the led_state with a value that includes the port number OR'd in, this incorrect value maybe reported back in ahci_led_store. For instance, if you turn off all the leds for port 1 and cat the value back it will report 1 instead of 0. # echo 0 > /sys/class/scsi_host/host1/em_message # cat /sys/class/scsi_host/host1/em_message 1 Signed-off-by: David Milburn Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ec2922ad2dc..788bba2b1e1 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -1348,7 +1348,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, writel(message[1], mmio + hpriv->em_loc+4); /* save off new led state for port/slot */ - emp->led_state = message[1]; + emp->led_state = state; /* * tell hardware to transmit the message -- cgit v1.2.3 From 140d6fed71a659f39f0b130b6ac8f8d28600bf60 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Mar 2009 10:21:49 +0000 Subject: pata_artop: Serializing support Enable both ports on the 6210 and serialize them Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_artop.c | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_artop.c b/drivers/ata/pata_artop.c index 07c7fae6da1..d332cfdb0f3 100644 --- a/drivers/ata/pata_artop.c +++ b/drivers/ata/pata_artop.c @@ -12,7 +12,6 @@ * performance Alessandro Zummo * * TODO - * 850 serialization once the core supports it * Investigate no_dsc on 850R * Clock detect */ @@ -29,7 +28,7 @@ #include #define DRV_NAME "pata_artop" -#define DRV_VERSION "0.4.4" +#define DRV_VERSION "0.4.5" /* * The ARTOP has 33 Mhz and "over clocked" timing tables. Until we @@ -283,6 +282,31 @@ static void artop6260_set_dmamode (struct ata_port *ap, struct ata_device *adev) pci_write_config_byte(pdev, 0x44 + ap->port_no, ultra); } +/** + * artop_6210_qc_defer - implement serialization + * @qc: command + * + * Issue commands per host on this chip. + */ + +static int artop6210_qc_defer(struct ata_queued_cmd *qc) +{ + struct ata_host *host = qc->ap->host; + struct ata_port *alt = host->ports[1 ^ qc->ap->port_no]; + int rc; + + /* First apply the usual rules */ + rc = ata_std_qc_defer(qc); + if (rc != 0) + return rc; + + /* Now apply serialization rules. Only allow a command if the + other channel state machine is idle */ + if (alt && alt->qc_active) + return ATA_DEFER_PORT; + return 0; +} + static struct scsi_host_template artop_sht = { ATA_BMDMA_SHT(DRV_NAME), }; @@ -293,6 +317,7 @@ static struct ata_port_operations artop6210_ops = { .set_piomode = artop6210_set_piomode, .set_dmamode = artop6210_set_dmamode, .prereset = artop6210_pre_reset, + .qc_defer = artop6210_qc_defer, }; static struct ata_port_operations artop6260_ops = { @@ -362,12 +387,8 @@ static int artop_init_one (struct pci_dev *pdev, const struct pci_device_id *id) if (id->driver_data == 0) { /* 6210 variant */ ppi[0] = &info_6210; - ppi[1] = &ata_dummy_port_info; /* BIOS may have left us in UDMA, clear it before libata probe */ pci_write_config_byte(pdev, 0x54, 0); - /* For the moment (also lacks dsc) */ - printk(KERN_WARNING "ARTOP 6210 requires serialize functionality not yet supported by libata.\n"); - printk(KERN_WARNING "Secondary ATA ports will not be activated.\n"); } else if (id->driver_data == 1) /* 6260 */ ppi[0] = &info_626x; -- cgit v1.2.3 From c0f2ee34a5a0b79fd98d965ad8ae765d4639bfa5 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Mar 2009 10:22:25 +0000 Subject: pata_sc1200: Activate secondary channel Implement serialize and turn on slave channel Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/pata_sc1200.c | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index 36a0c359329..f49814d6fd2 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -2,7 +2,6 @@ * New ATA layer SC1200 driver Alan Cox * * TODO: Mode selection filtering - * TODO: Can't enable second channel until ATA core has serialize * TODO: Needs custom DMA cleanup code * * Based very heavily on @@ -178,6 +177,31 @@ static unsigned int sc1200_qc_issue(struct ata_queued_cmd *qc) return ata_sff_qc_issue(qc); } +/** + * sc1200_qc_defer - implement serialization + * @qc: command + * + * Serialize command issue on this controller. + */ + +static int sc1200_qc_defer(struct ata_queued_cmd *qc) +{ + struct ata_host *host = qc->ap->host; + struct ata_port *alt = host->ports[1 ^ qc->ap->port_no]; + int rc; + + /* First apply the usual rules */ + rc = ata_std_qc_defer(qc); + if (rc != 0) + return rc; + + /* Now apply serialization rules. Only allow a command if the + other channel state machine is idle */ + if (alt && alt->qc_active) + return ATA_DEFER_PORT; + return 0; +} + static struct scsi_host_template sc1200_sht = { ATA_BMDMA_SHT(DRV_NAME), .sg_tablesize = LIBATA_DUMB_MAX_PRD, @@ -187,6 +211,7 @@ static struct ata_port_operations sc1200_port_ops = { .inherits = &ata_bmdma_port_ops, .qc_prep = ata_sff_dumb_qc_prep, .qc_issue = sc1200_qc_issue, + .qc_defer = sc1200_qc_defer, .cable_detect = ata_cable_40wire, .set_piomode = sc1200_set_piomode, .set_dmamode = sc1200_set_dmamode, @@ -211,7 +236,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id) .port_ops = &sc1200_port_ops }; /* Can't enable port 2 yet, see top comments */ - const struct ata_port_info *ppi[] = { &info, &ata_dummy_port_info }; + const struct ata_port_info *ppi[] = { &info, }; return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL); } -- cgit v1.2.3 From 3d47aa8e7e7b2aa09256590388aa8dddc79280f9 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Mar 2009 10:23:19 +0000 Subject: [libata] Drain data on errors If the device is signalling that there is data to drain after an error we should read the bytes out and throw them away. Without this some devices and controllers get wedged and don't recover. Based on earlier work by Mark Lord Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-sff.c | 45 +++++++++++++++++++++++++++++++++++++++++++-- drivers/ata/pata_pcmcia.c | 34 +++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index f93dc029dfd..9a10cb055ac 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -52,6 +52,7 @@ const struct ata_port_operations ata_sff_port_ops = { .softreset = ata_sff_softreset, .hardreset = sata_sff_hardreset, .postreset = ata_sff_postreset, + .drain_fifo = ata_sff_drain_fifo, .error_handler = ata_sff_error_handler, .post_internal_cmd = ata_sff_post_internal_cmd, @@ -2198,6 +2199,39 @@ void ata_sff_postreset(struct ata_link *link, unsigned int *classes) } EXPORT_SYMBOL_GPL(ata_sff_postreset); +/** + * ata_sff_drain_fifo - Stock FIFO drain logic for SFF controllers + * @qc: command + * + * Drain the FIFO and device of any stuck data following a command + * failing to complete. In some cases this is neccessary before a + * reset will recover the device. + * + */ + +void ata_sff_drain_fifo(struct ata_queued_cmd *qc) +{ + int count; + struct ata_port *ap; + + /* We only need to flush incoming data when a command was running */ + if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE) + return; + + ap = qc->ap; + /* Drain up to 64K of data before we give up this recovery method */ + for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ) + && count < 32768; count++) + ioread16(ap->ioaddr.data_addr); + + /* Can become DEBUG later */ + if (count) + ata_port_printk(ap, KERN_DEBUG, + "drained %d bytes to clear DRQ.\n", count); + +} +EXPORT_SYMBOL_GPL(ata_sff_drain_fifo); + /** * ata_sff_error_handler - Stock error handler for BMDMA controller * @ap: port to handle error for @@ -2239,7 +2273,8 @@ void ata_sff_error_handler(struct ata_port *ap) * really a timeout event, adjust error mask and * cancel frozen state. */ - if (qc->err_mask == AC_ERR_TIMEOUT && (host_stat & ATA_DMA_ERR)) { + if (qc->err_mask == AC_ERR_TIMEOUT + && (host_stat & ATA_DMA_ERR)) { qc->err_mask = AC_ERR_HOST_BUS; thaw = 1; } @@ -2250,6 +2285,13 @@ void ata_sff_error_handler(struct ata_port *ap) ata_sff_sync(ap); /* FIXME: We don't need this */ ap->ops->sff_check_status(ap); ap->ops->sff_irq_clear(ap); + /* We *MUST* do FIFO draining before we issue a reset as several + * devices helpfully clear their internal state and will lock solid + * if we touch the data port post reset. Pass qc in case anyone wants + * to do different PIO/DMA recovery or has per command fixups + */ + if (ap->ops->drain_fifo) + ap->ops->drain_fifo(qc); spin_unlock_irqrestore(ap->lock, flags); @@ -2959,4 +3001,3 @@ out: EXPORT_SYMBOL_GPL(ata_pci_sff_init_one); #endif /* CONFIG_PCI */ - diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index a5cbcc280b2..f4d009ed50a 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c @@ -42,7 +42,7 @@ #define DRV_NAME "pata_pcmcia" -#define DRV_VERSION "0.3.3" +#define DRV_VERSION "0.3.5" /* * Private data structure to glue stuff together @@ -126,6 +126,37 @@ static unsigned int ata_data_xfer_8bit(struct ata_device *dev, return buflen; } +/** + * pcmcia_8bit_drain_fifo - Stock FIFO drain logic for SFF controllers + * @qc: command + * + * Drain the FIFO and device of any stuck data following a command + * failing to complete. In some cases this is neccessary before a + * reset will recover the device. + * + */ + +void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc) +{ + int count; + struct ata_port *ap; + + /* We only need to flush incoming data when a command was running */ + if (qc == NULL || qc->dma_dir == DMA_TO_DEVICE) + return; + + ap = qc->ap; + + /* Drain up to 64K of data before we give up this recovery method */ + for (count = 0; (ap->ops->sff_check_status(ap) & ATA_DRQ) + && count++ < 65536;) + ioread8(ap->ioaddr.data_addr); + + if (count) + ata_port_printk(ap, KERN_WARNING, "drained %d bytes to clear DRQ.\n", + count); + +} static struct scsi_host_template pcmcia_sht = { ATA_PIO_SHT(DRV_NAME), @@ -143,6 +174,7 @@ static struct ata_port_operations pcmcia_8bit_port_ops = { .sff_data_xfer = ata_data_xfer_8bit, .cable_detect = ata_cable_40wire, .set_mode = pcmcia_set_mode_8bit, + .drain_fifo = pcmcia_8bit_drain_fifo, }; #define CS_CHECK(fn, ret) \ -- cgit v1.2.3 From c96f1732e25362d10ee7bcac1df8412a2e6b7d23 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 24 Mar 2009 10:23:46 +0000 Subject: [libata] Improve timeout handling On a timeout call a device specific handler early in the recovery so that we can complete and process successful commands which timed out due to IRQ loss or the like rather more elegantly. [Revised to exclude the timeout handling on a few devices that inherit from SFF but are not SFF enough to use the default timeout handler] Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 19 +++++++++++++++++-- drivers/ata/libata-sff.c | 46 +++++++++++++++++++++++++++++++++++++++++++++- drivers/ata/pata_isapnp.c | 12 ++++++++++-- drivers/ata/pdc_adma.c | 2 ++ drivers/ata/sata_mv.c | 2 ++ drivers/ata/sata_nv.c | 1 + drivers/ata/sata_promise.c | 2 ++ drivers/ata/sata_qstor.c | 1 + drivers/ata/sata_vsc.c | 3 +++ 9 files changed, 83 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index ea890911d4f..01831312c36 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -547,7 +547,7 @@ void ata_scsi_error(struct Scsi_Host *host) /* For new EH, all qcs are finished in one of three ways - * normal completion, error completion, and SCSI timeout. - * Both cmpletions can race against SCSI timeout. When normal + * Both completions can race against SCSI timeout. When normal * completion wins, the qc never reaches EH. When error * completion wins, the qc has ATA_QCFLAG_FAILED set. * @@ -562,7 +562,19 @@ void ata_scsi_error(struct Scsi_Host *host) int nr_timedout = 0; spin_lock_irqsave(ap->lock, flags); - + + /* This must occur under the ap->lock as we don't want + a polled recovery to race the real interrupt handler + + The lost_interrupt handler checks for any completed but + non-notified command and completes much like an IRQ handler. + + We then fall into the error recovery code which will treat + this as if normal completion won the race */ + + if (ap->ops->lost_interrupt) + ap->ops->lost_interrupt(ap); + list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) { struct ata_queued_cmd *qc; @@ -606,6 +618,9 @@ void ata_scsi_error(struct Scsi_Host *host) ap->eh_tries = ATA_EH_MAX_TRIES; } else spin_unlock_wait(ap->lock); + + /* If we timed raced normal completion and there is nothing to + recover nr_timedout == 0 why exactly are we doing error recovery ? */ repeat: /* invoke error handler */ diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 9a10cb055ac..8332e97a9de 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -65,6 +65,8 @@ const struct ata_port_operations ata_sff_port_ops = { .sff_irq_on = ata_sff_irq_on, .sff_irq_clear = ata_sff_irq_clear, + .lost_interrupt = ata_sff_lost_interrupt, + .port_start = ata_sff_port_start, }; EXPORT_SYMBOL_GPL(ata_sff_port_ops); @@ -1647,7 +1649,7 @@ EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf); * RETURNS: * One if interrupt was handled, zero if not (shared irq). */ -inline unsigned int ata_sff_host_intr(struct ata_port *ap, +unsigned int ata_sff_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc) { struct ata_eh_info *ehi = &ap->link.eh_info; @@ -1775,6 +1777,48 @@ irqreturn_t ata_sff_interrupt(int irq, void *dev_instance) } EXPORT_SYMBOL_GPL(ata_sff_interrupt); +/** + * ata_sff_lost_interrupt - Check for an apparent lost interrupt + * @ap: port that appears to have timed out + * + * Called from the libata error handlers when the core code suspects + * an interrupt has been lost. If it has complete anything we can and + * then return. Interface must support altstatus for this faster + * recovery to occur. + * + * Locking: + * Caller holds host lock + */ + +void ata_sff_lost_interrupt(struct ata_port *ap) +{ + u8 status; + struct ata_queued_cmd *qc; + + /* Only one outstanding command per SFF channel */ + qc = ata_qc_from_tag(ap, ap->link.active_tag); + /* Check we have a live one.. */ + if (qc == NULL || !(qc->flags & ATA_QCFLAG_ACTIVE)) + return; + /* We cannot lose an interrupt on a polled command */ + if (qc->tf.flags & ATA_TFLAG_POLLING) + return; + /* See if the controller thinks it is still busy - if so the command + isn't a lost IRQ but is still in progress */ + status = ata_sff_altstatus(ap); + if (status & ATA_BUSY) + return; + + /* There was a command running, we are no longer busy and we have + no interrupt. */ + ata_port_printk(ap, KERN_WARNING, "lost interrupt (Status 0x%x)\n", + status); + /* Run the host interrupt logic as if the interrupt had not been + lost */ + ata_sff_host_intr(ap, qc); +} +EXPORT_SYMBOL_GPL(ata_sff_lost_interrupt); + /** * ata_sff_freeze - Freeze SFF controller port * @ap: port to freeze diff --git a/drivers/ata/pata_isapnp.c b/drivers/ata/pata_isapnp.c index afa8f704271..4bceb8803a1 100644 --- a/drivers/ata/pata_isapnp.c +++ b/drivers/ata/pata_isapnp.c @@ -17,7 +17,7 @@ #include #define DRV_NAME "pata_isapnp" -#define DRV_VERSION "0.2.2" +#define DRV_VERSION "0.2.5" static struct scsi_host_template isapnp_sht = { ATA_PIO_SHT(DRV_NAME), @@ -28,6 +28,13 @@ static struct ata_port_operations isapnp_port_ops = { .cable_detect = ata_cable_40wire, }; +static struct ata_port_operations isapnp_noalt_port_ops = { + .inherits = &ata_sff_port_ops, + .cable_detect = ata_cable_40wire, + /* No altstatus so we don't want to use the lost interrupt poll */ + .lost_interrupt = ATA_OP_NULL, +}; + /** * isapnp_init_one - attach an isapnp interface * @idev: PnP device @@ -65,7 +72,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev ap = host->ports[0]; - ap->ops = &isapnp_port_ops; + ap->ops = &isapnp_noalt_port_ops; ap->pio_mask = ATA_PIO0; ap->flags |= ATA_FLAG_SLAVE_POSS; @@ -76,6 +83,7 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev pnp_port_start(idev, 1), 1); ap->ioaddr.altstatus_addr = ctl_addr; ap->ioaddr.ctl_addr = ctl_addr; + ap->ops = &isapnp_port_ops; } ata_sff_std_ports(&ap->ioaddr); diff --git a/drivers/ata/pdc_adma.c b/drivers/ata/pdc_adma.c index c509c206a45..39588178d02 100644 --- a/drivers/ata/pdc_adma.c +++ b/drivers/ata/pdc_adma.c @@ -148,6 +148,8 @@ static struct scsi_host_template adma_ata_sht = { static struct ata_port_operations adma_ata_ops = { .inherits = &ata_sff_port_ops, + .lost_interrupt = ATA_OP_NULL, + .check_atapi_dma = adma_check_atapi_dma, .qc_prep = adma_qc_prep, .qc_issue = adma_qc_issue, diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index 8a751054c8a..a377226b81c 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -646,6 +646,8 @@ static struct scsi_host_template mv6_sht = { static struct ata_port_operations mv5_ops = { .inherits = &ata_sff_port_ops, + .lost_interrupt = ATA_OP_NULL, + .qc_defer = mv_qc_defer, .qc_prep = mv_qc_prep, .qc_issue = mv_qc_issue, diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 2f523f8c27f..6cda12ba812 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c @@ -408,6 +408,7 @@ static struct scsi_host_template nv_swncq_sht = { static struct ata_port_operations nv_common_ops = { .inherits = &ata_bmdma_port_ops, + .lost_interrupt = ATA_OP_NULL, .scr_read = nv_scr_read, .scr_write = nv_scr_write, }; diff --git a/drivers/ata/sata_promise.c b/drivers/ata/sata_promise.c index 3ad2b886363..b1fd7d62071 100644 --- a/drivers/ata/sata_promise.c +++ b/drivers/ata/sata_promise.c @@ -176,7 +176,9 @@ static const struct ata_port_operations pdc_common_ops = { .check_atapi_dma = pdc_check_atapi_dma, .qc_prep = pdc_qc_prep, .qc_issue = pdc_qc_issue, + .sff_irq_clear = pdc_irq_clear, + .lost_interrupt = ATA_OP_NULL, .post_internal_cmd = pdc_post_internal_cmd, .error_handler = pdc_error_handler, diff --git a/drivers/ata/sata_qstor.c b/drivers/ata/sata_qstor.c index 7112d89fd9f..c3936d35cda 100644 --- a/drivers/ata/sata_qstor.c +++ b/drivers/ata/sata_qstor.c @@ -147,6 +147,7 @@ static struct ata_port_operations qs_ata_ops = { .softreset = ATA_OP_NULL, .error_handler = qs_error_handler, .post_internal_cmd = ATA_OP_NULL, + .lost_interrupt = ATA_OP_NULL, .scr_read = qs_scr_read, .scr_write = qs_scr_write, diff --git a/drivers/ata/sata_vsc.c b/drivers/ata/sata_vsc.c index ef211f333d7..ed70bd28fa2 100644 --- a/drivers/ata/sata_vsc.c +++ b/drivers/ata/sata_vsc.c @@ -308,6 +308,9 @@ static struct scsi_host_template vsc_sata_sht = { static struct ata_port_operations vsc_sata_ops = { .inherits = &ata_bmdma_port_ops, + /* The IRQ handling is not quite standard SFF behaviour so we + cannot use the default lost interrupt handler */ + .lost_interrupt = ATA_OP_NULL, .sff_tf_load = vsc_sata_tf_load, .sff_tf_read = vsc_sata_tf_read, .freeze = vsc_freeze, -- cgit v1.2.3