From 9bf8a1a79d549a0cf3b26c88d1ac8cdf07deafee Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 23 Jun 2008 20:33:06 +0200 Subject: pci: debug extra pci resources range Signed-off-by: Ingo Molnar --- drivers/pci/probe.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 3706ce7..27cdbb0 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -275,6 +275,7 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) } res->start = l64 & PCI_BASE_ADDRESS_MEM_MASK; res->end = res->start + sz64; + printk(KERN_INFO "PCI: %s reg %x 64bit mmio: [%llx, %llx]\n", pci_name(dev), reg, res->start, res->end); #else if (sz64 > 0x100000000ULL) { printk(KERN_ERR "PCI: Unable to handle 64-bit " @@ -290,6 +291,8 @@ static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom) res->end = sz; } #endif + } else { + printk(KERN_INFO "PCI: %s reg %x %s: [%llx, %llx]\n", pci_name(dev), reg, (res->flags & IORESOURCE_IO)? "io port":"32bit mmio", res->start, res->end); } } if (rom) { @@ -357,6 +360,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->start = base; if (!res->end) res->end = limit + 0xfff; + printk(KERN_INFO "PCI: bridge %s io port: [%llx, %llx]\n", pci_name(dev), res->start, res->end); } res = child->resource[1]; @@ -368,6 +372,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM; res->start = base; res->end = limit + 0xfffff; + printk(KERN_INFO "PCI: bridge %s 32bit mmio: [%llx, %llx]\n", pci_name(dev), res->start, res->end); } res = child->resource[2]; @@ -402,6 +407,7 @@ void __devinit pci_read_bridge_bases(struct pci_bus *child) res->flags = (mem_base_lo & PCI_MEMORY_RANGE_TYPE_MASK) | IORESOURCE_MEM | IORESOURCE_PREFETCH; res->start = base; res->end = limit + 0xfffff; + printk(KERN_INFO "PCI: bridge %s %sbit mmio pref: [%llx, %llx]\n", pci_name(dev), (res->flags & PCI_PREF_RANGE_TYPE_64)?"64":"32",res->start, res->end); } } -- cgit v1.1 From 76fbc263ff7e42ce8b21b8aee176e3c74b45f81a Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Mon, 23 Jun 2008 20:33:06 +0200 Subject: pci: debug extra pci bus resources Signed-off-by: Ingo Molnar --- drivers/pci/setup-bus.c | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 8ddb918..c74a2bc 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c @@ -537,6 +537,36 @@ void __ref pci_bus_assign_resources(struct pci_bus *bus) } EXPORT_SYMBOL(pci_bus_assign_resources); +static void pci_bus_dump_res(struct pci_bus *bus) +{ + int i; + + for (i = 0; i < PCI_BUS_NUM_RESOURCES; i++) { + struct resource *res = bus->resource[i]; + if (!res) + continue; + + printk(KERN_INFO "bus: %02x index %x %s: [%llx, %llx]\n", bus->number, i, (res->flags & IORESOURCE_IO)? "io port":"mmio", res->start, res->end); + } +} + +static void pci_bus_dump_resources(struct pci_bus *bus) +{ + struct pci_bus *b; + struct pci_dev *dev; + + + pci_bus_dump_res(bus); + + list_for_each_entry(dev, &bus->devices, bus_list) { + b = dev->subordinate; + if (!b) + continue; + + pci_bus_dump_resources(b); + } +} + void __init pci_assign_unassigned_resources(void) { @@ -552,4 +582,9 @@ pci_assign_unassigned_resources(void) pci_bus_assign_resources(bus); pci_enable_bridges(bus); } + + /* dump the resource on buses */ + list_for_each_entry(bus, &pci_root_buses, node) { + pci_bus_dump_resources(bus); + } } -- cgit v1.1 From b6ce9ad05f782e6a00aed8432d9513dc394115ce Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 11 Aug 2008 14:53:49 +0900 Subject: input: migor_ts compile and detection fix The i2c layer got changed while the migor_ts driver was in the input tree waiting to get merged upstream. Fix current compile issue by using struct i2c_client member "name" instead of "driver_name". Also, add id_table to make sure the device gets properly detected. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/input/touchscreen/migor_ts.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/touchscreen/migor_ts.c b/drivers/input/touchscreen/migor_ts.c index c1cd99d..504ca11 100644 --- a/drivers/input/touchscreen/migor_ts.c +++ b/drivers/input/touchscreen/migor_ts.c @@ -173,7 +173,7 @@ static int migor_ts_probe(struct i2c_client *client, input_set_abs_params(input, ABS_X, 95, 955, 0, 0); input_set_abs_params(input, ABS_Y, 85, 935, 0, 0); - input->name = client->driver_name; + input->name = client->name; input->id.bustype = BUS_I2C; input->dev.parent = &client->dev; @@ -192,7 +192,7 @@ static int migor_ts_probe(struct i2c_client *client, goto err1; error = request_irq(priv->irq, migor_ts_isr, IRQF_TRIGGER_LOW, - client->driver_name, priv); + client->name, priv); if (error) { dev_err(&client->dev, "Unable to request touchscreen IRQ.\n"); goto err2; @@ -224,12 +224,19 @@ static int migor_ts_remove(struct i2c_client *client) return 0; } +static const struct i2c_device_id migor_ts_id[] = { + { "migor_ts", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, migor_ts); + static struct i2c_driver migor_ts_driver = { .driver = { .name = "migor_ts", }, .probe = migor_ts_probe, .remove = migor_ts_remove, + .id_table = migor_ts_id, }; static int __init migor_ts_init(void) -- cgit v1.1 From ce9c008c8bea25a974d9027b7c6602d535639899 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Mon, 11 Aug 2008 15:26:00 +0900 Subject: video: export sh_mobile_lcdc panel size Export the LCD panel size for sh_mobile_lcdc boards. This allows us to perform dpi and screen aspect ratio calculations in user space. Signed-off-by: Magnus Damm Signed-off-by: Paul Mundt --- drivers/video/sh_mobile_lcdcfb.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index f6ef6cc..4c32c06 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -595,6 +595,8 @@ static int __init sh_mobile_lcdc_probe(struct platform_device *pdev) info->fbops = &sh_mobile_lcdc_ops; info->var.xres = info->var.xres_virtual = cfg->lcd_cfg.xres; info->var.yres = info->var.yres_virtual = cfg->lcd_cfg.yres; + info->var.width = cfg->lcd_size_cfg.width; + info->var.height = cfg->lcd_size_cfg.height; info->var.activate = FB_ACTIVATE_NOW; error = sh_mobile_lcdc_set_bpp(&info->var, cfg->bpp); if (error) -- cgit v1.1 From fde9403a982218fa8a437f815e7aa0e583e2d6ed Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Mon, 11 Aug 2008 12:56:44 +0800 Subject: [netdrvr] remove unnecessary #include The drivers below do not use LINUX_VERSION_CODE nor KERNEL_VERSION. drivers/net/acenic.c drivers/net/bnx2x_link.c drivers/net/bnx2x_main.c drivers/net/cpmac.c drivers/net/gianfar_sysfs.c drivers/net/ipg.h drivers/net/ppp_mppe.c drivers/net/pppol2tp.c drivers/net/r6040.c drivers/net/sh_eth.c drivers/net/sky2.c drivers/net/tehuti.h drivers/net/typhoon.c This patch removes the said #include . Signed-off-by: Huang Weiyi Signed-off-by: Jeff Garzik --- drivers/net/acenic.c | 1 - drivers/net/bnx2x_link.c | 1 - drivers/net/bnx2x_main.c | 1 - drivers/net/cpmac.c | 1 - drivers/net/gianfar_sysfs.c | 1 - drivers/net/ipg.h | 2 -- drivers/net/ppp_mppe.c | 1 - drivers/net/pppol2tp.c | 1 - drivers/net/r6040.c | 1 - drivers/net/sh_eth.c | 1 - drivers/net/sky2.c | 1 - drivers/net/tehuti.h | 1 - drivers/net/typhoon.c | 1 - 13 files changed, 14 deletions(-) (limited to 'drivers') diff --git a/drivers/net/acenic.c b/drivers/net/acenic.c index e4483de..66de80b 100644 --- a/drivers/net/acenic.c +++ b/drivers/net/acenic.c @@ -52,7 +52,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index 8b92c6a..4ce7fe9 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "bnx2x_reg.h" #include "bnx2x_fw_defs.h" diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 3e7dc17..971576b 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index a7800e5..ec6b0af 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -26,7 +26,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/gianfar_sysfs.c b/drivers/net/gianfar_sysfs.c index 5116f68..782c201 100644 --- a/drivers/net/gianfar_sysfs.c +++ b/drivers/net/gianfar_sysfs.c @@ -33,7 +33,6 @@ #include #include -#include #include "gianfar.h" diff --git a/drivers/net/ipg.h b/drivers/net/ipg.h index e0e718ab..dd9318f 100644 --- a/drivers/net/ipg.h +++ b/drivers/net/ipg.h @@ -7,7 +7,6 @@ #ifndef __LINUX_IPG_H #define __LINUX_IPG_H -#include #include #include @@ -21,7 +20,6 @@ #include #include #include -#include #include /* diff --git a/drivers/net/ppp_mppe.c b/drivers/net/ppp_mppe.c index b35d794..88f03c9 100644 --- a/drivers/net/ppp_mppe.c +++ b/drivers/net/ppp_mppe.c @@ -46,7 +46,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/pppol2tp.c b/drivers/net/pppol2tp.c index f929882..ff175e8 100644 --- a/drivers/net/pppol2tp.c +++ b/drivers/net/pppol2tp.c @@ -61,7 +61,6 @@ */ #include -#include #include #include #include diff --git a/drivers/net/r6040.c b/drivers/net/r6040.c index 6531ff5..5d86281 100644 --- a/drivers/net/r6040.c +++ b/drivers/net/r6040.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c index 25e62cf..1c370e6 100644 --- a/drivers/net/sh_eth.c +++ b/drivers/net/sh_eth.c @@ -20,7 +20,6 @@ * the file called "COPYING". */ -#include #include #include #include diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 7d29edc..06dfc95 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -24,7 +24,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h index c66dfc9..7db48f1 100644 --- a/drivers/net/tehuti.h +++ b/drivers/net/tehuti.h @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 8549f11..734ce09 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -128,7 +128,6 @@ static const int multicast_filter_limit = 32; #include #include #include -#include #include #include "typhoon.h" -- cgit v1.1 From 2a54adc3ad771c997bfa721f098d2d4a6ef6ea38 Mon Sep 17 00:00:00 2001 From: Scott Wood Date: Tue, 12 Aug 2008 15:10:46 -0500 Subject: gianfar: Call gfar_halt_nodisable() from gfar_halt(). gfar_halt() was factored out into halting and disabling by commit d87eb12785c14de1586e3bad86ca2c0991300339, as the suspend() method only wants to do the former. However, the call to gfar_halt_nodisable() from gfar_halt() apparently got lost during the patch respin process. This adds it back. Signed-off-by: Scott Wood Signed-off-by: Jeff Garzik --- drivers/net/gianfar.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index ca6cf6e..999d691 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -134,9 +134,7 @@ static int gfar_process_frame(struct net_device *dev, struct sk_buff *skb, int l static void gfar_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp); void gfar_halt(struct net_device *dev); -#ifdef CONFIG_PM static void gfar_halt_nodisable(struct net_device *dev); -#endif void gfar_start(struct net_device *dev); static void gfar_clear_exact_match(struct net_device *dev); static void gfar_set_mac_for_addr(struct net_device *dev, int num, u8 *addr); @@ -631,7 +629,6 @@ static void init_registers(struct net_device *dev) } -#ifdef CONFIG_PM /* Halt the receive and transmit queues */ static void gfar_halt_nodisable(struct net_device *dev) { @@ -657,7 +654,6 @@ static void gfar_halt_nodisable(struct net_device *dev) cpu_relax(); } } -#endif /* Halt the receive and transmit queues */ void gfar_halt(struct net_device *dev) @@ -666,6 +662,8 @@ void gfar_halt(struct net_device *dev) struct gfar __iomem *regs = priv->regs; u32 tempval; + gfar_halt_nodisable(dev); + /* Disable Rx and Tx */ tempval = gfar_read(®s->maccfg1); tempval &= ~(MACCFG1_RX_EN | MACCFG1_TX_EN); -- cgit v1.1 From 7144decb0f482fcb2152c10c376f0574d563ca52 Mon Sep 17 00:00:00 2001 From: Mikael Pettersson Date: Wed, 13 Aug 2008 21:08:14 +0200 Subject: ixp4xx_eth: fix dma_mapping_error() compile errors The arm ixp4xx_eth driver doesn't compile in 2.6.27-rc1: CC [M] drivers/net/arm/ixp4xx_eth.o drivers/net/arm/ixp4xx_eth.c: In function 'eth_poll': drivers/net/arm/ixp4xx_eth.c:554: warning: passing argument 1 of 'dma_mapping_error' makes pointer from integer without a cast drivers/net/arm/ixp4xx_eth.c:554: error: too few arguments to function 'dma_mapping_error' drivers/net/arm/ixp4xx_eth.c: In function 'eth_xmit': drivers/net/arm/ixp4xx_eth.c:701: warning: passing argument 1 of 'dma_mapping_error' makes pointer from integer without a cast drivers/net/arm/ixp4xx_eth.c:701: error: too few arguments to function 'dma_mapping_error' drivers/net/arm/ixp4xx_eth.c: In function 'init_queues': drivers/net/arm/ixp4xx_eth.c:886: warning: passing argument 1 of 'dma_mapping_error' makes pointer from integer without a cast drivers/net/arm/ixp4xx_eth.c:886: error: too few arguments to function 'dma_mapping_error' make[3]: *** [drivers/net/arm/ixp4xx_eth.o] Error 1 make[2]: *** [drivers/net/arm] Error 2 make[1]: *** [drivers/net] Error 2 make: *** [drivers] Error 2 dma_mapping_error() changed in 2.6.27-rc1 to also take a device parameter, but nobody bothered updating ixp4xx_eth.c. Fixed by passing the appropriate device value in the dma_mapping_error() calls. Tested on an ixp425 box. Signed-off-by: Mikael Pettersson Acked-by: Krzysztof Halasa Signed-off-by: Jeff Garzik --- drivers/net/arm/ixp4xx_eth.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/arm/ixp4xx_eth.c b/drivers/net/arm/ixp4xx_eth.c index 9b777d9..7d5db2e 100644 --- a/drivers/net/arm/ixp4xx_eth.c +++ b/drivers/net/arm/ixp4xx_eth.c @@ -551,7 +551,7 @@ static int eth_poll(struct napi_struct *napi, int budget) if ((skb = netdev_alloc_skb(dev, RX_BUFF_SIZE))) { phys = dma_map_single(&dev->dev, skb->data, RX_BUFF_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(phys)) { + if (dma_mapping_error(&dev->dev, phys)) { dev_kfree_skb(skb); skb = NULL; } @@ -698,7 +698,7 @@ static int eth_xmit(struct sk_buff *skb, struct net_device *dev) #endif phys = dma_map_single(&dev->dev, mem, bytes, DMA_TO_DEVICE); - if (dma_mapping_error(phys)) { + if (dma_mapping_error(&dev->dev, phys)) { #ifdef __ARMEB__ dev_kfree_skb(skb); #else @@ -883,7 +883,7 @@ static int init_queues(struct port *port) desc->buf_len = MAX_MRU; desc->data = dma_map_single(&port->netdev->dev, data, RX_BUFF_SIZE, DMA_FROM_DEVICE); - if (dma_mapping_error(desc->data)) { + if (dma_mapping_error(&port->netdev->dev, desc->data)) { free_buffer(buff); return -EIO; } -- cgit v1.1 From 13b2738cbb4b59f695bd72bcaabd71317e7731d2 Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Wed, 13 Aug 2008 21:05:52 +0200 Subject: myri10ge: myri10ge_fw_name also overrides the rss firmware When myri10ge_fw_name is given, use it to override the rss firmware name as well. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index f1de38f..5d76cd0 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -3548,7 +3548,11 @@ static void myri10ge_probe_slices(struct myri10ge_priv *mgp) /* try to load the slice aware rss firmware */ old_fw = mgp->fw_name; - if (old_fw == myri10ge_fw_aligned) + if (myri10ge_fw_name != NULL) { + dev_info(&mgp->pdev->dev, "overriding rss firmware to %s\n", + myri10ge_fw_name); + mgp->fw_name = myri10ge_fw_name; + } else if (old_fw == myri10ge_fw_aligned) mgp->fw_name = myri10ge_fw_rss_aligned; else mgp->fw_name = myri10ge_fw_rss_unaligned; -- cgit v1.1 From 2726fcf0dab1a9b1fd04dea3837b2b0bb639c1bd Mon Sep 17 00:00:00 2001 From: Vegard Nossum Date: Wed, 6 Aug 2008 14:12:11 +0200 Subject: au1000_eth: use 'unsigned long' for irqflags The patch was generated using the Coccinelle semantic patch framework. Cc: Julia Lawall Cc: Alexey Dobriyan Cc: Jeff Garzik Signed-off-by: Vegard Nossum Signed-off-by: Jeff Garzik --- drivers/net/au1000_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c index cb8be49..5ee1b05 100644 --- a/drivers/net/au1000_eth.c +++ b/drivers/net/au1000_eth.c @@ -807,7 +807,7 @@ err_out: static int au1000_init(struct net_device *dev) { struct au1000_private *aup = (struct au1000_private *) dev->priv; - u32 flags; + unsigned long flags; int i; u32 control; -- cgit v1.1 From e484d5f5c8c64e2c4f110c59e9e964884107822a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 10 Aug 2008 19:30:28 +0200 Subject: sky2: Fix suspend/hibernation/shutdown regression with WOL enabled (rev. 2) On my test box with the Asus M3A32-MVP main board there is a regression from 2.6.26 related to suspend, hibernation and shutdown. Namely, if Wake-on-LAN is enabled with 'ethtool -s eth0 wol g', the box hangs solid during all of these operations, while executing either sky2_suspend(), or sky2_shutdown(). This patch fixes it for me. Signed-off-by: Rafael J. Wysocki Signed-off-by: Jeff Garzik --- drivers/net/sky2.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 06dfc95..e24b25c 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -665,11 +665,16 @@ static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port) if (hw->chip_id != CHIP_ID_YUKON_EC) { if (hw->chip_id == CHIP_ID_YUKON_EC_U) { - ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); + /* select page 2 to access MAC control register */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); + ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); /* enable Power Down */ ctrl |= PHY_M_PC_POW_D_ENA; gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); + + /* set page register back to 0 */ + gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); } /* set IEEE compatible Power Down Mode (dev. #4.99) */ -- cgit v1.1 From 0d63bea2c20651588e5e631799a961468a735eb9 Mon Sep 17 00:00:00 2001 From: Robert Fitzsimons Date: Sat, 9 Aug 2008 17:54:02 +0100 Subject: tlan: Fix two regressions introduced by 64bit conversion. Two regressions were introduced by the recent tlan: 64bit conversion commit (93e16847c9db0093065c98063cfc639cdfccf19a). The first in TLan_GetSKB caused a NULL pointer dereference. With the second causing the link to fail to come up. Signed-off-by: Robert Fitzsimons Signed-off-by: Jeff Garzik --- drivers/net/tlan.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tlan.c b/drivers/net/tlan.c index 85246ed..ec871f6 100644 --- a/drivers/net/tlan.c +++ b/drivers/net/tlan.c @@ -360,8 +360,8 @@ TLan_GetSKB( const struct tlan_list_tag *tag) { unsigned long addr; - addr = tag->buffer[8].address; - addr |= (tag->buffer[9].address << 16) << 16; + addr = tag->buffer[9].address; + addr |= (tag->buffer[8].address << 16) << 16; return (struct sk_buff *) addr; } @@ -1984,7 +1984,6 @@ static void TLan_ResetLists( struct net_device *dev ) TLanList *list; dma_addr_t list_phys; struct sk_buff *skb; - void *t = NULL; priv->txHead = 0; priv->txTail = 0; @@ -2022,7 +2021,8 @@ static void TLan_ResetLists( struct net_device *dev ) } skb_reserve( skb, NET_IP_ALIGN ); - list->buffer[0].address = pci_map_single(priv->pciDev, t, + list->buffer[0].address = pci_map_single(priv->pciDev, + skb->data, TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE); TLan_StoreSKB(list, skb); -- cgit v1.1 From 56e1f82968af79f70902008098a4687198142ce7 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Aug 2008 18:35:44 -0700 Subject: e1000e: Return 1 instead of a non-zero value for link up indication A number of users have mentioned they have tools that rely on a link-up indication having a return value of 1 rather than a non-zero value. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/e1000e/ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index cf9679f..e21c9e0 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c @@ -177,7 +177,7 @@ static u32 e1000_get_link(struct net_device *netdev) u32 status; status = er32(STATUS); - return (status & E1000_STATUS_LU); + return (status & E1000_STATUS_LU) ? 1 : 0; } static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u16 spddplx) -- cgit v1.1 From 2d06cad1a5ceb3b04dc9547e261ad4fcebf7433d Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Aug 2008 18:35:51 -0700 Subject: e1000e: Set InterruptThrottleRate to default when invalid value used During module load, seting the InterruptThrottleRate parameter to an invalid value would result in the itr/itr_setting pair being set to unexpected values which would result in poor performance. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/e1000e/param.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index 8effc31..b0499f2 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -327,11 +327,26 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) e1000_validate_option(&adapter->itr, &opt, adapter); /* - * save the setting, because the dynamic bits - * change itr. clear the lower two bits - * because they are used as control + * Save the setting, because the dynamic bits + * change itr. */ - adapter->itr_setting = adapter->itr & ~3; + if (e1000_validate_option(&adapter->itr, &opt, + adapter) && + (adapter->itr == 3)) { + /* + * In case of invalid user value, + * default to conservative mode. + */ + adapter->itr_setting = adapter->itr; + adapter->itr = 20000; + } else { + /* + * Clear the lower two bits because + * they are used as control. + */ + adapter->itr_setting = + adapter->itr & ~3; + } break; } } else { -- cgit v1.1 From 808ff676c46d8e259c2cb38579f94f8e6ae38009 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Aug 2008 18:35:56 -0700 Subject: e1000e: Use skb_copy_to_linear_data_offset introduced in 2.6.22 The e1000e driver was based on a version of e1000 prior to acme's introduction of skb_copy_to_linear_data_offset, and was submitted after acme went through and coverted all the drivers to use it. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/e1000e/netdev.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 05b0b2f..efa94450 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -510,9 +510,12 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, netdev_alloc_skb(netdev, length + NET_IP_ALIGN); if (new_skb) { skb_reserve(new_skb, NET_IP_ALIGN); - memcpy(new_skb->data - NET_IP_ALIGN, - skb->data - NET_IP_ALIGN, - length + NET_IP_ALIGN); + skb_copy_to_linear_data_offset(new_skb, + -NET_IP_ALIGN, + (skb->data - + NET_IP_ALIGN), + (length + + NET_IP_ALIGN)); /* save the skb in buffer_info as good */ buffer_info->skb = skb; skb = new_skb; -- cgit v1.1 From 10f1b492135620a87970cad9f80439249dcce299 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Aug 2008 18:36:01 -0700 Subject: e1000e: Increase Tx timeout factor for 10Mbps Prevent Tx hangs from happening on 10Mb flood ping by increasing the timeout factor. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/e1000e/netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index efa94450..4573c7b 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3058,7 +3058,7 @@ static void e1000_watchdog_task(struct work_struct *work) case SPEED_10: txb2b = 0; netdev->tx_queue_len = 10; - adapter->tx_timeout_factor = 14; + adapter->tx_timeout_factor = 16; break; case SPEED_100: txb2b = 0; -- cgit v1.1 From d53f706da808e6d93dc60b1910233a309009939f Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Aug 2008 18:36:06 -0700 Subject: e1000e: increase minimum frame size allowed Setting an MTU value below 68 was disabling the network connection and would not reconnect until the driver was reloaded. Prevent changing the MTU to anything below 68. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/e1000e/netdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 4573c7b..b8b26cf 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -3724,7 +3724,7 @@ static int e1000_change_mtu(struct net_device *netdev, int new_mtu) struct e1000_adapter *adapter = netdev_priv(netdev); int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || + if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) || (max_frame > MAX_JUMBO_FRAME_SIZE)) { e_err("Invalid MTU setting\n"); return -EINVAL; -- cgit v1.1 From f8d59f7826aa73c5e7682fbed6db38020635d466 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Aug 2008 18:36:11 -0700 Subject: e1000e: test for unusable MSI support Some systems do not like 82571/2 use of 16-bit MSI messages and some other systems claim to support MSI, but neither really works. Setup a test MSI handler to detect whether or not MSI is working properly, and if not, fallback to legacy INTx interrupts. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/e1000e/defines.h | 2 +- drivers/net/e1000e/e1000.h | 1 + drivers/net/e1000e/netdev.c | 172 ++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 164 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index f823b8b..14b0e6c 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -389,7 +389,7 @@ /* Interrupt Cause Set */ #define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ +#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ #define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ /* Transmit Descriptor Control */ diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index cf57050..ac4e506 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h @@ -326,6 +326,7 @@ struct e1000_info { #define FLAG_RX_CSUM_ENABLED (1 << 28) #define FLAG_TSO_FORCE (1 << 29) #define FLAG_RX_RESTART_NOW (1 << 30) +#define FLAG_MSI_TEST_FAILED (1 << 31) #define E1000_RX_DESC_PS(R, i) \ (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index b8b26cf..d266510 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c @@ -1236,26 +1236,36 @@ static irqreturn_t e1000_intr(int irq, void *data) return IRQ_HANDLED; } +/** + * e1000_request_irq - initialize interrupts + * + * Attempts to configure interrupts using the best available + * capabilities of the hardware and kernel. + **/ static int e1000_request_irq(struct e1000_adapter *adapter) { struct net_device *netdev = adapter->netdev; - irq_handler_t handler = e1000_intr; int irq_flags = IRQF_SHARED; int err; - if (!pci_enable_msi(adapter->pdev)) { - adapter->flags |= FLAG_MSI_ENABLED; - handler = e1000_intr_msi; - irq_flags = 0; + if (!(adapter->flags & FLAG_MSI_TEST_FAILED)) { + err = pci_enable_msi(adapter->pdev); + if (!err) { + adapter->flags |= FLAG_MSI_ENABLED; + irq_flags = 0; + } } - err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name, - netdev); + err = request_irq(adapter->pdev->irq, + ((adapter->flags & FLAG_MSI_ENABLED) ? + &e1000_intr_msi : &e1000_intr), + irq_flags, netdev->name, netdev); if (err) { - e_err("Unable to allocate %s interrupt (return: %d)\n", - adapter->flags & FLAG_MSI_ENABLED ? "MSI":"INTx", err); - if (adapter->flags & FLAG_MSI_ENABLED) + if (adapter->flags & FLAG_MSI_ENABLED) { pci_disable_msi(adapter->pdev); + adapter->flags &= ~FLAG_MSI_ENABLED; + } + e_err("Unable to allocate interrupt, Error: %d\n", err); } return err; @@ -2595,6 +2605,135 @@ err: } /** + * e1000_intr_msi_test - Interrupt Handler + * @irq: interrupt number + * @data: pointer to a network interface device structure + **/ +static irqreturn_t e1000_intr_msi_test(int irq, void *data) +{ + struct net_device *netdev = data; + struct e1000_adapter *adapter = netdev_priv(netdev); + struct e1000_hw *hw = &adapter->hw; + u32 icr = er32(ICR); + + e_dbg("%s: icr is %08X\n", netdev->name, icr); + if (icr & E1000_ICR_RXSEQ) { + adapter->flags &= ~FLAG_MSI_TEST_FAILED; + wmb(); + } + + return IRQ_HANDLED; +} + +/** + * e1000_test_msi_interrupt - Returns 0 for successful test + * @adapter: board private struct + * + * code flow taken from tg3.c + **/ +static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) +{ + struct net_device *netdev = adapter->netdev; + struct e1000_hw *hw = &adapter->hw; + int err; + + /* poll_enable hasn't been called yet, so don't need disable */ + /* clear any pending events */ + er32(ICR); + + /* free the real vector and request a test handler */ + e1000_free_irq(adapter); + + /* Assume that the test fails, if it succeeds then the test + * MSI irq handler will unset this flag */ + adapter->flags |= FLAG_MSI_TEST_FAILED; + + err = pci_enable_msi(adapter->pdev); + if (err) + goto msi_test_failed; + + err = request_irq(adapter->pdev->irq, &e1000_intr_msi_test, 0, + netdev->name, netdev); + if (err) { + pci_disable_msi(adapter->pdev); + goto msi_test_failed; + } + + wmb(); + + e1000_irq_enable(adapter); + + /* fire an unusual interrupt on the test handler */ + ew32(ICS, E1000_ICS_RXSEQ); + e1e_flush(); + msleep(50); + + e1000_irq_disable(adapter); + + rmb(); + + if (adapter->flags & FLAG_MSI_TEST_FAILED) { + err = -EIO; + e_info("MSI interrupt test failed!\n"); + } + + free_irq(adapter->pdev->irq, netdev); + pci_disable_msi(adapter->pdev); + + if (err == -EIO) + goto msi_test_failed; + + /* okay so the test worked, restore settings */ + e_dbg("%s: MSI interrupt test succeeded!\n", netdev->name); +msi_test_failed: + /* restore the original vector, even if it failed */ + e1000_request_irq(adapter); + return err; +} + +/** + * e1000_test_msi - Returns 0 if MSI test succeeds or INTx mode is restored + * @adapter: board private struct + * + * code flow taken from tg3.c, called with e1000 interrupts disabled. + **/ +static int e1000_test_msi(struct e1000_adapter *adapter) +{ + int err; + u16 pci_cmd; + + if (!(adapter->flags & FLAG_MSI_ENABLED)) + return 0; + + /* disable SERR in case the MSI write causes a master abort */ + pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); + pci_write_config_word(adapter->pdev, PCI_COMMAND, + pci_cmd & ~PCI_COMMAND_SERR); + + err = e1000_test_msi_interrupt(adapter); + + /* restore previous setting of command word */ + pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd); + + /* success ! */ + if (!err) + return 0; + + /* EIO means MSI test failed */ + if (err != -EIO) + return err; + + /* back to INTx mode */ + e_warn("MSI interrupt test failed, using legacy interrupt.\n"); + + e1000_free_irq(adapter); + + err = e1000_request_irq(adapter); + + return err; +} + +/** * e1000_open - Called when a network interface is made active * @netdev: network interface device structure * @@ -2652,6 +2791,19 @@ static int e1000_open(struct net_device *netdev) if (err) goto err_req_irq; + /* + * Work around PCIe errata with MSI interrupts causing some chipsets to + * ignore e1000e MSI messages, which means we need to test our MSI + * interrupt now + */ + { + err = e1000_test_msi(adapter); + if (err) { + e_err("Interrupt allocation failed\n"); + goto err_req_irq; + } + } + /* From here on the code is the same as e1000e_up() */ clear_bit(__E1000_DOWN, &adapter->state); -- cgit v1.1 From 05c550babecfc129a8d9331edf43107192bae115 Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 8 Aug 2008 18:36:16 -0700 Subject: e1000e: remove unnecessary snippet missed in prior check_options update The removal of this bit of code was missed in an earlier patch submittal. Signed-off-by: Bruce Allan Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/e1000e/param.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000e/param.c b/drivers/net/e1000e/param.c index b0499f2..ed912e0 100644 --- a/drivers/net/e1000e/param.c +++ b/drivers/net/e1000e/param.c @@ -324,8 +324,6 @@ void __devinit e1000e_check_options(struct e1000_adapter *adapter) adapter->itr = 20000; break; default: - e1000_validate_option(&adapter->itr, &opt, - adapter); /* * Save the setting, because the dynamic bits * change itr. -- cgit v1.1 From 8d792cd990938c4d06b86141465ff8d52a946a0a Mon Sep 17 00:00:00 2001 From: Jesse Brandeburg Date: Fri, 8 Aug 2008 16:24:19 -0700 Subject: ixgbe: add cx4 device ID This is a simple device ID add for adapters that support CX4 (copper infiniband style cable) connectors for 10GbE. Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_82598.c | 1 + drivers/net/ixgbe/ixgbe_main.c | 4 +++- drivers/net/ixgbe/ixgbe_type.h | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/ixgbe/ixgbe_82598.c b/drivers/net/ixgbe/ixgbe_82598.c index 2f38e84..f96358b 100644 --- a/drivers/net/ixgbe/ixgbe_82598.c +++ b/drivers/net/ixgbe/ixgbe_82598.c @@ -190,6 +190,7 @@ static enum ixgbe_media_type ixgbe_get_media_type_82598(struct ixgbe_hw *hw) case IXGBE_DEV_ID_82598AF_DUAL_PORT: case IXGBE_DEV_ID_82598AF_SINGLE_PORT: case IXGBE_DEV_ID_82598EB_CX4: + case IXGBE_DEV_ID_82598_CX4_DUAL_PORT: media_type = ixgbe_media_type_fiber; break; case IXGBE_DEV_ID_82598AT_DUAL_PORT: diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index e5f3da8..34bca16 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -48,7 +48,7 @@ char ixgbe_driver_name[] = "ixgbe"; static const char ixgbe_driver_string[] = "Intel(R) 10 Gigabit PCI Express Network Driver"; -#define DRV_VERSION "1.3.18-k2" +#define DRV_VERSION "1.3.18-k4" const char ixgbe_driver_version[] = DRV_VERSION; static const char ixgbe_copyright[] = "Copyright (c) 1999-2007 Intel Corporation."; @@ -72,6 +72,8 @@ static struct pci_device_id ixgbe_pci_tbl[] = { board_82598 }, {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598EB_CX4), board_82598 }, + {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_82598_CX4_DUAL_PORT), + board_82598 }, /* required last entry */ {0, } diff --git a/drivers/net/ixgbe/ixgbe_type.h b/drivers/net/ixgbe/ixgbe_type.h index 1ad7cb9..c0282a2 100644 --- a/drivers/net/ixgbe/ixgbe_type.h +++ b/drivers/net/ixgbe/ixgbe_type.h @@ -39,6 +39,7 @@ #define IXGBE_DEV_ID_82598AF_SINGLE_PORT 0x10C7 #define IXGBE_DEV_ID_82598AT_DUAL_PORT 0x10C8 #define IXGBE_DEV_ID_82598EB_CX4 0x10DD +#define IXGBE_DEV_ID_82598_CX4_DUAL_PORT 0x10EC /* General Registers */ #define IXGBE_CTRL 0x00000 -- cgit v1.1 From 9dc28efeee98a4f81d5469d3576f55c5e6d1a5db Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 8 Aug 2008 00:08:39 -0700 Subject: netxen: fix mac addr setup For NX3031 mac addr should be read from firmware. mac addr in flash is still valid, but can be overridden by firmware if running in virtualization environment. For old revisions, mac addr is retrieved directly from flash. Signed-off-by: Dhananjay Phadke Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic.h | 3 +- drivers/net/netxen/netxen_nic_hw.c | 51 ++++++++++++++++++------- drivers/net/netxen/netxen_nic_main.c | 65 ++++++++++++++++++++------------ drivers/net/netxen/netxen_nic_phan_reg.h | 2 + 4 files changed, 83 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 93a7b9b..2cf6e41 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -1615,7 +1615,8 @@ dma_watchdog_wakeup(struct netxen_adapter *adapter) int netxen_is_flash_supported(struct netxen_adapter *adapter); -int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 mac[]); +int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac); +int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac); extern void netxen_change_ringparam(struct netxen_adapter *adapter); extern int netxen_rom_fast_read(struct netxen_adapter *adapter, int addr, int *valp); diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index 9aa20f9..f5db48b 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -733,31 +733,56 @@ static int netxen_get_flash_block(struct netxen_adapter *adapter, int base, return 0; } -int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 mac[]) +int netxen_get_flash_mac_addr(struct netxen_adapter *adapter, __le64 *mac) { - __le32 *pmac = (__le32 *) & mac[0]; + __le32 *pmac = (__le32 *) mac; + u32 offset; - if (netxen_get_flash_block(adapter, - NETXEN_USER_START + - offsetof(struct netxen_new_user_info, - mac_addr), - FLASH_NUM_PORTS * sizeof(u64), pmac) == -1) { + offset = NETXEN_USER_START + + offsetof(struct netxen_new_user_info, mac_addr) + + adapter->portnum * sizeof(u64); + + if (netxen_get_flash_block(adapter, offset, sizeof(u64), pmac) == -1) return -1; - } + if (*mac == cpu_to_le64(~0ULL)) { + + offset = NETXEN_USER_START_OLD + + offsetof(struct netxen_user_old_info, mac_addr) + + adapter->portnum * sizeof(u64); + if (netxen_get_flash_block(adapter, - NETXEN_USER_START_OLD + - offsetof(struct netxen_user_old_info, - mac_addr), - FLASH_NUM_PORTS * sizeof(u64), - pmac) == -1) + offset, sizeof(u64), pmac) == -1) return -1; + if (*mac == cpu_to_le64(~0ULL)) return -1; } return 0; } +int netxen_p3_get_mac_addr(struct netxen_adapter *adapter, __le64 *mac) +{ + uint32_t crbaddr, mac_hi, mac_lo; + int pci_func = adapter->ahw.pci_func; + + crbaddr = CRB_MAC_BLOCK_START + + (4 * ((pci_func/2) * 3)) + (4 * (pci_func & 1)); + + adapter->hw_read_wx(adapter, crbaddr, &mac_lo, 4); + adapter->hw_read_wx(adapter, crbaddr+4, &mac_hi, 4); + + mac_hi = cpu_to_le32(mac_hi); + mac_lo = cpu_to_le32(mac_lo); + + if (pci_func & 1) + *mac = ((mac_lo >> 16) | ((u64)mac_hi << 16)); + else + *mac = ((mac_lo) | ((u64)mac_hi << 32)); + + return 0; +} + #define CRB_WIN_LOCK_TIMEOUT 100000000 static int crb_win_lock(struct netxen_adapter *adapter) diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 7615c71..6fc42cd 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -501,6 +501,44 @@ static void netxen_init_msix_entries(struct netxen_adapter *adapter) adapter->msix_entries[i].entry = i; } +static int +netxen_read_mac_addr(struct netxen_adapter *adapter) +{ + int i; + unsigned char *p; + __le64 mac_addr; + DECLARE_MAC_BUF(mac); + struct net_device *netdev = adapter->netdev; + struct pci_dev *pdev = adapter->pdev; + + if (netxen_is_flash_supported(adapter) != 0) + return -EIO; + + if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { + if (netxen_p3_get_mac_addr(adapter, &mac_addr) != 0) + return -EIO; + } else { + if (netxen_get_flash_mac_addr(adapter, &mac_addr) != 0) + return -EIO; + } + + p = (unsigned char *)&mac_addr; + for (i = 0; i < 6; i++) + netdev->dev_addr[i] = *(p + 5 - i); + + memcpy(netdev->perm_addr, netdev->dev_addr, netdev->addr_len); + + /* set station address */ + + if (!is_valid_ether_addr(netdev->perm_addr)) { + dev_warn(&pdev->dev, "Bad MAC address %s.\n", + print_mac(mac, netdev->dev_addr)); + } else + adapter->macaddr_set(adapter, netdev->dev_addr); + + return 0; +} + /* * netxen_nic_probe() * @@ -529,10 +567,8 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) unsigned long mem_base, mem_len, db_base, db_len, pci_len0 = 0; int i = 0, err; int first_driver, first_boot; - __le64 mac_addr[FLASH_NUM_PORTS + 1]; u32 val; int pci_func_id = PCI_FUNC(pdev->devfn); - DECLARE_MAC_BUF(mac); struct netxen_legacy_intr_set *legacy_intrp; uint8_t revision_id; @@ -904,28 +940,9 @@ request_msi: INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); INIT_WORK(&adapter->tx_timeout_task, netxen_tx_timeout_task); - if (netxen_is_flash_supported(adapter) == 0 && - netxen_get_flash_mac_addr(adapter, mac_addr) == 0) { - unsigned char *p; - - p = (unsigned char *)&mac_addr[adapter->portnum]; - netdev->dev_addr[0] = *(p + 5); - netdev->dev_addr[1] = *(p + 4); - netdev->dev_addr[2] = *(p + 3); - netdev->dev_addr[3] = *(p + 2); - netdev->dev_addr[4] = *(p + 1); - netdev->dev_addr[5] = *(p + 0); - - memcpy(netdev->perm_addr, netdev->dev_addr, - netdev->addr_len); - if (!is_valid_ether_addr(netdev->perm_addr)) { - printk(KERN_ERR "%s: Bad MAC address %s.\n", - netxen_nic_driver_name, - print_mac(mac, netdev->dev_addr)); - } else { - adapter->macaddr_set(adapter, netdev->dev_addr); - } - } + err = netxen_read_mac_addr(adapter); + if (err) + dev_warn(&pdev->dev, "failed to read mac addr\n"); netif_carrier_off(netdev); netif_stop_queue(netdev); diff --git a/drivers/net/netxen/netxen_nic_phan_reg.h b/drivers/net/netxen/netxen_nic_phan_reg.h index 83e5ee5..b293adc 100644 --- a/drivers/net/netxen/netxen_nic_phan_reg.h +++ b/drivers/net/netxen/netxen_nic_phan_reg.h @@ -125,6 +125,8 @@ #define CRB_SW_INT_MASK_2 NETXEN_NIC_REG(0x1e4) #define CRB_SW_INT_MASK_3 NETXEN_NIC_REG(0x1e8) +#define CRB_MAC_BLOCK_START NETXEN_CAM_RAM(0x1c0) + /* * capabilities register, can be used to selectively enable/disable features * for backward compability -- cgit v1.1 From 9e410778047d0f2887adb888b44eda4d72d4f67d Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 8 Aug 2008 00:08:40 -0700 Subject: netxen: fix rxbuf leak across driver reload Free up rx ring during driver unload or open() failure. Signed-off-by: Dhananjay Phadke Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 6fc42cd..056f6b1 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -1017,6 +1017,7 @@ static void __devexit netxen_nic_remove(struct pci_dev *pdev) if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { netxen_free_hw_resources(adapter); + netxen_release_rx_buffers(adapter); netxen_free_sw_resources(adapter); } @@ -1111,7 +1112,7 @@ static int netxen_nic_open(struct net_device *netdev) flags, netdev->name, adapter); if (err) { printk(KERN_ERR "request_irq failed with: %d\n", err); - goto err_out_free_hw; + goto err_out_free_rxbuf; } adapter->is_up = NETXEN_ADAPTER_UP_MAGIC; @@ -1144,7 +1145,8 @@ static int netxen_nic_open(struct net_device *netdev) err_out_free_irq: free_irq(adapter->irq, adapter); -err_out_free_hw: +err_out_free_rxbuf: + netxen_release_rx_buffers(adapter); netxen_free_hw_resources(adapter); err_out_free_sw: netxen_free_sw_resources(adapter); -- cgit v1.1 From 922c4f2c70c156ac38b4e6affbd30d4b1efd5864 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 8 Aug 2008 00:08:41 -0700 Subject: netxen: force link update across ifdown/ifup Re-read link status in dev open(). Schedule link watchdog only if dev is up. Signed-off-by: Dhananjay Phadke Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic_main.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 056f6b1..f69807c 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -934,7 +934,6 @@ request_msi: goto err_out_disable_msi; init_timer(&adapter->watchdog_timer); - adapter->ahw.linkup = 0; adapter->watchdog_timer.function = &netxen_watchdog; adapter->watchdog_timer.data = (unsigned long)adapter; INIT_WORK(&adapter->watchdog_task, netxen_watchdog_task); @@ -1134,6 +1133,7 @@ static int netxen_nic_open(struct net_device *netdev) if (adapter->set_mtu) adapter->set_mtu(adapter, netdev->mtu); + adapter->ahw.linkup = 0; mod_timer(&adapter->watchdog_timer, jiffies); napi_enable(&adapter->napi); @@ -1171,10 +1171,8 @@ static int netxen_nic_close(struct net_device *netdev) netxen_release_tx_buffers(adapter); - if (adapter->is_up == NETXEN_ADAPTER_UP_MAGIC) { - FLUSH_SCHEDULED_WORK(); - del_timer_sync(&adapter->watchdog_timer); - } + FLUSH_SCHEDULED_WORK(); + del_timer_sync(&adapter->watchdog_timer); return 0; } @@ -1477,7 +1475,8 @@ void netxen_watchdog_task(struct work_struct *work) netxen_nic_handle_phy_intr(adapter); - mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); + if (netif_running(adapter->netdev)) + mod_timer(&adapter->watchdog_timer, jiffies + 2 * HZ); } static void netxen_tx_timeout(struct net_device *netdev) -- cgit v1.1 From 15eef1e1b718667981da92d2fa18283f181c117c Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 8 Aug 2008 00:08:42 -0700 Subject: netxen: fix dma watchdog NX3031 does not require driver to kill dma watchdog. Signed-off-by: Dhananjay Phadke Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic_init.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c index 519fc86..5bba675 100644 --- a/drivers/net/netxen/netxen_nic_init.c +++ b/drivers/net/netxen/netxen_nic_init.c @@ -1079,10 +1079,12 @@ int netxen_initialize_adapter_offload(struct netxen_adapter *adapter) void netxen_free_adapter_offload(struct netxen_adapter *adapter) { - int i; + int i = 100; + + if (!adapter->dummy_dma.addr) + return; - if (adapter->dummy_dma.addr) { - i = 100; + if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { do { if (dma_watchdog_shutdown_request(adapter) == 1) break; @@ -1090,17 +1092,17 @@ void netxen_free_adapter_offload(struct netxen_adapter *adapter) if (dma_watchdog_shutdown_poll_result(adapter) == 1) break; } while (--i); + } - if (i) { - pci_free_consistent(adapter->pdev, - NETXEN_HOST_DUMMY_DMA_SIZE, - adapter->dummy_dma.addr, - adapter->dummy_dma.phys_addr); - adapter->dummy_dma.addr = NULL; - } else { - printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n", - adapter->netdev->name); - } + if (i) { + pci_free_consistent(adapter->pdev, + NETXEN_HOST_DUMMY_DMA_SIZE, + adapter->dummy_dma.addr, + adapter->dummy_dma.phys_addr); + adapter->dummy_dma.addr = NULL; + } else { + printk(KERN_ERR "%s: dma_watchdog_shutdown failed\n", + adapter->netdev->name); } } -- cgit v1.1 From 092bc57184842229ee41f87d9c408a3f1302aaa6 Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 8 Aug 2008 00:08:43 -0700 Subject: netxen: cleanup interrupt code Mark interrupt scheme in very old firmware incompatible. Interrupt mask and status registers are per pci function / port. Signed-off-by: Dhananjay Phadke Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic_main.c | 123 ++++++++++++----------------------- 1 file changed, 40 insertions(+), 83 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index f69807c..3c424a8 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -149,76 +149,18 @@ static uint32_t msi_tgt_status[8] = { static struct netxen_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG; -static void netxen_nic_disable_int(struct netxen_adapter *adapter) +static inline void netxen_nic_disable_int(struct netxen_adapter *adapter) { - u32 mask = 0x7ff; - int retries = 32; - int pci_fn = adapter->ahw.pci_func; - - if (adapter->msi_mode != MSI_MODE_MULTIFUNC) - adapter->pci_write_normalize(adapter, - adapter->crb_intr_mask, 0); - - if (adapter->intr_scheme != -1 && - adapter->intr_scheme != INTR_SCHEME_PERPORT) - adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask); - - if (!NETXEN_IS_MSI_FAMILY(adapter)) { - do { - adapter->pci_write_immediate(adapter, - adapter->legacy_intr.tgt_status_reg, - 0xffffffff); - mask = adapter->pci_read_immediate(adapter, - ISR_INT_VECTOR); - if (!(mask & 0x80)) - break; - udelay(10); - } while (--retries); - - if (!retries) { - printk(KERN_NOTICE "%s: Failed to disable interrupt\n", - netxen_nic_driver_name); - } - } else { - if (adapter->msi_mode == MSI_MODE_MULTIFUNC) { - adapter->pci_write_immediate(adapter, - msi_tgt_status[pci_fn], 0xffffffff); - } - } + adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0); } -static void netxen_nic_enable_int(struct netxen_adapter *adapter) +static inline void netxen_nic_enable_int(struct netxen_adapter *adapter) { - u32 mask; - - if (adapter->intr_scheme != -1 && - adapter->intr_scheme != INTR_SCHEME_PERPORT) { - switch (adapter->ahw.board_type) { - case NETXEN_NIC_GBE: - mask = 0x77b; - break; - case NETXEN_NIC_XGBE: - mask = 0x77f; - break; - default: - mask = 0x7ff; - break; - } - - adapter->pci_write_immediate(adapter, ISR_INT_MASK, mask); - } - adapter->pci_write_normalize(adapter, adapter->crb_intr_mask, 0x1); - if (!NETXEN_IS_MSI_FAMILY(adapter)) { - mask = 0xbff; - if (adapter->intr_scheme == INTR_SCHEME_PERPORT) - adapter->pci_write_immediate(adapter, - adapter->legacy_intr.tgt_mask_reg, mask); - else - adapter->pci_write_normalize(adapter, - CRB_INT_VECTOR, 0); - } + if (!NETXEN_IS_MSI_FAMILY(adapter)) + adapter->pci_write_immediate(adapter, + adapter->legacy_intr.tgt_mask_reg, 0xfbff); } static int nx_set_dma_mask(struct netxen_adapter *adapter, uint8_t revision_id) @@ -1086,6 +1028,15 @@ static int netxen_nic_open(struct net_device *netdev) goto err_out_free_sw; } + if ((adapter->msi_mode != MSI_MODE_MULTIFUNC) || + (adapter->intr_scheme != INTR_SCHEME_PERPORT)) { + printk(KERN_ERR "%s: Firmware interrupt scheme is " + "incompatible with driver\n", + netdev->name); + adapter->driver_mismatch = 1; + goto err_out_free_hw; + } + if (adapter->fw_major < 4) { adapter->crb_addr_cmd_producer = crb_cmd_producer[adapter->portnum]; @@ -1147,6 +1098,7 @@ err_out_free_irq: free_irq(adapter->irq, adapter); err_out_free_rxbuf: netxen_release_rx_buffers(adapter); +err_out_free_hw: netxen_free_hw_resources(adapter); err_out_free_sw: netxen_free_sw_resources(adapter); @@ -1536,18 +1488,9 @@ struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev) return stats; } -static inline void -netxen_handle_int(struct netxen_adapter *adapter) -{ - netxen_nic_disable_int(adapter); - napi_schedule(&adapter->napi); -} - static irqreturn_t netxen_intr(int irq, void *data) { struct netxen_adapter *adapter = data; - u32 our_int = 0; - u32 status = 0; status = adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); @@ -1562,22 +1505,32 @@ static irqreturn_t netxen_intr(int irq, void *data) if (!ISR_LEGACY_INT_TRIGGERED(status)) return IRQ_NONE; - } else if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { + } else { + unsigned long our_int = 0; our_int = adapter->pci_read_normalize(adapter, CRB_INT_VECTOR); + /* not our interrupt */ - if ((our_int & (0x80 << adapter->portnum)) == 0) + if (!test_and_clear_bit((7 + adapter->portnum), &our_int)) return IRQ_NONE; - if (adapter->intr_scheme == INTR_SCHEME_PERPORT) { - /* claim interrupt */ - adapter->pci_write_normalize(adapter, - CRB_INT_VECTOR, - our_int & ~((u32)(0x80 << adapter->portnum))); - } + /* claim interrupt */ + adapter->pci_write_normalize(adapter, + CRB_INT_VECTOR, (our_int & 0xffffffff)); } - netxen_handle_int(adapter); + /* clear interrupt */ + if (adapter->fw_major < 4) + netxen_nic_disable_int(adapter); + + adapter->pci_write_immediate(adapter, + adapter->legacy_intr.tgt_status_reg, + 0xffffffff); + /* read twice to ensure write is flushed */ + adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); + adapter->pci_read_immediate(adapter, ISR_INT_VECTOR); + + napi_schedule(&adapter->napi); return IRQ_HANDLED; } @@ -1586,7 +1539,11 @@ static irqreturn_t netxen_msi_intr(int irq, void *data) { struct netxen_adapter *adapter = data; - netxen_handle_int(adapter); + /* clear interrupt */ + adapter->pci_write_immediate(adapter, + msi_tgt_status[adapter->ahw.pci_func], 0xffffffff); + + napi_schedule(&adapter->napi); return IRQ_HANDLED; } -- cgit v1.1 From 11d89d639352ef27bb3f0e7513dd406284bf034a Mon Sep 17 00:00:00 2001 From: Dhananjay Phadke Date: Fri, 8 Aug 2008 00:08:45 -0700 Subject: netxen: update driver version Raise driver version to 4.0.11. Signed-off-by: Dhananjay Phadke Signed-off-by: Jeff Garzik --- drivers/net/netxen/netxen_nic.h | 4 ++-- drivers/net/netxen/netxen_nic_hw.c | 8 ++++---- drivers/net/netxen/netxen_nic_main.c | 7 +++++++ 3 files changed, 13 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index 2cf6e41..ab871df 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -66,8 +66,8 @@ #define _NETXEN_NIC_LINUX_MAJOR 4 #define _NETXEN_NIC_LINUX_MINOR 0 -#define _NETXEN_NIC_LINUX_SUBVERSION 0 -#define NETXEN_NIC_LINUX_VERSIONID "4.0.0" +#define _NETXEN_NIC_LINUX_SUBVERSION 11 +#define NETXEN_NIC_LINUX_VERSIONID "4.0.11" #define NETXEN_VERSION_CODE(a, b, c) (((a) << 16) + ((b) << 8) + (c)) diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c index f5db48b..84978f8 100644 --- a/drivers/net/netxen/netxen_nic_hw.c +++ b/drivers/net/netxen/netxen_nic_hw.c @@ -2208,10 +2208,10 @@ void netxen_nic_flash_print(struct netxen_adapter *adapter) if (adapter->portnum == 0) { get_brd_name_by_type(board_info->board_type, brd_name); - printk("NetXen %s Board S/N %s Chip id 0x%x\n", - brd_name, serial_num, board_info->chip_id); - printk("NetXen Firmware version %d.%d.%d\n", fw_major, - fw_minor, fw_build); + printk(KERN_INFO "NetXen %s Board S/N %s Chip rev 0x%x\n", + brd_name, serial_num, adapter->ahw.revision_id); + printk(KERN_INFO "NetXen Firmware version %d.%d.%d\n", + fw_major, fw_minor, fw_build); } if (NETXEN_VERSION_CODE(fw_major, fw_minor, fw_build) < diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c index 3c424a8..32bb47a 100644 --- a/drivers/net/netxen/netxen_nic_main.c +++ b/drivers/net/netxen/netxen_nic_main.c @@ -523,6 +523,13 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent) return -ENODEV; } + if (pdev->revision >= NX_P3_A0 && pdev->revision < NX_P3_B1) { + printk(KERN_WARNING "NetXen chip revisions between 0x%x-0x%x" + "will not be enabled.\n", + NX_P3_A0, NX_P3_B1); + return -ENODEV; + } + if ((err = pci_enable_device(pdev))) return err; -- cgit v1.1 From 1595ab5d7d99bc6c9a5548ab3fb83e278eeae409 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Fri, 8 Aug 2008 21:33:34 +0300 Subject: [netdrvr] uninline atl1e_setup_mac_ctrl() There doesn't seem to be a compelling reason why atl1e_setup_mac_ctrl() is marked as "inline": It's not used in any place where speed would matter much, and as long as it has only one caller non-ancient gcc versions anyway inline it automatically. This patch fixes the following compile error with gcc 3.4: <-- snip --> ... CC drivers/net/atl1e/atl1e_main.o atl1e_main.c: In function `atl1e_check_link': atl1e_main.c:50: sorry, unimplemented: inlining failed in call to atl1e_main.c:196: sorry, unimplemented: called from here make[4]: *** [drivers/net/atl1e/atl1e_main.o] Error 1 <-- snip --> Reported-by: Adrian Bunk Signed-off-by: Adrian Bunk Signed-off-by: Jeff Garzik --- drivers/net/atl1e/atl1e_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 35264c2..82d7be1 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -47,7 +47,7 @@ MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -static inline void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter); +static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter); static const u16 atl1e_rx_page_vld_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] = @@ -1037,7 +1037,7 @@ static inline void atl1e_configure_dma(struct atl1e_adapter *adapter) return; } -static inline void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter) +static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter) { u32 value; struct atl1e_hw *hw = &adapter->hw; -- cgit v1.1 From add477df674db00377d9a4dc0d9b553ce79bc06d Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Fri, 8 Aug 2008 12:01:11 -0700 Subject: hso: fix oops in read/write callbacks The tty may be closed already when the read/write callbacks are called. This patch checks that the ttys still exist before waking them up. Signed-off-by: Olivier Blin Acked-by: Alan Cox Cc: Jari Tenhunen Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jeff Garzik --- drivers/net/usb/hso.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 031d07b..94a27f7 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1467,7 +1467,8 @@ static void hso_std_serial_write_bulk_callback(struct urb *urb) return; } hso_put_activity(serial->parent); - tty_wakeup(serial->tty); + if (serial->tty) + tty_wakeup(serial->tty); hso_kick_transmit(serial); D1(" "); @@ -1538,7 +1539,8 @@ static void ctrl_callback(struct urb *urb) clear_bit(HSO_SERIAL_FLAG_RX_SENT, &serial->flags); } else { hso_put_activity(serial->parent); - tty_wakeup(serial->tty); + if (serial->tty) + tty_wakeup(serial->tty); /* response to a write command */ hso_kick_transmit(serial); } -- cgit v1.1 From 6d558a52ba295fc1c281c671d7daab2f74ddb4f2 Mon Sep 17 00:00:00 2001 From: Olivier Blin Date: Fri, 8 Aug 2008 12:01:41 -0700 Subject: hso: fix refcounting on the ttyHSx devices The references on ttyHSx devices were not decremented correctly when the tty was closed. The helper freeing the serial devices was never called because of that, and the module left some dangling sysfs devices after being unloaded. Signed-off-by: Olivier Blin Cc: Jari Tenhunen Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jeff Garzik --- drivers/net/usb/hso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 94a27f7..94c41bb 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1103,8 +1103,8 @@ static void hso_serial_close(struct tty_struct *tty, struct file *filp) /* reset the rts and dtr */ /* do the actual close */ serial->open_count--; + kref_put(&serial->parent->ref, hso_serial_ref_free); if (serial->open_count <= 0) { - kref_put(&serial->parent->ref, hso_serial_ref_free); serial->open_count = 0; if (serial->tty) { serial->tty->driver_data = NULL; -- cgit v1.1 From 6c59f56978c3dffd447176d218bc5852842c9ce9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 8 Aug 2008 12:02:14 -0700 Subject: USB: HSO: make tty_operations const As recommended by Arjan. Cc: Arjan van de Ven Cc: Andrew Bird Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jeff Garzik --- drivers/net/usb/hso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 94c41bb..35a7772 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2725,7 +2725,7 @@ static int hso_mux_submit_intr_urb(struct hso_shared_int *shared_int, } /* operations setup of the serial interface */ -static struct tty_operations hso_serial_ops = { +static const struct tty_operations hso_serial_ops = { .open = hso_serial_open, .close = hso_serial_close, .write = hso_serial_write, -- cgit v1.1 From 0235f64175db41fa17a6ce5c9b58fd3550986eb4 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 8 Aug 2008 12:02:57 -0700 Subject: USB: HSO: minor fixes due to code review Fix up problems in hso.c driver as pointed out by Andrew. Cc: Andrew Morton Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jeff Garzik --- drivers/net/usb/hso.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 35a7772..1b7cac7 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -102,8 +102,12 @@ #define MAX_RX_URBS 2 -#define get_serial_by_tty(x) \ - (x ? (struct hso_serial *)x->driver_data : NULL) +static inline struct hso_serial *get_serial_by_tty(struct tty_struct *tty) +{ + if (tty) + return tty->driver_data; + return NULL; +} /*****************************************************************************/ /* Debugging functions */ @@ -294,24 +298,25 @@ static int hso_get_activity(struct hso_device *hso_dev); /* #define DEBUG */ -#define dev2net(x) (x->port_data.dev_net) -#define dev2ser(x) (x->port_data.dev_serial) +static inline struct hso_net *dev2net(struct hso_device *hso_dev) +{ + return hso_dev->port_data.dev_net; +} + +static inline struct hso_serial *dev2ser(struct hso_device *hso_dev) +{ + return hso_dev->port_data.dev_serial; +} /* Debugging functions */ #ifdef DEBUG static void dbg_dump(int line_count, const char *func_name, unsigned char *buf, unsigned int len) { - u8 i = 0; - - printk(KERN_DEBUG "[%d:%s]: len %d", line_count, func_name, len); + static char name[255]; - for (i = 0; i < len; i++) { - if (!(i % 16)) - printk("\n 0x%03x: ", i); - printk("%02x ", (unsigned char)buf[i]); - } - printk("\n"); + sprintf(name, "hso[%d:%s]", line_count, func_name); + print_hex_dump_bytes(name, DUMP_PREFIX_NONE, buf, len); } #define DUMP(buf_, len_) \ @@ -528,13 +533,12 @@ static struct hso_serial *get_serial_by_shared_int_and_type( static struct hso_serial *get_serial_by_index(unsigned index) { - struct hso_serial *serial; + struct hso_serial *serial = NULL; unsigned long flags; - if (!serial_table[index]) - return NULL; spin_lock_irqsave(&serial_table_lock, flags); - serial = dev2ser(serial_table[index]); + if (serial_table[index]) + serial = dev2ser(serial_table[index]); spin_unlock_irqrestore(&serial_table_lock, flags); return serial; @@ -561,6 +565,7 @@ static int get_free_serial_index(void) static void set_serial_by_index(unsigned index, struct hso_serial *serial) { unsigned long flags; + spin_lock_irqsave(&serial_table_lock, flags); if (serial) serial_table[index] = serial->parent; @@ -569,7 +574,7 @@ static void set_serial_by_index(unsigned index, struct hso_serial *serial) spin_unlock_irqrestore(&serial_table_lock, flags); } -/* log a meaningfull explanation of an USB status */ +/* log a meaningful explanation of an USB status */ static void log_usb_status(int status, const char *function) { char *explanation; @@ -2654,7 +2659,7 @@ static void hso_free_interface(struct usb_interface *interface) hso_stop_net_device(network_table[i]); cancel_work_sync(&network_table[i]->async_put_intf); cancel_work_sync(&network_table[i]->async_get_intf); - if(rfk) + if (rfk) rfkill_unregister(rfk); hso_free_net_device(network_table[i]); } -- cgit v1.1 From 85a73b333c0c06fcadb8e32f1e30f00e980f2fc7 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 8 Aug 2008 13:53:29 -0700 Subject: Kconfig: HSO driver bugfixes and updates Move the Kconfig for the new "Option" driver so it's not in the middle of the usbnet-based drivers, so the dependency displays in the Kconfig user interfaces don't get trashed. Signed-off-by: David Brownell Signed-off-by: Jeff Garzik --- drivers/net/usb/Kconfig | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 68e198b..0973b6e 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -154,17 +154,6 @@ config USB_NET_AX8817X This driver creates an interface named "ethX", where X depends on what other networking devices you have in use. -config USB_HSO - tristate "Option USB High Speed Mobile Devices" - depends on USB && RFKILL - default n - help - Choose this option if you have an Option HSDPA/HSUPA card. - These cards support downlink speeds of 7.2Mbps or greater. - - To compile this driver as a module, choose M here: the - module will be called hso. - config USB_NET_CDCETHER tristate "CDC Ethernet support (smart devices such as cable modems)" depends on USB_USBNET @@ -337,5 +326,15 @@ config USB_NET_ZAURUS really need this non-conformant variant of CDC Ethernet (or in some cases CDC MDLM) protocol, not "g_ether". +config USB_HSO + tristate "Option USB High Speed Mobile Devices" + depends on USB && RFKILL + default n + help + Choose this option if you have an Option HSDPA/HSUPA card. + These cards support downlink speeds of 7.2Mbps or greater. + + To compile this driver as a module, choose M here: the + module will be called hso. endmenu -- cgit v1.1 From c7e65c17d75f29c846ff711b1dc5e823ba8de314 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Fri, 8 Aug 2008 00:55:17 +0900 Subject: [netdrvr] ne: Use CONFIG_MACH_TX49XX After some cleanups in arch/mips area, now MACH_TX49XX is selected for both TOSHIBA_RBTX4927 and TOSHIBA_RBTX4938. Fold these two conditions to one. Signed-off-by: Atsushi Nemoto Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 2 +- drivers/net/ne.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 4b4cb2b..a5c141c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -1172,7 +1172,7 @@ config ETH16I config NE2000 tristate "NE2000/NE1000 support" - depends on NET_ISA || (Q40 && m) || M32R || TOSHIBA_RBTX4927 || TOSHIBA_RBTX4938 + depends on NET_ISA || (Q40 && m) || M32R || MACH_TX49XX select CRC32 ---help--- If you have a network (Ethernet) card of this type, say Y and read diff --git a/drivers/net/ne.c b/drivers/net/ne.c index 42443d6..fa3ceca 100644 --- a/drivers/net/ne.c +++ b/drivers/net/ne.c @@ -118,7 +118,7 @@ bad_clone_list[] __initdata = { {"E-LAN100", "E-LAN200", {0x00, 0x00, 0x5d}}, /* Broken ne1000 clones */ {"PCM-4823", "PCM-4823", {0x00, 0xc0, 0x6c}}, /* Broken Advantech MoBo */ {"REALTEK", "RTL8019", {0x00, 0x00, 0xe8}}, /* no-name with Realtek chip */ -#if defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938) +#ifdef CONFIG_MACH_TX49XX {"RBHMA4X00-RTL8019", "RBHMA4X00/RTL8019", {0x00, 0x60, 0x0a}}, /* Toshiba built-in */ #endif {"LCS-8834", "LCS-8836", {0x04, 0x04, 0x37}}, /* ShinyNet (SET) */ @@ -142,7 +142,7 @@ bad_clone_list[] __initdata = { #if defined(CONFIG_PLAT_MAPPI) # define DCR_VAL 0x4b #elif defined(CONFIG_PLAT_OAKS32R) || \ - defined(CONFIG_TOSHIBA_RBTX4927) || defined(CONFIG_TOSHIBA_RBTX4938) + defined(CONFIG_MACH_TX49XX) # define DCR_VAL 0x48 /* 8-bit mode */ #else # define DCR_VAL 0x49 -- cgit v1.1 From 1a3c4bc61547e5a75fd3b85b425624756da4cffb Mon Sep 17 00:00:00 2001 From: roel kluin Date: Thu, 7 Aug 2008 12:24:42 -0400 Subject: atl1e: WAKE_MCAST 2x. 1st WAKE_UCAST? Signed-off-by: Jeff Garzik --- drivers/net/atl1e/atl1e_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/atl1e/atl1e_ethtool.c b/drivers/net/atl1e/atl1e_ethtool.c index cdc3b85..619c658 100644 --- a/drivers/net/atl1e/atl1e_ethtool.c +++ b/drivers/net/atl1e/atl1e_ethtool.c @@ -355,7 +355,7 @@ static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) struct atl1e_adapter *adapter = netdev_priv(netdev); if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | - WAKE_MCAST | WAKE_BCAST | WAKE_MCAST)) + WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)) return -EOPNOTSUPP; /* these settings will always override what we currently have */ adapter->wol = 0; -- cgit v1.1 From c0912585ec8b64d846d56995241f2c8a7f48ee75 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Thu, 7 Aug 2008 17:21:09 +0100 Subject: AX88796: Fix locking in ethtool support Fix a pair of nasty locking problems in the ax88796 driver spotted by a sparse check: warning: context imbalance in 'ax_get_settings' - wrong count at exit warning: context imbalance in 'ax_set_settings' - wrong count at exit Signed-off-by: Ben Dooks Signed-off-by: Jeff Garzik --- drivers/net/ax88796.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ax88796.c b/drivers/net/ax88796.c index 0b4adf4..a886a4b 100644 --- a/drivers/net/ax88796.c +++ b/drivers/net/ax88796.c @@ -554,7 +554,7 @@ static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) spin_lock_irqsave(&ax->mii_lock, flags); mii_ethtool_gset(&ax->mii, cmd); - spin_lock_irqsave(&ax->mii_lock, flags); + spin_unlock_irqrestore(&ax->mii_lock, flags); return 0; } @@ -567,7 +567,7 @@ static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) spin_lock_irqsave(&ax->mii_lock, flags); rc = mii_ethtool_sset(&ax->mii, cmd); - spin_lock_irqsave(&ax->mii_lock, flags); + spin_unlock_irqrestore(&ax->mii_lock, flags); return rc; } -- cgit v1.1 From 7c6337a15e3d4689efe703e8bb65ae82cc13c435 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 14 Aug 2008 15:29:09 -0700 Subject: bnx2: Fix logic to setup VLAN rx tagging. We should now be checking BNX2_FLAG_CAN_KEEP_VLAN to determine how to set the VLAN rx tagging in the RX_MODE register. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 5ebde67..0623ceb7 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -3237,10 +3237,10 @@ bnx2_set_rx_mode(struct net_device *dev) BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG); sort_mode = 1 | BNX2_RPM_SORT_USER0_BC_EN; #ifdef BCM_VLAN - if (!bp->vlgrp && !(bp->flags & BNX2_FLAG_ASF_ENABLE)) + if (!bp->vlgrp && (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)) rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG; #else - if (!(bp->flags & BNX2_FLAG_ASF_ENABLE)) + if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN) rx_mode |= BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG; #endif if (dev->flags & IFF_PROMISC) { -- cgit v1.1 From 729b85cd47f4e63657505cb5c6af104e19250805 Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 14 Aug 2008 15:29:39 -0700 Subject: bnx2: Use proper CONFIG_VLAN_8021Q to compile the VLAN code. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 0623ceb7..a2a010e 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -35,7 +35,7 @@ #include #include #include -#ifdef NETIF_F_HW_VLAN_TX +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #include #define BCM_VLAN 1 #endif @@ -5963,10 +5963,12 @@ bnx2_start_xmit(struct sk_buff *skb, struct net_device *dev) vlan_tag_flags |= TX_BD_FLAGS_TCP_UDP_CKSUM; } +#ifdef BCM_VLAN if (bp->vlgrp && vlan_tx_tag_present(skb)) { vlan_tag_flags |= (TX_BD_FLAGS_VLAN_TAG | (vlan_tx_tag_get(skb) << 16)); } +#endif if ((mss = skb_shinfo(skb)->gso_size)) { u32 tcp_opt_len, ip_tcp_len; struct iphdr *iph; -- cgit v1.1 From f22828e89f4f3e8c74ca7ffa69b0410afbd80eee Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 14 Aug 2008 15:30:14 -0700 Subject: bnx2: Reinsert VLAN tag when necessary. In certain cases when ASF or other management firmware is running, the chip may be configured to always strip out the VLAN tag even when VLAN acceleration is not enabled. This causes some VLAN tagged packets to be received by the host stack without any knowledge that the original packet was VLAN tagged. We fix this by re-inserting the VLAN tag into the packet when necessary. Signed-off-by: Michael Chan Signed-off-by: Benjamin Li Signed-off-by: Matt Carlson Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index a2a010e..1f2e76f 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -2876,6 +2876,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) struct sw_bd *rx_buf; struct sk_buff *skb; dma_addr_t dma_addr; + u16 vtag = 0; + int hw_vlan __maybe_unused = 0; sw_ring_cons = RX_RING_IDX(sw_cons); sw_ring_prod = RX_RING_IDX(sw_prod); @@ -2919,7 +2921,7 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) if (len <= bp->rx_copy_thresh) { struct sk_buff *new_skb; - new_skb = netdev_alloc_skb(bp->dev, len + 2); + new_skb = netdev_alloc_skb(bp->dev, len + 6); if (new_skb == NULL) { bnx2_reuse_rx_skb(bp, rxr, skb, sw_ring_cons, sw_ring_prod); @@ -2928,9 +2930,9 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) /* aligned copy */ skb_copy_from_linear_data_offset(skb, - BNX2_RX_OFFSET - 2, - new_skb->data, len + 2); - skb_reserve(new_skb, 2); + BNX2_RX_OFFSET - 6, + new_skb->data, len + 6); + skb_reserve(new_skb, 6); skb_put(new_skb, len); bnx2_reuse_rx_skb(bp, rxr, skb, @@ -2941,6 +2943,25 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) dma_addr, (sw_ring_cons << 16) | sw_ring_prod))) goto next_rx; + if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) && + !(bp->rx_mode & BNX2_EMAC_RX_MODE_KEEP_VLAN_TAG)) { + vtag = rx_hdr->l2_fhdr_vlan_tag; +#ifdef BCM_VLAN + if (bp->vlgrp) + hw_vlan = 1; + else +#endif + { + struct vlan_ethhdr *ve = (struct vlan_ethhdr *) + __skb_push(skb, 4); + + memmove(ve, skb->data + 4, ETH_ALEN * 2); + ve->h_vlan_proto = htons(ETH_P_8021Q); + ve->h_vlan_TCI = htons(vtag); + len += 4; + } + } + skb->protocol = eth_type_trans(skb, bp->dev); if ((len > (bp->dev->mtu + ETH_HLEN)) && @@ -2962,10 +2983,8 @@ bnx2_rx_int(struct bnx2 *bp, struct bnx2_napi *bnapi, int budget) } #ifdef BCM_VLAN - if ((status & L2_FHDR_STATUS_L2_VLAN_TAG) && bp->vlgrp) { - vlan_hwaccel_receive_skb(skb, bp->vlgrp, - rx_hdr->l2_fhdr_vlan_tag); - } + if (hw_vlan) + vlan_hwaccel_receive_skb(skb, bp->vlgrp, vtag); else #endif netif_receive_skb(skb); -- cgit v1.1 From 0eb8b1fe9238ca4c1797e4c105d5790abda1726f Mon Sep 17 00:00:00 2001 From: Michael Chan Date: Thu, 14 Aug 2008 15:30:31 -0700 Subject: bnx2: Update version to 1.8.0. Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 1f2e76f..d454810 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -57,8 +57,8 @@ #define DRV_MODULE_NAME "bnx2" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "1.7.9" -#define DRV_MODULE_RELDATE "July 18, 2008" +#define DRV_MODULE_VERSION "1.8.0" +#define DRV_MODULE_RELDATE "Aug 14, 2008" #define RUN_AT(x) (jiffies + (x)) -- cgit v1.1 From 7ec01ff950c455aa1f1ccfaf347eb1aa9ec160d5 Mon Sep 17 00:00:00 2001 From: Ralph Campbell Date: Fri, 15 Aug 2008 11:23:47 -0700 Subject: IB/ipath: Fix lost UD send work request If a UD QP has some work requests queued to be sent by the DMA engine followed by a local loopback work request, we have to wait for the previous work requests to finish or the completion for the local loopback work request would be generated out of order. The problem was that the work request queue pointer was already updated so that the request would not be processed when the DMA queue drained. Signed-off-by: Ralph Campbell Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_ud.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ipath/ipath_ud.c b/drivers/infiniband/hw/ipath/ipath_ud.c index 36aa242..729446f 100644 --- a/drivers/infiniband/hw/ipath/ipath_ud.c +++ b/drivers/infiniband/hw/ipath/ipath_ud.c @@ -267,6 +267,7 @@ int ipath_make_ud_req(struct ipath_qp *qp) u16 lrh0; u16 lid; int ret = 0; + int next_cur; spin_lock_irqsave(&qp->s_lock, flags); @@ -290,8 +291,9 @@ int ipath_make_ud_req(struct ipath_qp *qp) goto bail; wqe = get_swqe_ptr(qp, qp->s_cur); - if (++qp->s_cur >= qp->s_size) - qp->s_cur = 0; + next_cur = qp->s_cur + 1; + if (next_cur >= qp->s_size) + next_cur = 0; /* Construct the header. */ ah_attr = &to_iah(wqe->wr.wr.ud.ah)->attr; @@ -315,6 +317,7 @@ int ipath_make_ud_req(struct ipath_qp *qp) qp->s_flags |= IPATH_S_WAIT_DMA; goto bail; } + qp->s_cur = next_cur; spin_unlock_irqrestore(&qp->s_lock, flags); ipath_ud_loopback(qp, wqe); spin_lock_irqsave(&qp->s_lock, flags); @@ -323,6 +326,7 @@ int ipath_make_ud_req(struct ipath_qp *qp) } } + qp->s_cur = next_cur; extra_bytes = -wqe->length & 3; nwords = (wqe->length + extra_bytes) >> 2; -- cgit v1.1 From 24babadec0209e5f84c067cb89aca6515486d35c Mon Sep 17 00:00:00 2001 From: Dave Olson Date: Fri, 15 Aug 2008 11:25:20 -0700 Subject: IB/ipath: Fix incorrect check for max physical address in TID The check for max physical address was incorrect, thus limiting the range of allowed physical addresses. Signed-off-by: Dave Olson Signed-off-by: Roland Dreier --- drivers/infiniband/hw/ipath/ipath_iba7220.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/infiniband/hw/ipath/ipath_iba7220.c b/drivers/infiniband/hw/ipath/ipath_iba7220.c index d90f5e9..9839e20 100644 --- a/drivers/infiniband/hw/ipath/ipath_iba7220.c +++ b/drivers/infiniband/hw/ipath/ipath_iba7220.c @@ -1720,7 +1720,7 @@ static void ipath_7220_put_tid(struct ipath_devdata *dd, u64 __iomem *tidptr, "not 2KB aligned!\n", pa); return; } - if (pa >= (1UL << IBA7220_TID_SZ_SHIFT)) { + if (chippa >= (1UL << IBA7220_TID_SZ_SHIFT)) { ipath_dev_err(dd, "BUG: Physical page address 0x%lx " "larger than supported\n", pa); -- cgit v1.1 From 77b483f132ba25edf4ef455dd87a91ab7bbf4170 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 15 Aug 2008 14:07:24 -0700 Subject: tg3: Add APE register access locking If the driver resets the chip while the APE is performing a register access, that register access will never complete and the APE will hang indefinitely. To prevent this race condition, the driver must acquire an APE mutex before resetting the chip. The APE will not attempt a register access until it acquires this lock. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 6 ++++++ drivers/net/tg3.h | 1 + 2 files changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index d2439b8..e3fd74b 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -536,6 +536,7 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum) return 0; switch (locknum) { + case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: break; default: @@ -573,6 +574,7 @@ static void tg3_ape_unlock(struct tg3 *tp, int locknum) return; switch (locknum) { + case TG3_APE_LOCK_GRC: case TG3_APE_LOCK_MEM: break; default: @@ -5760,6 +5762,8 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_mdio_stop(tp); + tg3_ape_lock(tp, TG3_APE_LOCK_GRC); + /* No matching tg3_nvram_unlock() after this because * chip reset below will undo the nvram lock. */ @@ -5914,6 +5918,8 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_mdio_start(tp); + tg3_ape_unlock(tp, TG3_APE_LOCK_GRC); + err = tg3_poll_fw(tp); if (err) return err; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index df07842..dd1af50 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -1889,6 +1889,7 @@ #define APE_EVENT_STATUS_EVENT_PENDING 0x80000000 /* APE convenience enumerations. */ +#define TG3_APE_LOCK_GRC 1 #define TG3_APE_LOCK_MEM 4 #define TG3_EEPROM_SB_F1R2_MBA_OFF 0x10 -- cgit v1.1 From 731fd79c133dc04cabee17ecfa7661189a8df5c8 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 15 Aug 2008 14:07:51 -0700 Subject: tg3: Refine APE status check Recently, more status bits have been added to the APE status register. This patch refines the status register check so that the driver can send more events than it would have otherwise. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e3fd74b..13640f1 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5495,7 +5495,7 @@ static void tg3_ape_send_event(struct tg3 *tp, u32 event) return; apedata = tg3_ape_read32(tp, TG3_APE_FW_STATUS); - if (apedata != APE_FW_STATUS_READY) + if (!(apedata & APE_FW_STATUS_READY)) return; /* Wait for up to 1 millisecond for APE to service previous event. */ -- cgit v1.1 From 3bda12589646caa22b2ed4ef7cf82d17ea59d7a6 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 15 Aug 2008 14:08:22 -0700 Subject: tg3: Preserve register settings for DASH Broadcom's DASH (Desktop and mobile Architecture for System Hardware) implementation requires that the driver preserve particular register settings. If the driver does not preserve them, communication with the DASH firmware will be lost. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 26 ++++++++++++++++++++++++-- drivers/net/tg3.h | 2 ++ 2 files changed, 26 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 13640f1..0ebf2ff 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -2126,6 +2126,13 @@ static int tg3_set_power_state(struct tg3 *tp, pci_power_t state) (tp->tg3_flags & TG3_FLAG_WOL_ENABLE)) mac_mode |= MAC_MODE_MAGIC_PKT_ENABLE; + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + mac_mode |= tp->mac_mode & + (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN); + if (mac_mode & MAC_MODE_APE_TX_EN) + mac_mode |= MAC_MODE_TDE_ENABLE; + } + tw32_f(MAC_MODE, mac_mode); udelay(100); @@ -5912,6 +5919,11 @@ static int tg3_chip_reset(struct tg3 *tp) } else if (tp->tg3_flags2 & TG3_FLG2_MII_SERDES) { tp->mac_mode = MAC_MODE_PORT_MODE_GMII; tw32_f(MAC_MODE, tp->mac_mode); + } else if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) { + tp->mac_mode &= (MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN); + if (tp->mac_mode & MAC_MODE_APE_TX_EN) + tp->mac_mode |= MAC_MODE_TDE_ENABLE; + tw32_f(MAC_MODE, tp->mac_mode); } else tw32_f(MAC_MODE, 0); udelay(40); @@ -7412,7 +7424,11 @@ static int tg3_reset_hw(struct tg3 *tp, int reset_phy) udelay(10); } - tp->mac_mode = MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + tp->mac_mode &= MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; + else + tp->mac_mode = 0; + tp->mac_mode |= MAC_MODE_TXSTAT_ENABLE | MAC_MODE_RXSTAT_ENABLE | MAC_MODE_TDE_ENABLE | MAC_MODE_RDE_ENABLE | MAC_MODE_FHDE_ENABLE; if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) && !(tp->tg3_flags2 & TG3_FLG2_PHY_SERDES) && @@ -12422,6 +12438,13 @@ static int __devinit tg3_get_invariants(struct tg3 *tp) tp->misc_host_ctrl); } + /* Preserve the APE MAC_MODE bits */ + if (tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) + tp->mac_mode = tr32(MAC_MODE) | + MAC_MODE_APE_TX_EN | MAC_MODE_APE_RX_EN; + else + tp->mac_mode = TG3_DEF_MAC_MODE; + /* these are limited to 10/100 only */ if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5703 && (grc_misc_cfg == 0x8000 || grc_misc_cfg == 0x4000)) || @@ -13281,7 +13304,6 @@ static int __devinit tg3_init_one(struct pci_dev *pdev, tp->pdev = pdev; tp->dev = dev; tp->pm_cap = pm_cap; - tp->mac_mode = TG3_DEF_MAC_MODE; tp->rx_mode = TG3_DEF_RX_MODE; tp->tx_mode = TG3_DEF_TX_MODE; diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index dd1af50..3772349 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -325,6 +325,8 @@ #define MAC_MODE_TDE_ENABLE 0x00200000 #define MAC_MODE_RDE_ENABLE 0x00400000 #define MAC_MODE_FHDE_ENABLE 0x00800000 +#define MAC_MODE_APE_RX_EN 0x08000000 +#define MAC_MODE_APE_TX_EN 0x10000000 #define MAC_STATUS 0x00000404 #define MAC_STATUS_PCS_SYNCED 0x00000001 #define MAC_STATUS_SIGNAL_DET 0x00000002 -- cgit v1.1 From bc7959b2cbb57393b625b423c73e6fd07610257f Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 15 Aug 2008 14:08:55 -0700 Subject: tg3: Turn off ASF "driver alive" heartbeats for APE The ENABLE_ASF flag is set when DASH is enabled on the NIC, but DASH does not run on the RX CPU. Instead it runs on the APE. Consequently, the driver does not need to send "driver alive" updates to the RX CPU when the APE is present. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0ebf2ff..e952b91 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -7862,7 +7862,8 @@ static void tg3_timer(unsigned long __opaque) * resets. */ if (!--tp->asf_counter) { - if (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) { + if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && + !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { u32 val; tg3_wait_for_event_ack(tp); -- cgit v1.1 From 4ba526ced990f4d61ee8d65fe8a6f0745e8e455c Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 15 Aug 2008 14:10:04 -0700 Subject: tg3: Fix firmware event timeouts The git commit 7c5026aa9b81dd45df8d3f4e0be73e485976a8b6 ("tg3: Add link state reporting to UMP firmware") introduced code that waits for previous firmware events to be serviced before attempting to submit a new event. Unfortunately that patch contained a bug that cause the driver to wait 2.5 seconds, rather than 2.5 milliseconds as intended. This patch fixes that bug. This bug revealed that not all firmware versions service driver events though. Since we do not know which versions of the firmware do and don't service these events, the driver needs some way to minimize the effects of the delay. This patch solves the problem by recording a jiffies timestamp when it submits an event to the hardware. If the jiffies counter shows that 2.5 milliseconds have already passed, a wait is not needed and the driver can proceed to submit a new event. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 53 +++++++++++++++++++++++++++++++++++++---------------- drivers/net/tg3.h | 3 +++ 2 files changed, 40 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index e952b91..c26011e 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -1020,15 +1020,43 @@ static void tg3_mdio_fini(struct tg3 *tp) } /* tp->lock is held. */ +static inline void tg3_generate_fw_event(struct tg3 *tp) +{ + u32 val; + + val = tr32(GRC_RX_CPU_EVENT); + val |= GRC_RX_CPU_DRIVER_EVENT; + tw32_f(GRC_RX_CPU_EVENT, val); + + tp->last_event_jiffies = jiffies; +} + +#define TG3_FW_EVENT_TIMEOUT_USEC 2500 + +/* tp->lock is held. */ static void tg3_wait_for_event_ack(struct tg3 *tp) { int i; + unsigned int delay_cnt; + long time_remain; + + /* If enough time has passed, no wait is necessary. */ + time_remain = (long)(tp->last_event_jiffies + 1 + + usecs_to_jiffies(TG3_FW_EVENT_TIMEOUT_USEC)) - + (long)jiffies; + if (time_remain < 0) + return; - /* Wait for up to 2.5 milliseconds */ - for (i = 0; i < 250000; i++) { + /* Check if we can shorten the wait time. */ + delay_cnt = jiffies_to_usecs(time_remain); + if (delay_cnt > TG3_FW_EVENT_TIMEOUT_USEC) + delay_cnt = TG3_FW_EVENT_TIMEOUT_USEC; + delay_cnt = (delay_cnt >> 3) + 1; + + for (i = 0; i < delay_cnt; i++) { if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT)) break; - udelay(10); + udelay(8); } } @@ -1077,9 +1105,7 @@ static void tg3_ump_link_report(struct tg3 *tp) val = 0; tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX + 12, val); - val = tr32(GRC_RX_CPU_EVENT); - val |= GRC_RX_CPU_DRIVER_EVENT; - tw32_f(GRC_RX_CPU_EVENT, val); + tg3_generate_fw_event(tp); } static void tg3_link_report(struct tg3 *tp) @@ -5953,6 +5979,7 @@ static int tg3_chip_reset(struct tg3 *tp) tg3_read_mem(tp, NIC_SRAM_DATA_CFG, &nic_cfg); if (nic_cfg & NIC_SRAM_DATA_CFG_ASF_ENABLE) { tp->tg3_flags |= TG3_FLAG_ENABLE_ASF; + tp->last_event_jiffies = jiffies; if (tp->tg3_flags2 & TG3_FLG2_5750_PLUS) tp->tg3_flags2 |= TG3_FLG2_ASF_NEW_HANDSHAKE; } @@ -5966,15 +5993,12 @@ static void tg3_stop_fw(struct tg3 *tp) { if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { - u32 val; - /* Wait for RX cpu to ACK the previous event. */ tg3_wait_for_event_ack(tp); tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, FWCMD_NICDRV_PAUSE_FW); - val = tr32(GRC_RX_CPU_EVENT); - val |= GRC_RX_CPU_DRIVER_EVENT; - tw32(GRC_RX_CPU_EVENT, val); + + tg3_generate_fw_event(tp); /* Wait for RX cpu to ACK this event. */ tg3_wait_for_event_ack(tp); @@ -7864,8 +7888,6 @@ static void tg3_timer(unsigned long __opaque) if (!--tp->asf_counter) { if ((tp->tg3_flags & TG3_FLAG_ENABLE_ASF) && !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE)) { - u32 val; - tg3_wait_for_event_ack(tp); tg3_write_mem(tp, NIC_SRAM_FW_CMD_MBOX, @@ -7873,9 +7895,8 @@ static void tg3_timer(unsigned long __opaque) tg3_write_mem(tp, NIC_SRAM_FW_CMD_LEN_MBOX, 4); /* 5 seconds timeout */ tg3_write_mem(tp, NIC_SRAM_FW_CMD_DATA_MBOX, 5); - val = tr32(GRC_RX_CPU_EVENT); - val |= GRC_RX_CPU_DRIVER_EVENT; - tw32_f(GRC_RX_CPU_EVENT, val); + + tg3_generate_fw_event(tp); } tp->asf_counter = tp->asf_multiplier; } diff --git a/drivers/net/tg3.h b/drivers/net/tg3.h index 3772349..f5b8cab 100644 --- a/drivers/net/tg3.h +++ b/drivers/net/tg3.h @@ -2432,7 +2432,10 @@ struct tg3 { struct tg3_ethtool_stats estats; struct tg3_ethtool_stats estats_prev; + union { unsigned long phy_crc_errors; + unsigned long last_event_jiffies; + }; u32 rx_offset; u32 tg3_flags; -- cgit v1.1 From 816f8b86621000fc82e16ae5f172164de761d5eb Mon Sep 17 00:00:00 2001 From: Stefan Buehler Date: Fri, 15 Aug 2008 14:10:54 -0700 Subject: tg3: fix 64 bit counter for ethtool stats Ethtool stats are 64-bits in length. net_device_stats members are unsigned long types. When gathering information for a get_ethtool_stats call, the driver will call a driver-private, inlined get_stat64() function, which returns an unsigned long value. This call will inadvertently mask off the upper 32-bits of a stat on 32-bit machines. This patch defines a new get_estat() inline function and modifies the ESTAT_ADD() macro to use it. Signed-off-by: Stefan Buehler Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index c26011e..ada1d0d 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -8466,6 +8466,11 @@ static inline unsigned long get_stat64(tg3_stat64_t *val) return ret; } +static inline u64 get_estat64(tg3_stat64_t *val) +{ + return ((u64)val->high << 32) | ((u64)val->low); +} + static unsigned long calc_crc_errors(struct tg3 *tp) { struct tg3_hw_stats *hw_stats = tp->hw_stats; @@ -8494,7 +8499,7 @@ static unsigned long calc_crc_errors(struct tg3 *tp) #define ESTAT_ADD(member) \ estats->member = old_estats->member + \ - get_stat64(&hw_stats->member) + get_estat64(&hw_stats->member) static struct tg3_ethtool_stats *tg3_get_estats(struct tg3 *tp) { -- cgit v1.1 From 23197916c447a1623d196e6547781180905f0bb2 Mon Sep 17 00:00:00 2001 From: Matt Carlson Date: Fri, 15 Aug 2008 14:11:19 -0700 Subject: tg3: Update version to 3.94 This patch updates the version number to 3.94. Signed-off-by: Matt Carlson Signed-off-by: Michael Chan Signed-off-by: David S. Miller --- drivers/net/tg3.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index ada1d0d..71d2c5c 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -66,8 +66,8 @@ #define DRV_MODULE_NAME "tg3" #define PFX DRV_MODULE_NAME ": " -#define DRV_MODULE_VERSION "3.93" -#define DRV_MODULE_RELDATE "May 22, 2008" +#define DRV_MODULE_VERSION "3.94" +#define DRV_MODULE_RELDATE "August 14, 2008" #define TG3_DEF_MAC_MODE 0 #define TG3_DEF_RX_MODE 0 -- cgit v1.1 From f22f8567cb0a530d8958d177e0f268783bd0d894 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 15 Aug 2008 14:52:08 -0700 Subject: loopback: Enable TSO This patch enables TSO since the loopback device is naturally capable of handling packets of any size. This also means that we won't enable GSO on lo which is good until GSO is fixed to preserve netfilter state as netfilter treats loopback packets in a special way. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/loopback.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 49f6bc0..46e87cc 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -234,9 +234,7 @@ static void loopback_setup(struct net_device *dev) dev->type = ARPHRD_LOOPBACK; /* 0x0001*/ dev->flags = IFF_LOOPBACK; dev->features = NETIF_F_SG | NETIF_F_FRAGLIST -#ifdef LOOPBACK_TSO | NETIF_F_TSO -#endif | NETIF_F_NO_CSUM | NETIF_F_HIGHDMA | NETIF_F_LLTX -- cgit v1.1 From 7447ef63cf2dfdc444f4c72ae13f604350b2e25f Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 15 Aug 2008 14:54:03 -0700 Subject: loopback: Remove rest of LOOPBACK_TSO code. It hasn't been enabled for a long time and the generic GSO engine is better documentation of what is expected of a device implementing TSO. Signed-off-by: David S. Miller --- drivers/net/loopback.c | 62 -------------------------------------------------- 1 file changed, 62 deletions(-) (limited to 'drivers') diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 46e87cc..489d53b 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -64,68 +64,6 @@ struct pcpu_lstats { unsigned long bytes; }; -/* KISS: just allocate small chunks and copy bits. - * - * So, in fact, this is documentation, explaining what we expect - * of largesending device modulo TCP checksum, which is ignored for loopback. - */ - -#ifdef LOOPBACK_TSO -static void emulate_large_send_offload(struct sk_buff *skb) -{ - struct iphdr *iph = ip_hdr(skb); - struct tcphdr *th = (struct tcphdr *)(skb_network_header(skb) + - (iph->ihl * 4)); - unsigned int doffset = (iph->ihl + th->doff) * 4; - unsigned int mtu = skb_shinfo(skb)->gso_size + doffset; - unsigned int offset = 0; - u32 seq = ntohl(th->seq); - u16 id = ntohs(iph->id); - - while (offset + doffset < skb->len) { - unsigned int frag_size = min(mtu, skb->len - offset) - doffset; - struct sk_buff *nskb = alloc_skb(mtu + 32, GFP_ATOMIC); - - if (!nskb) - break; - skb_reserve(nskb, 32); - skb_set_mac_header(nskb, -ETH_HLEN); - skb_reset_network_header(nskb); - iph = ip_hdr(nskb); - skb_copy_to_linear_data(nskb, skb_network_header(skb), - doffset); - if (skb_copy_bits(skb, - doffset + offset, - nskb->data + doffset, - frag_size)) - BUG(); - skb_put(nskb, doffset + frag_size); - nskb->ip_summed = CHECKSUM_UNNECESSARY; - nskb->dev = skb->dev; - nskb->priority = skb->priority; - nskb->protocol = skb->protocol; - nskb->dst = dst_clone(skb->dst); - memcpy(nskb->cb, skb->cb, sizeof(skb->cb)); - nskb->pkt_type = skb->pkt_type; - - th = (struct tcphdr *)(skb_network_header(nskb) + iph->ihl * 4); - iph->tot_len = htons(frag_size + doffset); - iph->id = htons(id); - iph->check = 0; - iph->check = ip_fast_csum((unsigned char *) iph, iph->ihl); - th->seq = htonl(seq); - if (offset + doffset + frag_size < skb->len) - th->fin = th->psh = 0; - netif_rx(nskb); - offset += frag_size; - seq += frag_size; - id++; - } - - dev_kfree_skb(skb); -} -#endif /* LOOPBACK_TSO */ - /* * The higher levels take care of making this non-reentrant (it's * called with bh's disabled). -- cgit v1.1 From 04a0551c87363f100b04d28d7a15a632b70e18e7 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 15 Aug 2008 14:56:37 -0700 Subject: loopback: Drop obsolete ip_summed setting Now that the network stack can handle inbound packets with partial checksums, we should no longer clobber the ip_summed field in the loopback driver. This is because CHECKSUM_UNNECESSARY implies that the checksum field is actually valid which is not true for loopback packets since it's only partial (and thus complemented). This allows packets from lo to then be SNATed to an external source while still preserving the checksum's validity. Signed-off-by: Herbert Xu Signed-off-by: David S. Miller --- drivers/net/loopback.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 489d53b..3b43bfd 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c @@ -75,9 +75,6 @@ static int loopback_xmit(struct sk_buff *skb, struct net_device *dev) skb_orphan(skb); skb->protocol = eth_type_trans(skb,dev); -#ifndef LOOPBACK_MUST_CHECKSUM - skb->ip_summed = CHECKSUM_UNNECESSARY; -#endif #ifdef LOOPBACK_TSO if (skb_is_gso(skb)) { -- cgit v1.1 From e3b99556975907530aeb9745e7b3945a0da48f17 Mon Sep 17 00:00:00 2001 From: Mark McLoughlin Date: Fri, 15 Aug 2008 15:09:56 -0700 Subject: tun: TUNGETIFF interface to query name and flags Add a TUNGETIFF interface so that userspace can query a tun/tap descriptor for its name and flags. This is needed because it is common for one app to create a tap interface, exec another app and pass it the file descriptor for the interface. Without TUNGETIFF the spawned app has no way of detecting wheter the interface has e.g. IFF_VNET_HDR set. Signed-off-by: Mark McLoughlin Acked-by: Max Krasnyansky Signed-off-by: David S. Miller --- drivers/net/tun.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index e6bbc63..95931a5 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -748,6 +748,36 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) return err; } +static int tun_get_iff(struct net *net, struct file *file, struct ifreq *ifr) +{ + struct tun_struct *tun = file->private_data; + + if (!tun) + return -EBADFD; + + DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name); + + strcpy(ifr->ifr_name, tun->dev->name); + + ifr->ifr_flags = 0; + + if (ifr->ifr_flags & TUN_TUN_DEV) + ifr->ifr_flags |= IFF_TUN; + else + ifr->ifr_flags |= IFF_TAP; + + if (tun->flags & TUN_NO_PI) + ifr->ifr_flags |= IFF_NO_PI; + + if (tun->flags & TUN_ONE_QUEUE) + ifr->ifr_flags |= IFF_ONE_QUEUE; + + if (tun->flags & TUN_VNET_HDR) + ifr->ifr_flags |= IFF_VNET_HDR; + + return 0; +} + /* This is like a cut-down ethtool ops, except done via tun fd so no * privs required. */ static int set_offload(struct net_device *dev, unsigned long arg) @@ -833,6 +863,15 @@ static int tun_chr_ioctl(struct inode *inode, struct file *file, DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd); switch (cmd) { + case TUNGETIFF: + ret = tun_get_iff(current->nsproxy->net_ns, file, &ifr); + if (ret) + return ret; + + if (copy_to_user(argp, &ifr, sizeof(ifr))) + return -EFAULT; + break; + case TUNSETNOCSUM: /* Disable/Enable checksum */ if (arg) -- cgit v1.1 From f42157cb568c1eb02eca7df4da67553a9edae24a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 15 Aug 2008 15:15:10 -0700 Subject: tun: fallback if skb_alloc() fails on big packets skb_alloc produces linear packets (using kmalloc()). That can fail, so should we fall back to making paged skbs. My original version of this patch always allocate paged skbs for big packets. But that made performance drop from 8.4 seconds to 8.8 seconds on 1G lguest->Host TCP xmit. So now we only do that as a fallback. Signed-off-by: Rusty Russell Acked-by: Max Krasnyansky Signed-off-by: David S. Miller --- drivers/net/tun.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 95931a5..6daea0c 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -358,6 +358,66 @@ static unsigned int tun_chr_poll(struct file *file, poll_table * wait) return mask; } +/* prepad is the amount to reserve at front. len is length after that. + * linear is a hint as to how much to copy (usually headers). */ +static struct sk_buff *tun_alloc_skb(size_t prepad, size_t len, size_t linear, + gfp_t gfp) +{ + struct sk_buff *skb; + unsigned int i; + + skb = alloc_skb(prepad + len, gfp|__GFP_NOWARN); + if (skb) { + skb_reserve(skb, prepad); + skb_put(skb, len); + return skb; + } + + /* Under a page? Don't bother with paged skb. */ + if (prepad + len < PAGE_SIZE) + return NULL; + + /* Start with a normal skb, and add pages. */ + skb = alloc_skb(prepad + linear, gfp); + if (!skb) + return NULL; + + skb_reserve(skb, prepad); + skb_put(skb, linear); + + len -= linear; + + for (i = 0; i < MAX_SKB_FRAGS; i++) { + skb_frag_t *f = &skb_shinfo(skb)->frags[i]; + + f->page = alloc_page(gfp|__GFP_ZERO); + if (!f->page) + break; + + f->page_offset = 0; + f->size = PAGE_SIZE; + + skb->data_len += PAGE_SIZE; + skb->len += PAGE_SIZE; + skb->truesize += PAGE_SIZE; + skb_shinfo(skb)->nr_frags++; + + if (len < PAGE_SIZE) { + len = 0; + break; + } + len -= PAGE_SIZE; + } + + /* Too large, or alloc fail? */ + if (unlikely(len)) { + kfree_skb(skb); + skb = NULL; + } + + return skb; +} + /* Get packet from user space buffer */ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, size_t count) { @@ -391,14 +451,12 @@ static __inline__ ssize_t tun_get_user(struct tun_struct *tun, struct iovec *iv, return -EINVAL; } - if (!(skb = alloc_skb(len + align, GFP_KERNEL))) { + if (!(skb = tun_alloc_skb(align, len, gso.hdr_len, GFP_KERNEL))) { tun->dev->stats.rx_dropped++; return -ENOMEM; } - if (align) - skb_reserve(skb, align); - if (memcpy_fromiovec(skb_put(skb, len), iv, len)) { + if (skb_copy_datagram_from_iovec(skb, 0, iv, len)) { tun->dev->stats.rx_dropped++; kfree_skb(skb); return -EFAULT; -- cgit v1.1 From 08013fa353fdcfc0a03cae805393abfc56722387 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Fri, 15 Aug 2008 19:46:01 -0700 Subject: bnx2: Fix build with VLAN_8021Q disabled. Reported by Randy Dunlap. Signed-off-by: David S. Miller --- drivers/net/bnx2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index d454810..2486a65 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -35,8 +35,8 @@ #include #include #include -#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #include +#if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE) #define BCM_VLAN 1 #endif #include -- cgit v1.1 From 06f579dee5dd75c2aaf8fe83d034b5470eeee2f4 Mon Sep 17 00:00:00 2001 From: "Yang, Bo" Date: Sun, 10 Aug 2008 12:42:37 -0700 Subject: [SCSI] megaraid_sas: add readl to force PCI posting flush MegaRAID SAS Driver get unexpected Interrupt. Add the dummy readl to force PCI flush will fix this issue. Signed-off-by: Bo Yang Signed-off-by: Andrew Morton Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index fc7ac15..d7b9984 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -198,6 +198,9 @@ megasas_clear_intr_xscale(struct megasas_register_set __iomem * regs) */ writel(status, ®s->outbound_intr_status); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_status); + return 0; } @@ -293,6 +296,9 @@ megasas_clear_intr_ppc(struct megasas_register_set __iomem * regs) */ writel(status, ®s->outbound_doorbell_clear); + /* Dummy readl to force pci flush */ + readl(®s->outbound_doorbell_clear); + return 0; } /** -- cgit v1.1 From 530e6fc1e05f14762aea954ca8d6422c5a7077c1 Mon Sep 17 00:00:00 2001 From: "Yang, Bo" Date: Sun, 10 Aug 2008 12:42:37 -0700 Subject: [SCSI] megaraid_sas: add the shutdown DCMD cmd to driver shutdown routine Add the shutdown DCMD cmd to driver shutdown routine to make megaraid sas FW shutdown proper. Signed-off-by: Bo Yang Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index d7b9984..e880cd4 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -2863,6 +2863,7 @@ static void megasas_shutdown(struct pci_dev *pdev) { struct megasas_instance *instance = pci_get_drvdata(pdev); megasas_flush_cache(instance); + megasas_shutdown_controller(instance, MR_DCMD_CTRL_SHUTDOWN); } /** -- cgit v1.1 From 6610a6b354d6c3377a1e79cd1d760ffe4358245c Mon Sep 17 00:00:00 2001 From: "Yang, Bo" Date: Sun, 10 Aug 2008 12:42:38 -0700 Subject: [SCSI] megaraid_sas: add new controllers (0x78 0x79) Add the new controllers (0x78 0x79) support to the driver. Those controllers are LSI's next generation (gen2) SAS controllers. [akpm@linux-foundation.org: coding-style fixes] [akpm@linux-foundation.org: parenthesise a macro] Signed-off-by: Bo Yang Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.c | 110 ++++++++++++++++++++++++++++++++++- drivers/scsi/megaraid/megaraid_sas.h | 4 ++ 2 files changed, 112 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index e880cd4..870dc1c 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -10,7 +10,7 @@ * 2 of the License, or (at your option) any later version. * * FILE : megaraid_sas.c - * Version : v00.00.03.20-rc1 + * Version : v00.00.04.01-rc1 * * Authors: * (email-id : megaraidlinux@lsi.com) @@ -71,6 +71,10 @@ static struct pci_device_id megasas_pci_table[] = { /* ppc IOP */ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078DE)}, /* ppc IOP */ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS1078GEN2)}, + /* gen2*/ + {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_SAS0079GEN2)}, + /* gen2*/ {PCI_DEVICE(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_VERDE_ZCR)}, /* xscale IOP, vega */ {PCI_DEVICE(PCI_VENDOR_ID_DELL, PCI_DEVICE_ID_DELL_PERC5)}, @@ -324,6 +328,99 @@ static struct megasas_instance_template megasas_instance_template_ppc = { }; /** +* The following functions are defined for gen2 (deviceid : 0x78 0x79) +* controllers +*/ + +/** + * megasas_enable_intr_gen2 - Enables interrupts + * @regs: MFI register set + */ +static inline void +megasas_enable_intr_gen2(struct megasas_register_set __iomem *regs) +{ + writel(0xFFFFFFFF, &(regs)->outbound_doorbell_clear); + + /* write ~0x00000005 (4 & 1) to the intr mask*/ + writel(~MFI_GEN2_ENABLE_INTERRUPT_MASK, &(regs)->outbound_intr_mask); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_disable_intr_gen2 - Disables interrupt + * @regs: MFI register set + */ +static inline void +megasas_disable_intr_gen2(struct megasas_register_set __iomem *regs) +{ + u32 mask = 0xFFFFFFFF; + writel(mask, ®s->outbound_intr_mask); + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_mask); +} + +/** + * megasas_read_fw_status_reg_gen2 - returns the current FW status value + * @regs: MFI register set + */ +static u32 +megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs) +{ + return readl(&(regs)->outbound_scratch_pad); +} + +/** + * megasas_clear_interrupt_gen2 - Check & clear interrupt + * @regs: MFI register set + */ +static int +megasas_clear_intr_gen2(struct megasas_register_set __iomem *regs) +{ + u32 status; + /* + * Check if it is our interrupt + */ + status = readl(®s->outbound_intr_status); + + if (!(status & MFI_GEN2_ENABLE_INTERRUPT_MASK)) + return 1; + + /* + * Clear the interrupt by writing back the same value + */ + writel(status, ®s->outbound_doorbell_clear); + + /* Dummy readl to force pci flush */ + readl(®s->outbound_intr_status); + + return 0; +} +/** + * megasas_fire_cmd_gen2 - Sends command to the FW + * @frame_phys_addr : Physical address of cmd + * @frame_count : Number of frames for the command + * @regs : MFI register set + */ +static inline void +megasas_fire_cmd_gen2(dma_addr_t frame_phys_addr, u32 frame_count, + struct megasas_register_set __iomem *regs) +{ + writel((frame_phys_addr | (frame_count<<1))|1, + &(regs)->inbound_queue_port); +} + +static struct megasas_instance_template megasas_instance_template_gen2 = { + + .fire_cmd = megasas_fire_cmd_gen2, + .enable_intr = megasas_enable_intr_gen2, + .disable_intr = megasas_disable_intr_gen2, + .clear_intr = megasas_clear_intr_gen2, + .read_fw_status_reg = megasas_read_fw_status_reg_gen2, +}; + +/** * This is the end of set of functions & definitions * specific to ppc (deviceid : 0x60) controllers */ @@ -1982,7 +2079,12 @@ static int megasas_init_mfi(struct megasas_instance *instance) /* * Map the message registers */ - instance->base_addr = pci_resource_start(instance->pdev, 0); + if ((instance->pdev->device == PCI_DEVICE_ID_LSI_SAS1078GEN2) || + (instance->pdev->device == PCI_DEVICE_ID_LSI_SAS0079GEN2)) { + instance->base_addr = pci_resource_start(instance->pdev, 1); + } else { + instance->base_addr = pci_resource_start(instance->pdev, 0); + } if (pci_request_regions(instance->pdev, "megasas: LSI")) { printk(KERN_DEBUG "megasas: IO memory region busy!\n"); @@ -2004,6 +2106,10 @@ static int megasas_init_mfi(struct megasas_instance *instance) case PCI_DEVICE_ID_LSI_SAS1078DE: instance->instancet = &megasas_instance_template_ppc; break; + case PCI_DEVICE_ID_LSI_SAS1078GEN2: + case PCI_DEVICE_ID_LSI_SAS0079GEN2: + instance->instancet = &megasas_instance_template_gen2; + break; case PCI_DEVICE_ID_LSI_SAS1064R: case PCI_DEVICE_ID_DELL_PERC5: default: diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index b0c41e6..7072ff2 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -28,6 +28,8 @@ #define PCI_DEVICE_ID_LSI_SAS1078R 0x0060 #define PCI_DEVICE_ID_LSI_SAS1078DE 0x007C #define PCI_DEVICE_ID_LSI_VERDE_ZCR 0x0413 +#define PCI_DEVICE_ID_LSI_SAS1078GEN2 0x0078 +#define PCI_DEVICE_ID_LSI_SAS0079GEN2 0x0079 /* * ===================================== @@ -580,6 +582,8 @@ struct megasas_ctrl_info { #define MEGASAS_COMPLETION_TIMER_INTERVAL (HZ/10) #define MFI_REPLY_1078_MESSAGE_INTERRUPT 0x80000000 +#define MFI_REPLY_GEN2_MESSAGE_INTERRUPT 0x00000001 +#define MFI_GEN2_ENABLE_INTERRUPT_MASK (0x00000001 | 0x00000004) /* * register set for both 1068 and 1078 controllers -- cgit v1.1 From 24541f99ba7231de26355d1cb87ab06e0f593efb Mon Sep 17 00:00:00 2001 From: "Yang, Bo" Date: Sun, 10 Aug 2008 12:42:39 -0700 Subject: [SCSI] megaraid_sas: version and Documentation Update Signed-off-by: Bo Yang Signed-off-by: Andrew Morton Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.h b/drivers/scsi/megaraid/megaraid_sas.h index 7072ff2..0d03324 100644 --- a/drivers/scsi/megaraid/megaraid_sas.h +++ b/drivers/scsi/megaraid/megaraid_sas.h @@ -18,9 +18,9 @@ /* * MegaRAID SAS Driver meta data */ -#define MEGASAS_VERSION "00.00.03.20-rc1" -#define MEGASAS_RELDATE "March 10, 2008" -#define MEGASAS_EXT_VERSION "Mon. March 10 11:02:31 PDT 2008" +#define MEGASAS_VERSION "00.00.04.01" +#define MEGASAS_RELDATE "July 24, 2008" +#define MEGASAS_EXT_VERSION "Thu July 24 11:41:51 PST 2008" /* * Device IDs -- cgit v1.1 From 8479fca119fac63538af9e313ad0b8658cbbe662 Mon Sep 17 00:00:00 2001 From: Chandra Seetharaman Date: Tue, 12 Aug 2008 17:26:58 -0700 Subject: [SCSI] scsi_dh: Do not use scsilun in rdac hardware handler RDAC storage controller doesn't seem to use the scsilun format. It uses only the last byte for LUN. Signed-off-by: Chandra Seetharaman Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_rdac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index b093a50..8636546 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -376,7 +376,7 @@ static int get_lun(struct scsi_device *sdev, struct rdac_dh_data *h) if (inqp->page_id[0] != 'e' || inqp->page_id[1] != 'd' || inqp->page_id[2] != 'i' || inqp->page_id[3] != 'd') return SCSI_DH_NOSYS; - h->lun = scsilun_to_int((struct scsi_lun *)inqp->lun); + h->lun = inqp->lun[7]; /* Uses only the last byte */ } return err; } -- cgit v1.1 From fe42625cdf0d4e06f01e365897a64b68d7f7de7d Mon Sep 17 00:00:00 2001 From: Chandra Seetharaman Date: Tue, 12 Aug 2008 17:26:59 -0700 Subject: [SCSI] scsi_dh: Initialize lun_state in check_ownership() lun_state need to be initialized inside check_ownership(). Signed-off-by: Chandra Seetharaman Signed-off-by: James Bottomley --- drivers/scsi/device_handler/scsi_dh_rdac.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/scsi/device_handler/scsi_dh_rdac.c b/drivers/scsi/device_handler/scsi_dh_rdac.c index 8636546..518da83 100644 --- a/drivers/scsi/device_handler/scsi_dh_rdac.c +++ b/drivers/scsi/device_handler/scsi_dh_rdac.c @@ -386,6 +386,7 @@ static int check_ownership(struct scsi_device *sdev, struct rdac_dh_data *h) int err; struct c9_inquiry *inqp; + h->lun_state = RDAC_LUN_UNOWNED; err = submit_inquiry(sdev, 0xC9, sizeof(struct c9_inquiry), h); if (err == SCSI_DH_OK) { inqp = &h->inq.c9; -- cgit v1.1 From 6390d1f33faecf48e31f27dd7dbe928540f8acfc Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 13 Aug 2008 21:36:56 -0700 Subject: [SCSI] qla2xxx: Correct synchronization of software/firmware fcport states. Greg Wettstein (greg@enjellic.com) noted: http://article.gmane.org/gmane.linux.scsi/43409 on a reboot of a previously recognized SCST target, the initiator driver would be unable to re-recognize the device as a target. It turns out that prior to the SCST software reloading and returning it's "target-capable" abilities in the PRLI payload, the HBA would be re-initialized as an initiator-only type port. Since initiators typically classify themselves as an FCP-2 capable device, both software and firmware do not perform an explicit logout during port-loss. Unfortunately, as can be seen by the failure case, when the port (now target-capable) returns, firmware performs an ADISC without a follow-on PRLI, leaving stale 'initiator-only' data in the firmware's port database. Correct the discrepancy by performing the explicit logout during the transport's request to terminate-rport-io, thus synchronizing port states and ensuring a follow-on PRLI is performed. Reported-by: Greg Wettstein Signed-off-by: Andrew Vasquez Cc: Stable Tree Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_attr.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c index a319a20..45e7dcb 100644 --- a/drivers/scsi/qla2xxx/qla_attr.c +++ b/drivers/scsi/qla2xxx/qla_attr.c @@ -993,6 +993,17 @@ qla2x00_terminate_rport_io(struct fc_rport *rport) { fc_port_t *fcport = *(fc_port_t **)rport->dd_data; + /* + * At this point all fcport's software-states are cleared. Perform any + * final cleanup of firmware resources (PCBs and XCBs). + */ + if (fcport->loop_id != FC_NO_LOOP_ID) { + fcport->ha->isp_ops->fabric_logout(fcport->ha, fcport->loop_id, + fcport->d_id.b.domain, fcport->d_id.b.area, + fcport->d_id.b.al_pa); + fcport->loop_id = FC_NO_LOOP_ID; + } + qla2x00_abort_fcport_cmds(fcport); scsi_target_unblock(&rport->dev); } -- cgit v1.1 From a7a28504bfa61dc6caa495f55c52623d10b42b32 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 13 Aug 2008 21:36:57 -0700 Subject: [SCSI] qla2xxx: Correct vport-state management issues during ISP-ABORT. * Use correct 'ha' to mark a device lost from ISR. I/Os will always be returned on the physical-HA. qla2x00_mark_device_lost() should be called with the HA bound to the fcport. * Mark *all* devices lost during ISP-ABORT (bighammer). These fixes correct issues discovered locally where during link-perturbation and heavy vport-I/O fcport/rport states would stray and an rport's scsi-target lost (timed-out). Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 3 +++ drivers/scsi/qla2xxx/qla_isr.c | 7 +++---- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index 601a6b2..e1de7a6 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -3251,6 +3251,7 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) { int rval; uint8_t status = 0; + scsi_qla_host_t *vha; if (ha->flags.online) { ha->flags.online = 0; @@ -3265,6 +3266,8 @@ qla2x00_abort_isp(scsi_qla_host_t *ha) if (atomic_read(&ha->loop_state) != LOOP_DOWN) { atomic_set(&ha->loop_state, LOOP_DOWN); qla2x00_mark_all_devices_lost(ha, 0); + list_for_each_entry(vha, &ha->vp_list, vp_list) + qla2x00_mark_all_devices_lost(vha, 0); } else { if (!atomic_read(&ha->loop_down_timer)) atomic_set(&ha->loop_down_timer, diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index 874d802..d6a1a66 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -1184,9 +1184,8 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) atomic_read(&fcport->state))); cp->result = DID_BUS_BUSY << 16; - if (atomic_read(&fcport->state) == FCS_ONLINE) { - qla2x00_mark_device_lost(ha, fcport, 1, 1); - } + if (atomic_read(&fcport->state) == FCS_ONLINE) + qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1); break; case CS_RESET: @@ -1229,7 +1228,7 @@ qla2x00_status_entry(scsi_qla_host_t *ha, void *pkt) /* Check to see if logout occurred. */ if ((le16_to_cpu(sts->status_flags) & SF_LOGOUT_SENT)) - qla2x00_mark_device_lost(ha, fcport, 1, 1); + qla2x00_mark_device_lost(fcport->ha, fcport, 1, 1); break; default: -- cgit v1.1 From bed475c4cde5d12f537f445bdd0a5a3bb5684481 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 13 Aug 2008 21:36:58 -0700 Subject: [SCSI] qla2xxx: Don't leak SG-DMA mappings while aborting commands. Original code inadvertently cleared an SRB's 'flags' while aborting; causing a follow-on scsi_dma_unmap() to be potentially missed. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_os.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 7c8af7e..c2092ad 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1080,9 +1080,7 @@ qla2x00_abort_all_cmds(scsi_qla_host_t *ha, int res) sp = ha->outstanding_cmds[cnt]; if (sp) { ha->outstanding_cmds[cnt] = NULL; - sp->flags = 0; sp->cmd->result = res; - sp->cmd->host_scribble = (unsigned char *)NULL; qla2x00_sp_compl(ha, sp); } } -- cgit v1.1 From 946fb8915a47bbd76de75b2ae7f1c7e92c0666ca Mon Sep 17 00:00:00 2001 From: Mike Hernandez Date: Wed, 13 Aug 2008 21:36:59 -0700 Subject: [SCSI] qla2xxx: Set npiv_supported flag for FCoE HBAs. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_init.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c index e1de7a6..ee89ddd 100644 --- a/drivers/scsi/qla2xxx/qla_init.c +++ b/drivers/scsi/qla2xxx/qla_init.c @@ -976,8 +976,9 @@ qla2x00_setup_chip(scsi_qla_host_t *ha) &ha->fw_attributes, &ha->fw_memory_size); qla2x00_resize_request_q(ha); ha->flags.npiv_supported = 0; - if ((IS_QLA24XX(ha) || IS_QLA25XX(ha)) && - (ha->fw_attributes & BIT_2)) { + if ((IS_QLA24XX(ha) || IS_QLA25XX(ha) || + IS_QLA84XX(ha)) && + (ha->fw_attributes & BIT_2)) { ha->flags.npiv_supported = 1; if ((!ha->max_npiv_vports) || ((ha->max_npiv_vports + 1) % -- cgit v1.1 From 19851f136ab37d7ac6f7c865329d13db54712ec0 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 13 Aug 2008 21:37:00 -0700 Subject: [SCSI] qla2xxx: Reference proper ha during SBR handling. The executing-HA of an SRB can be referenced from the sp->fcport. Use this correct value while processing status-continuation data and abort processing. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_isr.c | 7 ++++--- drivers/scsi/qla2xxx/qla_os.c | 3 ++- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c index d6a1a66..45a3b93 100644 --- a/drivers/scsi/qla2xxx/qla_isr.c +++ b/drivers/scsi/qla2xxx/qla_isr.c @@ -879,11 +879,12 @@ qla2x00_handle_sense(srb_t *sp, uint8_t *sense_data, uint32_t sense_len) sp->request_sense_ptr += sense_len; sp->request_sense_length -= sense_len; if (sp->request_sense_length != 0) - sp->ha->status_srb = sp; + sp->fcport->ha->status_srb = sp; DEBUG5(printk("%s(): Check condition Sense data, scsi(%ld:%d:%d:%d) " - "cmd=%p pid=%ld\n", __func__, sp->ha->host_no, cp->device->channel, - cp->device->id, cp->device->lun, cp, cp->serial_number)); + "cmd=%p pid=%ld\n", __func__, sp->fcport->ha->host_no, + cp->device->channel, cp->device->id, cp->device->lun, cp, + cp->serial_number)); if (sense_len) DEBUG5(qla2x00_dump_buffer(cp->sense_buffer, CMD_ACTUAL_SNSLEN(cp))); diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index c2092ad..e0880ad 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -780,7 +780,8 @@ qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *ha, unsigned int t, sp = pha->outstanding_cmds[cnt]; if (!sp) continue; - if (ha->vp_idx != sp->ha->vp_idx) + + if (ha->vp_idx != sp->fcport->ha->vp_idx) continue; match = 0; switch (type) { -- cgit v1.1 From c795c1e4b68a74536f0fb18744d0e381ceb1f37e Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 13 Aug 2008 21:37:01 -0700 Subject: [SCSI] qla2xxx: Explicitly tear-down vports during PCI remove_one(). During internal testing, we've seen issues (hangs) with the 'deferred' vport tear-down-processing typically accompanied with the fc_remove_host() call. This is due to the current implementation's back-end vport handling being performed by the physical-HA's DPC thread where premature shutdown could lead to latent vport requests without a processor. This should also address a problem reported by Gal Rosen (http://marc.info/?l=linux-scsi&m=121731664417358&w=2) where the driver would attempt to awaken a previously torn-down DPC thread from interrupt context by implicitly calling wake_up_process() rather than the driver's qla2xxx_wake_dpc() helper. Rather, than reshuffle the remove_one() device-removal code, during unload, depend on the driver's timer to wake-up the DPC process, by limiting wake-ups based on an 'unloading' flag. Signed-off-by: Andrew Vasquez Signed-off-by: James Bottomley --- drivers/scsi/qla2xxx/qla_def.h | 1 + drivers/scsi/qla2xxx/qla_mbx.c | 2 +- drivers/scsi/qla2xxx/qla_os.c | 13 ++++++++++--- 3 files changed, 12 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 6da31ba..94a720e 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -2237,6 +2237,7 @@ typedef struct scsi_qla_host { #define REGISTER_FDMI_NEEDED 26 #define FCPORT_UPDATE_NEEDED 27 #define VP_DPC_NEEDED 28 /* wake up for VP dpc handling */ +#define UNLOADING 29 uint32_t device_flags; #define DFLG_LOCAL_DEVICES BIT_0 diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c index bc90d6b..813bc77 100644 --- a/drivers/scsi/qla2xxx/qla_mbx.c +++ b/drivers/scsi/qla2xxx/qla_mbx.c @@ -2686,7 +2686,7 @@ qla24xx_report_id_acquisition(scsi_qla_host_t *ha, set_bit(VP_IDX_ACQUIRED, &vha->vp_flags); set_bit(VP_DPC_NEEDED, &ha->dpc_flags); - wake_up_process(ha->dpc_thread); + qla2xxx_wake_dpc(ha); } } diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index e0880ad..26afe44 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -1775,10 +1775,15 @@ probe_out: static void qla2x00_remove_one(struct pci_dev *pdev) { - scsi_qla_host_t *ha; + scsi_qla_host_t *ha, *vha, *temp; ha = pci_get_drvdata(pdev); + list_for_each_entry_safe(vha, temp, &ha->vp_list, vp_list) + fc_vport_terminate(vha->fc_vport); + + set_bit(UNLOADING, &ha->dpc_flags); + qla2x00_dfs_remove(ha); qla84xx_put_chip(ha); @@ -2450,8 +2455,10 @@ qla2x00_do_dpc(void *data) void qla2xxx_wake_dpc(scsi_qla_host_t *ha) { - if (ha->dpc_thread) - wake_up_process(ha->dpc_thread); + struct task_struct *t = ha->dpc_thread; + + if (!test_bit(UNLOADING, &ha->dpc_flags) && t) + wake_up_process(t); } /* -- cgit v1.1 From bcd2361d7eda10f85a103cbe70f7eebaeef03072 Mon Sep 17 00:00:00 2001 From: Andrew Vasquez Date: Wed, 13 Aug 2008 21:37:02 -0700 Subject: [SCSI] qla2xxx: Update version number to 8.02.01-k7. 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 676c390..4160e4c 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.02.01-k6" +#define QLA2XXX_VERSION "8.02.01-k7" #define QLA_DRIVER_MAJOR_VER 8 #define QLA_DRIVER_MINOR_VER 2 -- cgit v1.1 From 66dca9b8c50b5e59d3bea8b21cee5c6dae6c9c46 Mon Sep 17 00:00:00 2001 From: Joe Malicki Date: Thu, 14 Aug 2008 17:14:48 -0400 Subject: [SCSI] megaraid_sas: remove sysfs dbg_lvl world writeable permissions /sys/bus/pci/drivers/megaraid_sas/dbg_lvl defaults to being world-writable, which seems bad (letting any user affect kernel driver behavior and logging level). This turns off group and user write permissions, so that on typical production systems only root can write to it. [jejb: fix up rejections] Signed-off-by: Joseph Malicki Acked-by: "Yang, Bo" Signed-off-by: James Bottomley --- drivers/scsi/megaraid/megaraid_sas.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/megaraid/megaraid_sas.c b/drivers/scsi/megaraid/megaraid_sas.c index 870dc1c..97b7633 100644 --- a/drivers/scsi/megaraid/megaraid_sas.c +++ b/drivers/scsi/megaraid/megaraid_sas.c @@ -3405,7 +3405,7 @@ megasas_sysfs_set_dbg_lvl(struct device_driver *dd, const char *buf, size_t coun return retval; } -static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUGO, megasas_sysfs_show_dbg_lvl, +static DRIVER_ATTR(dbg_lvl, S_IRUGO|S_IWUSR, megasas_sysfs_show_dbg_lvl, megasas_sysfs_set_dbg_lvl); static ssize_t -- cgit v1.1 From 004dd5e88673516a408f0e8e43edbe6a4424be2f Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 15 Aug 2008 10:48:47 -0500 Subject: [SCSI] ibmvscsi: Fixup desired DMA value for shared memory partitions When running ibmvscsi in a shared memory partition, it must provide a default value for the amount of DMA resources it will need in order to perform reasonably well. This was being calculated in sectors rather than bytes, as it should. This patch fixes this. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvscsi.c b/drivers/scsi/ibmvscsi/ibmvscsi.c index 6b24b9c..7b1502c 100644 --- a/drivers/scsi/ibmvscsi/ibmvscsi.c +++ b/drivers/scsi/ibmvscsi/ibmvscsi.c @@ -1636,7 +1636,7 @@ static unsigned long ibmvscsi_get_desired_dma(struct vio_dev *vdev) unsigned long desired_io = max_requests * sizeof(union viosrp_iu); /* add io space for sg data */ - desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * + desired_io += (IBMVSCSI_MAX_SECTORS_DEFAULT * 512 * IBMVSCSI_CMDS_PER_LUN_DEFAULT); return desired_io; -- cgit v1.1 From 3eddc569770a76f2ca65621cdde3c0a2552b5b0c Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 15 Aug 2008 10:59:21 -0500 Subject: [SCSI] ibmvfc: Fix another hang on module removal This fixes a hang on module removal. The module removal code was setting the hosts's state to IBMVFC_HOST_OFFLINE before tearing down the kernel thread, but, due to a bug in ibmvfc_wait_while_resetting, was not waiting for the kernel thread's offlining work to be done prior to destroying the kernel thread, which left the scsi host in a blocked state which we never got out of. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index ae560bc..ee11568 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1059,9 +1059,10 @@ static void ibmvfc_get_starget_port_id(struct scsi_target *starget) static int ibmvfc_wait_while_resetting(struct ibmvfc_host *vhost) { long timeout = wait_event_timeout(vhost->init_wait_q, - (vhost->state == IBMVFC_ACTIVE || - vhost->state == IBMVFC_HOST_OFFLINE || - vhost->state == IBMVFC_LINK_DEAD), + ((vhost->state == IBMVFC_ACTIVE || + vhost->state == IBMVFC_HOST_OFFLINE || + vhost->state == IBMVFC_LINK_DEAD) && + vhost->action == IBMVFC_HOST_ACTION_NONE), (init_timeout * HZ)); return timeout ? 0 : -EIO; -- cgit v1.1 From 915be024414c52e311f795566ac938223ba3c847 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 15 Aug 2008 10:59:22 -0500 Subject: [SCSI] ibmvfc: Fixup host state during reinit If an ELS is received while the virtual fibre channel adapter is going through its discovery, a flag is set which causes discovery to get re-driven. However, the hosts's state does not get set back to IBMVFC_INITIALIZING and scsi_block_requests does not get called again, which can result in queuecommand ops getting sent during discovery. This should not occur and may cause problems. One example is that we may no longer be logged into the target we send the command to, resulting in a failure which should not have occurred. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index ee11568..406ab27 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -3602,8 +3602,9 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost) } } - if (vhost->reinit) { + if (vhost->reinit && !ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) { vhost->reinit = 0; + scsi_block_requests(vhost->host); ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_QUERY); } else { ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_NONE); -- cgit v1.1 From cf6f10d794ab4a9bd84fce345c3947588670d5f5 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 15 Aug 2008 10:59:23 -0500 Subject: [SCSI] ibmvfc: Fix for lost async events If the client virtual fibre channel adapter is already logged into the server and does an NPIV Login again, the async queue, which is used for reporting Link Up/Link Down type of events, does not get reset on the server side. Fix up the client driver so that we also do not reset it. This fixes a problem of lost async events following relogins. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 406ab27..58f8c9e 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -556,11 +556,12 @@ static void ibmvfc_link_down(struct ibmvfc_host *vhost, /** * ibmvfc_init_host - Start host initialization * @vhost: ibmvfc host struct + * @relogin: is this a re-login? * * Return value: * nothing **/ -static void ibmvfc_init_host(struct ibmvfc_host *vhost) +static void ibmvfc_init_host(struct ibmvfc_host *vhost, int relogin) { struct ibmvfc_target *tgt; @@ -574,6 +575,11 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost) } if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) { + if (!relogin) { + memset(vhost->async_crq.msgs, 0, PAGE_SIZE); + vhost->async_crq.cur = 0; + } + list_for_each_entry(tgt, &vhost->targets, queue) tgt->need_login = 1; scsi_block_requests(vhost->host); @@ -2084,11 +2090,11 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, case IBMVFC_AE_LINK_UP: case IBMVFC_AE_RESUME: vhost->events_to_log |= IBMVFC_AE_LINKUP; - ibmvfc_init_host(vhost); + ibmvfc_init_host(vhost, 1); break; case IBMVFC_AE_SCN_FABRIC: vhost->events_to_log |= IBMVFC_AE_RSCN; - ibmvfc_init_host(vhost); + ibmvfc_init_host(vhost, 1); break; case IBMVFC_AE_SCN_NPORT: case IBMVFC_AE_SCN_GROUP: @@ -2134,13 +2140,13 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost) /* Send back a response */ rc = ibmvfc_send_crq_init_complete(vhost); if (rc == 0) - ibmvfc_init_host(vhost); + ibmvfc_init_host(vhost, 0); else dev_err(vhost->dev, "Unable to send init rsp. rc=%ld\n", rc); break; case IBMVFC_CRQ_INIT_COMPLETE: dev_info(vhost->dev, "Partner initialization complete\n"); - ibmvfc_init_host(vhost); + ibmvfc_init_host(vhost, 0); break; default: dev_err(vhost->dev, "Unknown crq message type: %d\n", crq->format); @@ -3358,8 +3364,6 @@ static void ibmvfc_npiv_login(struct ibmvfc_host *vhost) mad->buffer.va = vhost->login_buf_dma; mad->buffer.len = sizeof(*vhost->login_buf); - memset(vhost->async_crq.msgs, 0, PAGE_SIZE); - vhost->async_crq.cur = 0; ibmvfc_set_host_action(vhost, IBMVFC_HOST_ACTION_INIT_WAIT); if (!ibmvfc_send_event(evt, vhost, default_timeout)) -- cgit v1.1 From 2bac406df52100aec42e230a2cc2986d34e86218 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 15 Aug 2008 10:59:26 -0500 Subject: [SCSI] ibmvfc: Sanitize response lengths Sanitize the response lengths in order to prevent possible oopses in the command response path. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 58f8c9e..6ecc0dd 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -1457,8 +1457,8 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt) struct ibmvfc_cmd *vfc_cmd = &evt->xfer_iu->cmd; struct ibmvfc_fcp_rsp *rsp = &vfc_cmd->rsp; struct scsi_cmnd *cmnd = evt->cmnd; - int rsp_len = 0; - int sense_len = rsp->fcp_sense_len; + u32 rsp_len = 0; + u32 sense_len = rsp->fcp_sense_len; if (cmnd) { if (vfc_cmd->response_flags & IBMVFC_ADAPTER_RESID_VALID) @@ -1475,7 +1475,7 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt) rsp_len = rsp->fcp_rsp_len; if ((sense_len + rsp_len) > SCSI_SENSE_BUFFERSIZE) sense_len = SCSI_SENSE_BUFFERSIZE - rsp_len; - if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len) + if ((rsp->flags & FCP_SNS_LEN_VALID) && rsp->fcp_sense_len && rsp_len <= 8) memcpy(cmnd->sense_buffer, rsp->data.sense + rsp_len, sense_len); ibmvfc_log_error(evt); -- cgit v1.1 From 3e3399467d4c4aefe6a24225b5b277cf7d6e58a7 Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 15 Aug 2008 10:59:27 -0500 Subject: [SCSI] ibmvfc: Add details to async event log When logging async events, also print the payload in addition to the event received. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c index 6ecc0dd..4e0b7c8 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.c +++ b/drivers/scsi/ibmvscsi/ibmvfc.c @@ -2084,7 +2084,8 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq, { const char *desc = ibmvfc_get_ae_desc(crq->event); - ibmvfc_log(vhost, 3, "%s event received\n", desc); + ibmvfc_log(vhost, 3, "%s event received. scsi_id: %lx, wwpn: %lx," + " node_name: %lx\n", desc, crq->scsi_id, crq->wwpn, crq->node_name); switch (crq->event) { case IBMVFC_AE_LINK_UP: -- cgit v1.1 From 7d0e367ab3f3ad345bd3e121c4c5f511e8b274fa Mon Sep 17 00:00:00 2001 From: Brian King Date: Fri, 15 Aug 2008 10:59:28 -0500 Subject: [SCSI] ibmvfc: Driver version 1.0.2 Bump driver version to 1.0.2. Signed-off-by: Brian King Signed-off-by: James Bottomley --- drivers/scsi/ibmvscsi/ibmvfc.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h index 4bf6e37..fb3177a 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc.h +++ b/drivers/scsi/ibmvscsi/ibmvfc.h @@ -29,8 +29,8 @@ #include "viosrp.h" #define IBMVFC_NAME "ibmvfc" -#define IBMVFC_DRIVER_VERSION "1.0.1" -#define IBMVFC_DRIVER_DATE "(July 11, 2008)" +#define IBMVFC_DRIVER_VERSION "1.0.2" +#define IBMVFC_DRIVER_DATE "(August 14, 2008)" #define IBMVFC_DEFAULT_TIMEOUT 15 #define IBMVFC_INIT_TIMEOUT 30 -- cgit v1.1 From 9bfa35fe422c74882e27cc54450a5f76c96aad68 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 18 Aug 2008 13:23:52 +0200 Subject: [Bluetooth] Add SCO support to btusb driver The new generic driver for Bluetooth USB devices was missing proper SCO support. The driver now claims the second interface for these USB devices to allow the flow of SCO packets. It also handles switching of the alternate setting and re-submission of isochronous URBs. The btusb driver is now a full replacement for hci_usb and thus the experimental tag has been removed and this driver is promoted as preferred one. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/Kconfig | 10 +- drivers/bluetooth/btusb.c | 282 +++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 272 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/Kconfig b/drivers/bluetooth/Kconfig index a235ca7..7cb4029 100644 --- a/drivers/bluetooth/Kconfig +++ b/drivers/bluetooth/Kconfig @@ -3,8 +3,8 @@ menu "Bluetooth device drivers" depends on BT config BT_HCIUSB - tristate "HCI USB driver" - depends on USB + tristate "HCI USB driver (old version)" + depends on USB && BT_HCIBTUSB=n help Bluetooth HCI USB driver. This driver is required if you want to use Bluetooth devices with @@ -23,15 +23,13 @@ config BT_HCIUSB_SCO Say Y here to compile support for SCO over HCI USB. config BT_HCIBTUSB - tristate "HCI USB driver (alternate version)" - depends on USB && EXPERIMENTAL && BT_HCIUSB=n + tristate "HCI USB driver" + depends on USB help Bluetooth HCI USB driver. This driver is required if you want to use Bluetooth devices with USB interface. - This driver is still experimental and has no SCO support. - Say Y here to compile support for Bluetooth USB devices into the kernel or say M to compile it as module (btusb). diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 95ae9ba..6a01068 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -2,7 +2,7 @@ * * Generic Bluetooth USB driver * - * Copyright (C) 2005-2007 Marcel Holtmann + * Copyright (C) 2005-2008 Marcel Holtmann * * * This program is free software; you can redistribute it and/or modify @@ -41,7 +41,7 @@ #define BT_DBG(D...) #endif -#define VERSION "0.2" +#define VERSION "0.3" static int ignore_dga; static int ignore_csr; @@ -160,12 +160,16 @@ static struct usb_device_id blacklist_table[] = { { } /* Terminating entry */ }; +#define BTUSB_MAX_ISOC_FRAMES 10 + #define BTUSB_INTR_RUNNING 0 #define BTUSB_BULK_RUNNING 1 +#define BTUSB_ISOC_RUNNING 2 struct btusb_data { struct hci_dev *hdev; struct usb_device *udev; + struct usb_interface *isoc; spinlock_t lock; @@ -176,10 +180,15 @@ struct btusb_data { struct usb_anchor tx_anchor; struct usb_anchor intr_anchor; struct usb_anchor bulk_anchor; + struct usb_anchor isoc_anchor; struct usb_endpoint_descriptor *intr_ep; struct usb_endpoint_descriptor *bulk_tx_ep; struct usb_endpoint_descriptor *bulk_rx_ep; + struct usb_endpoint_descriptor *isoc_tx_ep; + struct usb_endpoint_descriptor *isoc_rx_ep; + + int isoc_altsetting; }; static void btusb_intr_complete(struct urb *urb) @@ -195,6 +204,8 @@ static void btusb_intr_complete(struct urb *urb) return; if (urb->status == 0) { + hdev->stat.byte_rx += urb->actual_length; + if (hci_recv_fragment(hdev, HCI_EVENT_PKT, urb->transfer_buffer, urb->actual_length) < 0) { @@ -216,7 +227,7 @@ static void btusb_intr_complete(struct urb *urb) } } -static inline int btusb_submit_intr_urb(struct hci_dev *hdev) +static int btusb_submit_intr_urb(struct hci_dev *hdev) { struct btusb_data *data = hdev->driver_data; struct urb *urb; @@ -226,6 +237,9 @@ static inline int btusb_submit_intr_urb(struct hci_dev *hdev) BT_DBG("%s", hdev->name); + if (!data->intr_ep) + return -ENODEV; + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; @@ -274,6 +288,8 @@ static void btusb_bulk_complete(struct urb *urb) return; if (urb->status == 0) { + hdev->stat.byte_rx += urb->actual_length; + if (hci_recv_fragment(hdev, HCI_ACLDATA_PKT, urb->transfer_buffer, urb->actual_length) < 0) { @@ -295,7 +311,7 @@ static void btusb_bulk_complete(struct urb *urb) } } -static inline int btusb_submit_bulk_urb(struct hci_dev *hdev) +static int btusb_submit_bulk_urb(struct hci_dev *hdev) { struct btusb_data *data = hdev->driver_data; struct urb *urb; @@ -305,6 +321,9 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev) BT_DBG("%s", hdev->name); + if (!data->bulk_rx_ep) + return -ENODEV; + urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) return -ENOMEM; @@ -339,6 +358,127 @@ static inline int btusb_submit_bulk_urb(struct hci_dev *hdev) return err; } +static void btusb_isoc_complete(struct urb *urb) +{ + struct hci_dev *hdev = urb->context; + struct btusb_data *data = hdev->driver_data; + int i, err; + + BT_DBG("%s urb %p status %d count %d", hdev->name, + urb, urb->status, urb->actual_length); + + if (!test_bit(HCI_RUNNING, &hdev->flags)) + return; + + if (urb->status == 0) { + for (i = 0; i < urb->number_of_packets; i++) { + unsigned int offset = urb->iso_frame_desc[i].offset; + unsigned int length = urb->iso_frame_desc[i].actual_length; + + if (urb->iso_frame_desc[i].status) + continue; + + hdev->stat.byte_rx += length; + + if (hci_recv_fragment(hdev, HCI_SCODATA_PKT, + urb->transfer_buffer + offset, + length) < 0) { + BT_ERR("%s corrupted SCO packet", hdev->name); + hdev->stat.err_rx++; + } + } + } + + if (!test_bit(BTUSB_ISOC_RUNNING, &data->flags)) + return; + + usb_anchor_urb(urb, &data->isoc_anchor); + + err = usb_submit_urb(urb, GFP_ATOMIC); + if (err < 0) { + BT_ERR("%s urb %p failed to resubmit (%d)", + hdev->name, urb, -err); + usb_unanchor_urb(urb); + } +} + +static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu) +{ + int i, offset = 0; + + BT_DBG("len %d mtu %d", len, mtu); + + for (i = 0; i < BTUSB_MAX_ISOC_FRAMES && len >= mtu; + i++, offset += mtu, len -= mtu) { + urb->iso_frame_desc[i].offset = offset; + urb->iso_frame_desc[i].length = mtu; + } + + if (len && i < BTUSB_MAX_ISOC_FRAMES) { + urb->iso_frame_desc[i].offset = offset; + urb->iso_frame_desc[i].length = len; + i++; + } + + urb->number_of_packets = i; +} + +static int btusb_submit_isoc_urb(struct hci_dev *hdev) +{ + struct btusb_data *data = hdev->driver_data; + struct urb *urb; + unsigned char *buf; + unsigned int pipe; + int err, size; + + BT_DBG("%s", hdev->name); + + if (!data->isoc_rx_ep) + return -ENODEV; + + urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_KERNEL); + if (!urb) + return -ENOMEM; + + size = le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize) * + BTUSB_MAX_ISOC_FRAMES; + + buf = kmalloc(size, GFP_KERNEL); + if (!buf) { + usb_free_urb(urb); + return -ENOMEM; + } + + pipe = usb_rcvisocpipe(data->udev, data->isoc_rx_ep->bEndpointAddress); + + urb->dev = data->udev; + urb->pipe = pipe; + urb->context = hdev; + urb->complete = btusb_isoc_complete; + urb->interval = data->isoc_rx_ep->bInterval; + + urb->transfer_flags = URB_FREE_BUFFER | URB_ISO_ASAP; + urb->transfer_buffer = buf; + urb->transfer_buffer_length = size; + + __fill_isoc_descriptor(urb, size, + le16_to_cpu(data->isoc_rx_ep->wMaxPacketSize)); + + usb_anchor_urb(urb, &data->isoc_anchor); + + err = usb_submit_urb(urb, GFP_KERNEL); + if (err < 0) { + BT_ERR("%s urb %p submission failed (%d)", + hdev->name, urb, -err); + usb_unanchor_urb(urb); + kfree(buf); + } + + usb_free_urb(urb); + + return err; +} + static void btusb_tx_complete(struct urb *urb) { struct sk_buff *skb = urb->context; @@ -392,6 +532,9 @@ static int btusb_close(struct hci_dev *hdev) if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags)) return 0; + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + usb_kill_anchored_urbs(&data->intr_anchor); + clear_bit(BTUSB_BULK_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->bulk_anchor); @@ -453,6 +596,9 @@ static int btusb_send_frame(struct sk_buff *skb) break; case HCI_ACLDATA_PKT: + if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1) + return -ENODEV; + urb = usb_alloc_urb(0, GFP_ATOMIC); if (!urb) return -ENOMEM; @@ -467,9 +613,31 @@ static int btusb_send_frame(struct sk_buff *skb) break; case HCI_SCODATA_PKT: + if (!data->isoc_tx_ep || hdev->conn_hash.sco_num < 1) + return -ENODEV; + + urb = usb_alloc_urb(BTUSB_MAX_ISOC_FRAMES, GFP_ATOMIC); + if (!urb) + return -ENOMEM; + + pipe = usb_sndisocpipe(data->udev, + data->isoc_tx_ep->bEndpointAddress); + + urb->dev = data->udev; + urb->pipe = pipe; + urb->context = skb; + urb->complete = btusb_tx_complete; + urb->interval = data->isoc_tx_ep->bInterval; + + urb->transfer_flags = URB_ISO_ASAP; + urb->transfer_buffer = skb->data; + urb->transfer_buffer_length = skb->len; + + __fill_isoc_descriptor(urb, skb->len, + le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize)); + hdev->stat.sco_tx++; - kfree_skb(skb); - return 0; + break; default: return -EILSEQ; @@ -508,22 +676,86 @@ static void btusb_notify(struct hci_dev *hdev, unsigned int evt) schedule_work(&data->work); } +static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting) +{ + struct btusb_data *data = hdev->driver_data; + struct usb_interface *intf = data->isoc; + struct usb_endpoint_descriptor *ep_desc; + int i, err; + + if (!data->isoc) + return -ENODEV; + + err = usb_set_interface(data->udev, 1, altsetting); + if (err < 0) { + BT_ERR("%s setting interface failed (%d)", hdev->name, -err); + return err; + } + + data->isoc_altsetting = altsetting; + + data->isoc_tx_ep = NULL; + data->isoc_rx_ep = NULL; + + for (i = 0; i < intf->cur_altsetting->desc.bNumEndpoints; i++) { + ep_desc = &intf->cur_altsetting->endpoint[i].desc; + + if (!data->isoc_tx_ep && usb_endpoint_is_isoc_out(ep_desc)) { + data->isoc_tx_ep = ep_desc; + continue; + } + + if (!data->isoc_rx_ep && usb_endpoint_is_isoc_in(ep_desc)) { + data->isoc_rx_ep = ep_desc; + continue; + } + } + + if (!data->isoc_tx_ep || !data->isoc_rx_ep) { + BT_ERR("%s invalid SCO descriptors", hdev->name); + return -ENODEV; + } + + return 0; +} + static void btusb_work(struct work_struct *work) { struct btusb_data *data = container_of(work, struct btusb_data, work); struct hci_dev *hdev = data->hdev; - if (hdev->conn_hash.acl_num == 0) { + if (hdev->conn_hash.acl_num > 0) { + if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) { + if (btusb_submit_bulk_urb(hdev) < 0) + clear_bit(BTUSB_BULK_RUNNING, &data->flags); + else + btusb_submit_bulk_urb(hdev); + } + } else { clear_bit(BTUSB_BULK_RUNNING, &data->flags); usb_kill_anchored_urbs(&data->bulk_anchor); - return; } - if (!test_and_set_bit(BTUSB_BULK_RUNNING, &data->flags)) { - if (btusb_submit_bulk_urb(hdev) < 0) - clear_bit(BTUSB_BULK_RUNNING, &data->flags); - else - btusb_submit_bulk_urb(hdev); + if (hdev->conn_hash.sco_num > 0) { + if (data->isoc_altsetting != 2) { + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + usb_kill_anchored_urbs(&data->isoc_anchor); + + if (__set_isoc_interface(hdev, 2) < 0) + return; + } + + if (!test_and_set_bit(BTUSB_ISOC_RUNNING, &data->flags)) { + if (btusb_submit_isoc_urb(hdev) < 0) + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + else + btusb_submit_isoc_urb(hdev); + } + } else { + clear_bit(BTUSB_ISOC_RUNNING, &data->flags); + usb_kill_anchored_urbs(&data->isoc_anchor); + + __set_isoc_interface(hdev, 0); } } @@ -597,6 +829,7 @@ static int btusb_probe(struct usb_interface *intf, init_usb_anchor(&data->tx_anchor); init_usb_anchor(&data->intr_anchor); init_usb_anchor(&data->bulk_anchor); + init_usb_anchor(&data->isoc_anchor); hdev = hci_alloc_dev(); if (!hdev) { @@ -620,6 +853,9 @@ static int btusb_probe(struct usb_interface *intf, hdev->owner = THIS_MODULE; + /* interface numbers are hardcoded in the spec */ + data->isoc = usb_ifnum_to_if(data->udev, 1); + if (reset || id->driver_info & BTUSB_RESET) set_bit(HCI_QUIRK_RESET_ON_INIT, &hdev->quirks); @@ -628,11 +864,16 @@ static int btusb_probe(struct usb_interface *intf, set_bit(HCI_QUIRK_FIXUP_BUFFER_SIZE, &hdev->quirks); } + if (id->driver_info & BTUSB_BROKEN_ISOC) + data->isoc = NULL; + if (id->driver_info & BTUSB_SNIFFER) { - struct usb_device *udev = interface_to_usbdev(intf); + struct usb_device *udev = data->udev; if (le16_to_cpu(udev->descriptor.bcdDevice) > 0x997) set_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks); + + data->isoc = NULL; } if (id->driver_info & BTUSB_BCM92035) { @@ -646,6 +887,16 @@ static int btusb_probe(struct usb_interface *intf, } } + if (data->isoc) { + err = usb_driver_claim_interface(&btusb_driver, + data->isoc, NULL); + if (err < 0) { + hci_free_dev(hdev); + kfree(data); + return err; + } + } + err = hci_register_dev(hdev); if (err < 0) { hci_free_dev(hdev); @@ -670,6 +921,9 @@ static void btusb_disconnect(struct usb_interface *intf) hdev = data->hdev; + if (data->isoc) + usb_driver_release_interface(&btusb_driver, data->isoc); + usb_set_intfdata(intf, NULL); hci_unregister_dev(hdev); -- cgit v1.1 From 63fbd24e5102eecfc9d049ed7f4be7f9a25f814f Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Mon, 18 Aug 2008 13:23:53 +0200 Subject: [Bluetooth] Consolidate maintainers information The Bluetooth entries for the MAINTAINERS file are a little bit too much. Consolidate them into two entries. One for Bluetooth drivers and another one for the Bluetooth subsystem. Also the MODULE_AUTHOR should indicate the current maintainer of the module and actually not the original author. Fix all Bluetooth modules to provide current maintainer information. Signed-off-by: Marcel Holtmann --- drivers/bluetooth/bt3c_cs.c | 2 +- drivers/bluetooth/hci_ldisc.c | 2 +- drivers/bluetooth/hci_usb.c | 2 +- drivers/bluetooth/hci_vhci.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/bluetooth/bt3c_cs.c b/drivers/bluetooth/bt3c_cs.c index 593b7c5..2705847 100644 --- a/drivers/bluetooth/bt3c_cs.c +++ b/drivers/bluetooth/bt3c_cs.c @@ -60,7 +60,7 @@ /* ======================== Module parameters ======================== */ -MODULE_AUTHOR("Marcel Holtmann , Jose Orlando Pereira "); +MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth driver for the 3Com Bluetooth PCMCIA card"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE("BT3CPCC.bin"); diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index 69df187..8dfcf77 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c @@ -577,7 +577,7 @@ module_exit(hci_uart_exit); module_param(reset, bool, 0644); MODULE_PARM_DESC(reset, "Send HCI reset command on initialization"); -MODULE_AUTHOR("Maxim Krasnyansky , Marcel Holtmann "); +MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth HCI UART driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/bluetooth/hci_usb.c b/drivers/bluetooth/hci_usb.c index e397572..3c45392 100644 --- a/drivers/bluetooth/hci_usb.c +++ b/drivers/bluetooth/hci_usb.c @@ -1130,7 +1130,7 @@ module_param(isoc, int, 0644); MODULE_PARM_DESC(isoc, "Set isochronous transfers for SCO over HCI support"); #endif -MODULE_AUTHOR("Maxim Krasnyansky , Marcel Holtmann "); +MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth HCI USB driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); diff --git a/drivers/bluetooth/hci_vhci.c b/drivers/bluetooth/hci_vhci.c index d97700a..7320a71 100644 --- a/drivers/bluetooth/hci_vhci.c +++ b/drivers/bluetooth/hci_vhci.c @@ -377,7 +377,7 @@ module_exit(vhci_exit); module_param(minor, int, 0444); MODULE_PARM_DESC(minor, "Miscellaneous minor device number"); -MODULE_AUTHOR("Maxim Krasnyansky , Marcel Holtmann "); +MODULE_AUTHOR("Marcel Holtmann "); MODULE_DESCRIPTION("Bluetooth virtual HCI driver ver " VERSION); MODULE_VERSION(VERSION); MODULE_LICENSE("GPL"); -- cgit v1.1 From 26135ed3229a06dc8b5b7686dd272a28f5bf40b3 Mon Sep 17 00:00:00 2001 From: Martin Michlmayr Date: Fri, 15 Aug 2008 15:06:21 -0400 Subject: Input: cobalt_btns - add missing MODULE_LICENSE Export the module license and other information about the Cobalt button module in order to avoid the following warning: | WARNING: modpost: missing MODULE_LICENSE() in drivers/input/misc/cobalt_btns.o Signed-off-by: Martin Michlmayr Acked-by: Yoichi Yuasa Signed-off-by: Dmitry Torokhov --- drivers/input/misc/cobalt_btns.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/input/misc/cobalt_btns.c b/drivers/input/misc/cobalt_btns.c index 6a1f48b..2adf9cb 100644 --- a/drivers/input/misc/cobalt_btns.c +++ b/drivers/input/misc/cobalt_btns.c @@ -148,6 +148,9 @@ static int __devexit cobalt_buttons_remove(struct platform_device *pdev) return 0; } +MODULE_AUTHOR("Yoichi Yuasa "); +MODULE_DESCRIPTION("Cobalt button interface driver"); +MODULE_LICENSE("GPL"); /* work with hotplug and coldplug */ MODULE_ALIAS("platform:Cobalt buttons"); -- cgit v1.1 From 0cc1fe2238e458ebe2d52f035ccc6f3d2ecc9ca1 Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Mon, 18 Aug 2008 10:57:10 -0400 Subject: Input: remove version.h from drivers that don't need it If a driver dies not use LINUX_VERSION_CODE nor KERNEL_VERSION then it does not need to include version.h Signed-off-by: Huang Weiyi Acked-by: Mark Brown Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/gpio_keys.c | 1 - drivers/input/mouse/gpio_mouse.c | 1 - drivers/input/tablet/gtco.c | 1 - drivers/input/touchscreen/wm9705.c | 1 - drivers/input/touchscreen/wm9712.c | 1 - drivers/input/touchscreen/wm9713.c | 1 - drivers/input/touchscreen/wm97xx-core.c | 1 - 7 files changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c index 3f48279..ec96b36 100644 --- a/drivers/input/keyboard/gpio_keys.c +++ b/drivers/input/keyboard/gpio_keys.c @@ -9,7 +9,6 @@ */ #include -#include #include #include diff --git a/drivers/input/mouse/gpio_mouse.c b/drivers/input/mouse/gpio_mouse.c index 3392901..72cf5e3 100644 --- a/drivers/input/mouse/gpio_mouse.c +++ b/drivers/input/mouse/gpio_mouse.c @@ -9,7 +9,6 @@ */ #include -#include #include #include #include diff --git a/drivers/input/tablet/gtco.c b/drivers/input/tablet/gtco.c index b9b7a98..7df0228 100644 --- a/drivers/input/tablet/gtco.c +++ b/drivers/input/tablet/gtco.c @@ -64,7 +64,6 @@ Scott Hill shill@gtcocalcomp.com #include -#include #include /* Version with a Major number of 2 is for kernel inclusion only. */ diff --git a/drivers/input/touchscreen/wm9705.c b/drivers/input/touchscreen/wm9705.c index 978e1a1..372efbc 100644 --- a/drivers/input/touchscreen/wm9705.c +++ b/drivers/input/touchscreen/wm9705.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include diff --git a/drivers/input/touchscreen/wm9712.c b/drivers/input/touchscreen/wm9712.c index 4c5d85a..c8bb1e7 100644 --- a/drivers/input/touchscreen/wm9712.c +++ b/drivers/input/touchscreen/wm9712.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include diff --git a/drivers/input/touchscreen/wm9713.c b/drivers/input/touchscreen/wm9713.c index 8384587..781ee83 100644 --- a/drivers/input/touchscreen/wm9713.c +++ b/drivers/input/touchscreen/wm9713.c @@ -17,7 +17,6 @@ #include #include -#include #include #include #include diff --git a/drivers/input/touchscreen/wm97xx-core.c b/drivers/input/touchscreen/wm97xx-core.c index cdc24ad..d589ab0 100644 --- a/drivers/input/touchscreen/wm97xx-core.c +++ b/drivers/input/touchscreen/wm97xx-core.c @@ -37,7 +37,6 @@ #include #include -#include #include #include #include -- cgit v1.1 From 88b9e2bef3e38c053ec8f054f2cbb9345724cdb1 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 5 Aug 2008 22:06:51 +0300 Subject: ath9k: work around gcc ICEs (again) (I missed the fact that the original post said to apply this patch twice... -- JWL) Original commit log message: This patch works around an internal compiler error (gcc bug #37014) in all gcc 4.2 compilers and the gcc 4.3 series up to at least 4.3.1 on at least powerpc and mips. Many thanks to Andrew Pinski for analyzing the gcc bug. Signed-off-by: Adrian Bunk Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/hw.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath9k/hw.c b/drivers/net/wireless/ath9k/hw.c index bde162f..a17eb13 100644 --- a/drivers/net/wireless/ath9k/hw.c +++ b/drivers/net/wireless/ath9k/hw.c @@ -5017,7 +5017,11 @@ static void ath9k_hw_spur_mitigate(struct ath_hal *ah, for (i = 0; i < 123; i++) { if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - if ((abs(cur_vit_mask - bin)) < 75) + + /* workaround for gcc bug #37014 */ + volatile int tmp = abs(cur_vit_mask - bin); + + if (tmp < 75) mask_amt = 1; else mask_amt = 0; -- cgit v1.1 From aaa1553512b9105699113ea7e2ea726f3d9d4de2 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sat, 9 Aug 2008 19:20:47 -0500 Subject: p54: Fix regression due to "net: Delete NETDEVICES_MULTIQUEUE kconfig option" Commit b19fa1f, entitled "net: Delete NETDEVICES_MULTIQUEUE kconfig option" breaks p54pci and p54usb. Additionally, the old logic always tx'ed cts frames (if enabled) with a short preamble when [rate > 3]. (i.e. with any 802.11g rate). Of course this isn't that bad, but it's still wrong! (This patch also clarifies the meanings of some of the fields in the tx header for the hardware. -- JWL) Signed-off-by: Christian Lamparter Acked-by: Larry Finger Cc: [2.6.25.x, 2.6.26.x] Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 31 ++++++++++++++++--------------- drivers/net/wireless/p54/p54common.h | 18 +++++++++--------- 2 files changed, 25 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 83cd85e..49afd20 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -413,12 +413,12 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) last_addr = range->end_addr; __skb_unlink(entry, &priv->tx_queue); memset(&info->status, 0, sizeof(info->status)); - priv->tx_stats[skb_get_queue_mapping(skb)].len--; entry_hdr = (struct p54_control_hdr *) entry->data; entry_data = (struct p54_tx_control_allocdata *) entry_hdr->data; if ((entry_hdr->magic1 & cpu_to_le16(0x4000)) != 0) pad = entry_data->align[0]; + priv->tx_stats[entry_data->hw_queue - 4].len--; if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { if (!(payload->status & 0x01)) info->flags |= IEEE80211_TX_STAT_ACK; @@ -557,6 +557,7 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) struct p54_tx_control_allocdata *txhdr; size_t padding, len; u8 rate; + u8 cts_rate = 0x20; current_queue = &priv->tx_stats[skb_get_queue_mapping(skb)]; if (unlikely(current_queue->len > current_queue->limit)) @@ -581,28 +582,28 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) hdr->type = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? 0 : cpu_to_le16(1); hdr->retry1 = hdr->retry2 = info->control.retry_limit; - memset(txhdr->wep_key, 0x0, 16); - txhdr->padding = 0; - txhdr->padding2 = 0; - /* TODO: add support for alternate retry TX rates */ rate = ieee80211_get_tx_rate(dev, info)->hw_value; - if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) + if (info->flags & IEEE80211_TX_CTL_SHORT_PREAMBLE) { rate |= 0x10; - if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) + cts_rate |= 0x10; + } + if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) { rate |= 0x40; - else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) + cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; + } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) { rate |= 0x20; + cts_rate |= ieee80211_get_rts_cts_rate(dev, info)->hw_value; + } memset(txhdr->rateset, rate, 8); - txhdr->wep_key_present = 0; - txhdr->wep_key_len = 0; - txhdr->frame_type = cpu_to_le32(skb_get_queue_mapping(skb) + 4); - txhdr->magic4 = 0; - txhdr->antenna = (info->antenna_sel_tx == 0) ? + txhdr->key_type = 0; + txhdr->key_len = 0; + txhdr->hw_queue = skb_get_queue_mapping(skb) + 4; + txhdr->tx_antenna = (info->antenna_sel_tx == 0) ? 2 : info->antenna_sel_tx - 1; txhdr->output_power = 0x7f; // HW Maximum - txhdr->magic5 = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? - 0 : ((rate > 0x3) ? cpu_to_le32(0x33) : cpu_to_le32(0x23)); + txhdr->cts_rate = (info->flags & IEEE80211_TX_CTL_NO_ACK) ? + 0 : cts_rate; if (padding) txhdr->align[0] = padding; diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 2245fcc..8db6c0e 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h @@ -183,16 +183,16 @@ struct p54_frame_sent_hdr { struct p54_tx_control_allocdata { u8 rateset[8]; - u16 padding; - u8 wep_key_present; - u8 wep_key_len; - u8 wep_key[16]; - __le32 frame_type; - u32 padding2; - __le16 magic4; - u8 antenna; + u8 unalloc0[2]; + u8 key_type; + u8 key_len; + u8 key[16]; + u8 hw_queue; + u8 unalloc1[9]; + u8 tx_antenna; u8 output_power; - __le32 magic5; + u8 cts_rate; + u8 unalloc2[3]; u8 align[0]; } __attribute__ ((packed)); -- cgit v1.1 From 7f37441c21d3ae9fec47ef418ccafb2823d12a27 Mon Sep 17 00:00:00 2001 From: Holger Schurig Date: Thu, 7 Aug 2008 18:24:12 +0200 Subject: ssb: allow compilation on systems without PCI Makes ssb work on system without a PCI bus. Signed-off-by: Holger Schurig Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/ssb/main.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index d831a2b..87ab244 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c @@ -1165,15 +1165,19 @@ EXPORT_SYMBOL(ssb_dma_translation); int ssb_dma_set_mask(struct ssb_device *dev, u64 mask) { +#ifdef CONFIG_SSB_PCIHOST int err; +#endif switch (dev->bus->bustype) { case SSB_BUSTYPE_PCI: +#ifdef CONFIG_SSB_PCIHOST err = pci_set_dma_mask(dev->bus->host_pci, mask); if (err) return err; err = pci_set_consistent_dma_mask(dev->bus->host_pci, mask); return err; +#endif case SSB_BUSTYPE_SSB: return dma_set_mask(dev->dev, mask); default: @@ -1188,6 +1192,7 @@ void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, { switch (dev->bus->bustype) { case SSB_BUSTYPE_PCI: +#ifdef CONFIG_SSB_PCIHOST if (gfp_flags & GFP_DMA) { /* Workaround: The PCI API does not support passing * a GFP flag. */ @@ -1195,6 +1200,7 @@ void * ssb_dma_alloc_consistent(struct ssb_device *dev, size_t size, size, dma_handle, gfp_flags); } return pci_alloc_consistent(dev->bus->host_pci, size, dma_handle); +#endif case SSB_BUSTYPE_SSB: return dma_alloc_coherent(dev->dev, size, dma_handle, gfp_flags); default: @@ -1210,6 +1216,7 @@ void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, { switch (dev->bus->bustype) { case SSB_BUSTYPE_PCI: +#ifdef CONFIG_SSB_PCIHOST if (gfp_flags & GFP_DMA) { /* Workaround: The PCI API does not support passing * a GFP flag. */ @@ -1220,6 +1227,7 @@ void ssb_dma_free_consistent(struct ssb_device *dev, size_t size, pci_free_consistent(dev->bus->host_pci, size, vaddr, dma_handle); return; +#endif case SSB_BUSTYPE_SSB: dma_free_coherent(dev->dev, size, vaddr, dma_handle); return; -- cgit v1.1 From 37465c8a3ec7279e3314623d1e2d2a50c10cf79f Mon Sep 17 00:00:00 2001 From: Michael Karcher Date: Thu, 7 Aug 2008 19:34:01 +0200 Subject: ath5k: Don't fiddle with MSI on suspend/resume. Commit 256b152b005e319f985f50f2a910a75ba0def74f (ath5k: don't enable MSI, we cannot handle it yet) has removed msi support, but overlooked the suspend/resume code. This patch completes msi removal. I don't consider this patch copyrightable, and thus put it into the public domain. The result is of course a base.c file dual-licensed under 3-clause-BSD and GPL. Signed-off-by: Michael Karcher Acked-by: Nick Kossifidis Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 2028866..f19f33c 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -587,7 +587,6 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) ath5k_stop_hw(sc); free_irq(pdev->irq, sc); - pci_disable_msi(pdev); pci_save_state(pdev); pci_disable_device(pdev); pci_set_power_state(pdev, PCI_D3hot); @@ -616,12 +615,10 @@ ath5k_pci_resume(struct pci_dev *pdev) */ pci_write_config_byte(pdev, 0x41, 0); - pci_enable_msi(pdev); - err = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); if (err) { ATH5K_ERR(sc, "request_irq failed\n"); - goto err_msi; + goto err_no_irq; } err = ath5k_init(sc); @@ -642,8 +639,7 @@ ath5k_pci_resume(struct pci_dev *pdev) return 0; err_irq: free_irq(pdev->irq, sc); -err_msi: - pci_disable_msi(pdev); +err_no_irq: pci_disable_device(pdev); return err; } -- cgit v1.1 From a58d452290aafae30b021c8bf185853b1aaf2092 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Sun, 10 Aug 2008 10:19:33 -0500 Subject: b43: Fix for SPROM coding error in Linksys WMP54G (BCM4306/3) The Linksys WMP54G (BCM4306/3) card in a PCI format has an SPROM coding error and needs the fix found for several other cards. Signed-off-by: Larry Finger Cc: Stable [2.6.25.x, 2.6.26.x] Signed-off-by: Michael Buesch Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 3bf3a86..ee462b5 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4616,6 +4616,7 @@ static void b43_sprom_fixup(struct ssb_bus *bus) pdev = bus->host_pci; if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) || + IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013)) bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST; } -- cgit v1.1 From fcd7cc1496681f7241ef8b80f32bb35d72a4e78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?matthieu=20Barth=C3=A9lemy?= Date: Sun, 10 Aug 2008 23:34:59 -0500 Subject: rtl8187: Add USB ID for Netgear WG111V3 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add the USB ID for a Netgear WG111v3. Signed-off-by: matthieu Barthélemy Signed-off-by: Larry Finger Signed-off-by: John W. Linville --- drivers/net/wireless/rtl8187_dev.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/rtl8187_dev.c b/drivers/net/wireless/rtl8187_dev.c index 57376fb..ca5deb6 100644 --- a/drivers/net/wireless/rtl8187_dev.c +++ b/drivers/net/wireless/rtl8187_dev.c @@ -40,6 +40,7 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { /* Netgear */ {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, + {USB_DEVICE(0x0846, 0x4260), .driver_info = DEVICE_RTL8187B}, /* HP */ {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, /* Sitecom */ -- cgit v1.1 From 6f14792610905fe006c0c3c4d9e1478fb6be7cec Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 11 Aug 2008 23:49:41 +0200 Subject: iwlwifi: fix printk newlines Add newlines at printk outputs to not break dmesg. Signed-off-by: Jiri Slaby Cc: Zhu Yi Cc: Reinette Chatre Signed-off-by: John W. Linville --- drivers/net/wireless/iwlwifi/iwl-4965.c | 2 +- drivers/net/wireless/iwlwifi/iwl-eeprom.c | 6 +++--- drivers/net/wireless/iwlwifi/iwl-sta.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl-tx.c | 4 ++-- drivers/net/wireless/iwlwifi/iwl3945-base.c | 6 +++--- 5 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 22bb269..4a0cc78 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -967,7 +967,7 @@ static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel, s = iwl4965_get_sub_band(priv, channel); if (s >= EEPROM_TX_POWER_BANDS) { - IWL_ERROR("Tx Power can not find channel %d ", channel); + IWL_ERROR("Tx Power can not find channel %d\n", channel); return -1; } diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index bce5383..19985bf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -146,7 +146,7 @@ int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) { u32 gp = iwl_read32(priv, CSR_EEPROM_GP); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); return -ENOENT; } return 0; @@ -227,7 +227,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); if (ret < 0) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); ret = -ENOENT; goto err; } @@ -254,7 +254,7 @@ int iwl_eeprom_init(struct iwl_priv *priv) } if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) { - IWL_ERROR("Time out reading EEPROM[%d]", addr); + IWL_ERROR("Time out reading EEPROM[%d]\n", addr); ret = -ETIMEDOUT; goto done; } diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c index 60a6e01..6283a3a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ b/drivers/net/wireless/iwlwifi/iwl-sta.c @@ -207,7 +207,7 @@ static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, case WLAN_HT_CAP_MIMO_PS_DISABLED: break; default: - IWL_WARNING("Invalid MIMO PS mode %d", mimo_ps_mode); + IWL_WARNING("Invalid MIMO PS mode %d\n", mimo_ps_mode); break; } @@ -969,7 +969,7 @@ int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) return priv->hw_params.bcast_sta_id; default: - IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); + IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode); return priv->hw_params.bcast_sta_id; } } diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 4108c7c..d82823b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c @@ -493,7 +493,7 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv) /* Alloc keep-warm buffer */ ret = iwl_kw_alloc(priv); if (ret) { - IWL_ERROR("Keep Warm allocation failed"); + IWL_ERROR("Keep Warm allocation failed\n"); goto error_kw; } spin_lock_irqsave(&priv->lock, flags); @@ -1463,7 +1463,7 @@ void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); if (scd_flow >= priv->hw_params.max_txq_num) { - IWL_ERROR("BUG_ON scd_flow is bigger than number of queues"); + IWL_ERROR("BUG_ON scd_flow is bigger than number of queues\n"); return; } diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 444847a..348048a 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -1558,7 +1558,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) BUILD_BUG_ON(sizeof(priv->eeprom) != IWL_EEPROM_IMAGE_SIZE); if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x", gp); + IWL_ERROR("EEPROM not found, EEPROM_GP=0x%08x\n", gp); return -ENOENT; } @@ -1583,7 +1583,7 @@ int iwl3945_eeprom_init(struct iwl3945_priv *priv) } if (!(r & CSR_EEPROM_REG_READ_VALID_MSK)) { - IWL_ERROR("Time out reading EEPROM[%d]", addr); + IWL_ERROR("Time out reading EEPROM[%d]\n", addr); return -ETIMEDOUT; } e[addr / 2] = le16_to_cpu((__force __le16)(r >> 16)); @@ -2507,7 +2507,7 @@ static int iwl3945_get_sta_id(struct iwl3945_priv *priv, struct ieee80211_hdr *h return priv->hw_setting.bcast_sta_id; default: - IWL_WARNING("Unknown mode of operation: %d", priv->iw_mode); + IWL_WARNING("Unknown mode of operation: %d\n", priv->iw_mode); return priv->hw_setting.bcast_sta_id; } } -- cgit v1.1 From 69bbc7dc9f59fedb6067c7f9f9f9bc1da27407ad Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 13 Aug 2008 23:41:45 +0200 Subject: p54: move p54_vdcf_init to the right place. priv->tx_hdr_len is set by the driver _after_ it called p54_init_common. While this isn't much a problem for any PCI or ISL3887 cards/sticks, because they don't need any extra header and therefore tx_hdr_len is zero for them... Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54common.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index 49afd20..29be3dc 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c @@ -837,10 +837,21 @@ static int p54_start(struct ieee80211_hw *dev) struct p54_common *priv = dev->priv; int err; + if (!priv->cached_vdcf) { + priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf)+ + priv->tx_hdr_len + sizeof(struct p54_control_hdr), + GFP_KERNEL); + + if (!priv->cached_vdcf) + return -ENOMEM; + } + err = priv->open(dev); if (!err) priv->mode = IEEE80211_IF_TYPE_MNTR; + p54_init_vdcf(dev); + return err; } @@ -1020,15 +1031,6 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) dev->extra_tx_headroom = sizeof(struct p54_control_hdr) + 4 + sizeof(struct p54_tx_control_allocdata); - priv->cached_vdcf = kzalloc(sizeof(struct p54_tx_control_vdcf) + - priv->tx_hdr_len + sizeof(struct p54_control_hdr), GFP_KERNEL); - - if (!priv->cached_vdcf) { - ieee80211_free_hw(dev); - return NULL; - } - - p54_init_vdcf(dev); mutex_init(&priv->conf_mutex); return dev; -- cgit v1.1 From d47c3cebf5aae9d72b2cc18e5ac3b520fdbb0bca Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Wed, 13 Aug 2008 23:41:48 +0200 Subject: p54u: reset skb's data/tail pointer on requeue (Only important for USB V1 Adaptors) If an incoming frame wasn't accepted by p54_rx function the skb will be reused for new frames... But, we must not forget to set the skb's data pointers into the same state in which it was initialized by p54u_init_urbs. Otherwise we either end up with 16 bytes less on every requeue, or if a new frame is worthy enough to be accepted, the data is in the wrong place (urb->transfer_buffer wasn't updated!) and mac80211 has a hard time to recognize it... Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/p54/p54usb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index 815c095..cbaca23 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c @@ -109,7 +109,17 @@ static void p54u_rx_cb(struct urb *urb) urb->context = skb; skb_queue_tail(&priv->rx_queue, skb); } else { + if (!priv->hw_type) + skb_push(skb, sizeof(struct net2280_tx_hdr)); + + skb_reset_tail_pointer(skb); skb_trim(skb, 0); + if (urb->transfer_buffer != skb_tail_pointer(skb)) { + /* this should not happen */ + WARN_ON(1); + urb->transfer_buffer = skb_tail_pointer(skb); + } + skb_queue_tail(&priv->rx_queue, skb); } -- cgit v1.1 From 430cd47fa98178b5199105fab4fb74e04bd0635c Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Thu, 14 Aug 2008 18:57:11 -0500 Subject: b43: Fix for another Bluetooth Coexistence SPROM Programming error for BCM4306 In trying to help users on the Ubuntu Bugzilla, I discovered another BCM4306 with the Bluetooth Coexistence programming error in the SPROM. This patch is contingent on the one that added the Linksys device with subdevice code of 0x0014. Signed-off-by: Larry Finger Cc: Stable Signed-off-by: John W. Linville --- drivers/net/wireless/b43/main.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ee462b5..8e09982 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -4615,6 +4615,7 @@ static void b43_sprom_fixup(struct ssb_bus *bus) if (bus->bustype == SSB_BUSTYPE_PCI) { pdev = bus->host_pci; if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) || + IS_PDEV(pdev, BROADCOM, 0x4320, DELL, 0x0003) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) || IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013)) -- cgit v1.1 From f126cba427170eac9e37311b2ab7afc0e2261906 Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Fri, 15 Aug 2008 14:47:46 +0200 Subject: rt2x00: Fix txdone_entry_desc_flags txdone_entry_desc_flags is used with __set_bit and test_bit which bit-shift the values, so don't bit-shift the flags in the enum. Also make sure flags are initialized before being used. Signed-off-by: Jochen Friedrich Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt2x00queue.h | 8 ++++---- drivers/net/wireless/rt2x00/rt2x00usb.c | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h index a4a8c57..ff78e52 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ b/drivers/net/wireless/rt2x00/rt2x00queue.h @@ -173,10 +173,10 @@ struct rxdone_entry_desc { * frame transmission failed due to excessive retries. */ enum txdone_entry_desc_flags { - TXDONE_UNKNOWN = 1 << 0, - TXDONE_SUCCESS = 1 << 1, - TXDONE_FAILURE = 1 << 2, - TXDONE_EXCESSIVE_RETRY = 1 << 3, + TXDONE_UNKNOWN, + TXDONE_SUCCESS, + TXDONE_FAILURE, + TXDONE_EXCESSIVE_RETRY, }; /** diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 8d76bb2..2050227 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c @@ -181,6 +181,7 @@ static void rt2x00usb_interrupt_txdone(struct urb *urb) * (Only indirectly by looking at the failed TX counters * in the register). */ + txdesc.flags = 0; if (!urb->status) __set_bit(TXDONE_UNKNOWN, &txdesc.flags); else -- cgit v1.1 From 3eb75aac8907e7ea36f0d078b2cc7393986001cf Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 17 Aug 2008 07:50:47 +0800 Subject: removed unused #include The drivers below do not use LINUX_VERSION_CODE nor KERNEL_VERSION. drivers/net/wireless/ath5k/base.c drivers/net/wireless/b43/main.c drivers/net/wireless/ipw2100.c drivers/net/wireless/ipw2200.c drivers/net/wireless/iwlwifi/iwl-3945.c drivers/net/wireless/iwlwifi/iwl-4965.c drivers/net/wireless/iwlwifi/iwl-5000.c drivers/net/wireless/iwlwifi/iwl-agn.c drivers/net/wireless/iwlwifi/iwl-core.c drivers/net/wireless/iwlwifi/iwl-eeprom.c drivers/net/wireless/iwlwifi/iwl-hcmd.c drivers/net/wireless/iwlwifi/iwl-power.c drivers/net/wireless/iwlwifi/iwl3945-base.c This patch removes the said #include . Signed-off-by: Huang Weiyi Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 1 - drivers/net/wireless/b43/main.c | 1 - drivers/net/wireless/ipw2100.c | 1 - drivers/net/wireless/ipw2200.c | 1 - drivers/net/wireless/iwlwifi/iwl-3945.c | 1 - drivers/net/wireless/iwlwifi/iwl-4965.c | 1 - drivers/net/wireless/iwlwifi/iwl-5000.c | 1 - drivers/net/wireless/iwlwifi/iwl-agn.c | 1 - drivers/net/wireless/iwlwifi/iwl-core.c | 1 - drivers/net/wireless/iwlwifi/iwl-eeprom.c | 1 - drivers/net/wireless/iwlwifi/iwl-hcmd.c | 1 - drivers/net/wireless/iwlwifi/iwl-power.c | 1 - drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 - 13 files changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index f19f33c..b20a45a 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -40,7 +40,6 @@ * */ -#include #include #include #include diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 8e09982..7205a93 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wireless/ipw2100.c b/drivers/net/wireless/ipw2100.c index c6f886e..19a401c 100644 --- a/drivers/net/wireless/ipw2100.c +++ b/drivers/net/wireless/ipw2100.c @@ -157,7 +157,6 @@ that only one external action is invoked at a time. #include #include #include -#include #include #include #include diff --git a/drivers/net/wireless/ipw2200.c b/drivers/net/wireless/ipw2200.c index 36e8d2f..dcce3542 100644 --- a/drivers/net/wireless/ipw2200.c +++ b/drivers/net/wireless/ipw2200.c @@ -31,7 +31,6 @@ ******************************************************************************/ #include "ipw2200.h" -#include #ifndef KBUILD_EXTMOD diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index b3931f6..3f51f36 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index 4a0cc78..e258122 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c @@ -26,7 +26,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index f3d139b..cbc01a0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index ed09e48..061ffba 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c index 9bd6180..c72f725 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ b/drivers/net/wireless/iwlwifi/iwl-core.c @@ -28,7 +28,6 @@ #include #include -#include #include struct iwl_priv; /* FIXME: remove */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c index 19985bf..3715575 100644 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ b/drivers/net/wireless/iwlwifi/iwl-eeprom.c @@ -63,7 +63,6 @@ #include #include -#include #include #include diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c index 6512834..2eb03ee 100644 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c @@ -28,7 +28,6 @@ #include #include -#include #include #include "iwl-dev.h" /* FIXME: remove */ diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c index 028e305..a099c9e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ b/drivers/net/wireless/iwlwifi/iwl-power.c @@ -29,7 +29,6 @@ #include #include -#include #include #include diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 348048a..b775d5b 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -29,7 +29,6 @@ #include #include -#include #include #include #include -- cgit v1.1 From a69999e286b5da33232694a2ad99c29419b91a44 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 18 Aug 2008 21:40:03 +0200 Subject: drivers/ide/pci/: use __devexit_p() This patch adds missing __devexit_p's. Reported-by: Russell King Signed-off-by: Adrian Bunk Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/aec62xx.c | 2 +- drivers/ide/pci/cy82c693.c | 2 +- drivers/ide/pci/hpt366.c | 2 +- drivers/ide/pci/it821x.c | 2 +- drivers/ide/pci/pdc202xx_new.c | 2 +- drivers/ide/pci/scc_pata.c | 2 +- drivers/ide/pci/siimage.c | 2 +- drivers/ide/pci/sis5513.c | 2 +- drivers/ide/pci/tc86c001.c | 2 +- drivers/ide/pci/via82cxxx.c | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/pci/aec62xx.c b/drivers/ide/pci/aec62xx.c index 40644b6..3187215 100644 --- a/drivers/ide/pci/aec62xx.c +++ b/drivers/ide/pci/aec62xx.c @@ -307,7 +307,7 @@ static struct pci_driver driver = { .name = "AEC62xx_IDE", .id_table = aec62xx_pci_tbl, .probe = aec62xx_init_one, - .remove = aec62xx_remove, + .remove = __devexit_p(aec62xx_remove), }; static int __init aec62xx_ide_init(void) diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index bfae2f8..e6d8ee8 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -447,7 +447,7 @@ static struct pci_driver driver = { .name = "Cypress_IDE", .id_table = cy82c693_pci_tbl, .probe = cy82c693_init_one, - .remove = cy82c693_remove, + .remove = __devexit_p(cy82c693_remove), }; static int __init cy82c693_ide_init(void) diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index 748793a..eb107ee 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c @@ -1620,7 +1620,7 @@ static struct pci_driver driver = { .name = "HPT366_IDE", .id_table = hpt366_pci_tbl, .probe = hpt366_init_one, - .remove = hpt366_remove, + .remove = __devexit_p(hpt366_remove), }; static int __init hpt366_ide_init(void) diff --git a/drivers/ide/pci/it821x.c b/drivers/ide/pci/it821x.c index b6dc723..4a1508a 100644 --- a/drivers/ide/pci/it821x.c +++ b/drivers/ide/pci/it821x.c @@ -686,7 +686,7 @@ static struct pci_driver driver = { .name = "ITE821x IDE", .id_table = it821x_pci_tbl, .probe = it821x_init_one, - .remove = it821x_remove, + .remove = __devexit_p(it821x_remove), }; static int __init it821x_ide_init(void) diff --git a/drivers/ide/pci/pdc202xx_new.c b/drivers/ide/pci/pdc202xx_new.c index 0f609b7..d477da6 100644 --- a/drivers/ide/pci/pdc202xx_new.c +++ b/drivers/ide/pci/pdc202xx_new.c @@ -566,7 +566,7 @@ static struct pci_driver driver = { .name = "Promise_IDE", .id_table = pdc202new_pci_tbl, .probe = pdc202new_init_one, - .remove = pdc202new_remove, + .remove = __devexit_p(pdc202new_remove), }; static int __init pdc202new_ide_init(void) diff --git a/drivers/ide/pci/scc_pata.c b/drivers/ide/pci/scc_pata.c index 6cde48b..44cccd1 100644 --- a/drivers/ide/pci/scc_pata.c +++ b/drivers/ide/pci/scc_pata.c @@ -954,7 +954,7 @@ static struct pci_driver driver = { .name = "SCC IDE", .id_table = scc_pci_tbl, .probe = scc_init_one, - .remove = scc_remove, + .remove = __devexit_p(scc_remove), }; static int scc_ide_init(void) diff --git a/drivers/ide/pci/siimage.c b/drivers/ide/pci/siimage.c index 445ce6f..db2b88a 100644 --- a/drivers/ide/pci/siimage.c +++ b/drivers/ide/pci/siimage.c @@ -832,7 +832,7 @@ static struct pci_driver driver = { .name = "SiI_IDE", .id_table = siimage_pci_tbl, .probe = siimage_init_one, - .remove = siimage_remove, + .remove = __devexit_p(siimage_remove), }; static int __init siimage_ide_init(void) diff --git a/drivers/ide/pci/sis5513.c b/drivers/ide/pci/sis5513.c index e5a4b42..5efe21d 100644 --- a/drivers/ide/pci/sis5513.c +++ b/drivers/ide/pci/sis5513.c @@ -610,7 +610,7 @@ static struct pci_driver driver = { .name = "SIS_IDE", .id_table = sis5513_pci_tbl, .probe = sis5513_init_one, - .remove = sis5513_remove, + .remove = __devexit_p(sis5513_remove), }; static int __init sis5513_ide_init(void) diff --git a/drivers/ide/pci/tc86c001.c b/drivers/ide/pci/tc86c001.c index 7fc88c3..927277c 100644 --- a/drivers/ide/pci/tc86c001.c +++ b/drivers/ide/pci/tc86c001.c @@ -249,7 +249,7 @@ static struct pci_driver driver = { .name = "TC86C001", .id_table = tc86c001_pci_tbl, .probe = tc86c001_init_one, - .remove = tc86c001_remove, + .remove = __devexit_p(tc86c001_remove), }; static int __init tc86c001_ide_init(void) diff --git a/drivers/ide/pci/via82cxxx.c b/drivers/ide/pci/via82cxxx.c index a6b2cc8..94fb9ab 100644 --- a/drivers/ide/pci/via82cxxx.c +++ b/drivers/ide/pci/via82cxxx.c @@ -491,7 +491,7 @@ static struct pci_driver driver = { .name = "VIA_IDE", .id_table = via_pci_tbl, .probe = via_init_one, - .remove = via_remove, + .remove = __devexit_p(via_remove), }; static int __init via_ide_init(void) -- cgit v1.1 From 3e636f78e5bbe95831e4d0071ee8f40b507e1cbd Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 18 Aug 2008 21:40:03 +0200 Subject: viocd: add dummy audio ioctl handler Make sure audio_ioctl is always defined even if being a dummy function since the cdrom_ioctl interface assumes its existence and we don't want to BUG on null ptr on some ioctls like, e.g. CDROMREADTOCENTRY, CDROMREADTOCHDR etc. when we fix CDC_PLAY_AUDIO checking in cdrom.c. Signed-off-by: Borislav Petkov Acked-by: Stephen Rothwell Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/cdrom/viocd.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 9d0dfe6..031e0e1 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -550,12 +550,19 @@ return_complete: } } +static int viocd_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, + void *arg) +{ + return -EINVAL; +} + static struct cdrom_device_ops viocd_dops = { .open = viocd_open, .release = viocd_release, .media_changed = viocd_media_changed, .lock_door = viocd_lock_door, .generic_packet = viocd_packet, + .audio_ioctl = viocd_audio_ioctl, .capability = CDC_CLOSE_TRAY | CDC_OPEN_TRAY | CDC_LOCK | CDC_SELECT_SPEED | CDC_SELECT_DISC | CDC_MULTI_SESSION | CDC_MCN | CDC_MEDIA_CHANGED | CDC_PLAY_AUDIO | CDC_RESET | CDC_DRIVE_STATUS | CDC_GENERIC_PACKET | CDC_CD_R | CDC_CD_RW | CDC_DVD | CDC_DVD_R | CDC_DVD_RAM | CDC_RAM }; -- cgit v1.1 From d15cad5df1dac17ae33152646f599f0bdc6be48e Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Mon, 18 Aug 2008 21:40:04 +0200 Subject: gdrom: add dummy audio_ioctl handler Make sure audio_ioctl is always defined even if being a dummy function since the cdrom_ioctl interface assumes its existence and we don't want to BUG on null ptr on some ioctls like, e.g. CDROMREADTOCENTRY, CDROMREADTOCHDR etc. when we fix CDC_PLAY_AUDIO checking in cdrom.c. Signed-off-by: Borislav Petkov Acked-by: Adrian McMenamin Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/cdrom/gdrom.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'drivers') diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 1e0455b..1231d95 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -471,6 +471,12 @@ cleanup_sense_final: return err; } +static int gdrom_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, + void *arg) +{ + return -EINVAL; +} + static struct cdrom_device_ops gdrom_ops = { .open = gdrom_open, .release = gdrom_release, @@ -478,6 +484,7 @@ static struct cdrom_device_ops gdrom_ops = { .media_changed = gdrom_mediachanged, .get_last_session = gdrom_get_last_session, .reset = gdrom_hardreset, + .audio_ioctl = gdrom_audio_ioctl, .capability = CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R, .n_minors = 1, -- cgit v1.1 From bce31b674846584f0a80c95b6c09f07c32b9b041 Mon Sep 17 00:00:00 2001 From: Alexander Inyukhin Date: Mon, 18 Aug 2008 21:40:04 +0200 Subject: cdrom: handle TOC This patch should fix TOC handling for cdroms that can not play audio. It extends commit af744e3294d09d706c4eae26cffaaa68a8d40337 ("cdrom: don't check CDC_PLAY_AUDIO in cdrom_count_tracks()") with a safety check and non-audio ioctls support. Since CDC_PLAY_AUDIO flag was used not only to check ability to play audio but also to ensure that audio_ioctl was not NULL, all TOC-related operations had to use it. As far as I understand, now audio_ioctl is never NULL, so a sanity check during device registration should be sufficient. It was tested on Optiarc AD7203A device, that has no ability to play audio. Cc: Tejun Heo Cc: Jens Axboe Cc: Borislav Petkov Signed-off-by: Andrew Morton [bart: remove now unneeded ->audio_ioctl check (noticed by Borislav)] Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/cdrom/cdrom.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'drivers') diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index d9d1b65..74031de 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -408,7 +408,6 @@ int register_cdrom(struct cdrom_device_info *cdi) ENSURE(get_last_session, CDC_MULTI_SESSION); ENSURE(get_mcn, CDC_MCN); ENSURE(reset, CDC_RESET); - ENSURE(audio_ioctl, CDC_PLAY_AUDIO); ENSURE(generic_packet, CDC_GENERIC_PACKET); cdi->mc_flags = 0; cdo->n_minors = 0; @@ -2506,8 +2505,6 @@ static int cdrom_ioctl_get_subchnl(struct cdrom_device_info *cdi, /* cdinfo(CD_DO_IOCTL,"entering CDROMSUBCHNL\n");*/ - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; if (copy_from_user(&q, argp, sizeof(q))) return -EFAULT; @@ -2538,8 +2535,6 @@ static int cdrom_ioctl_read_tochdr(struct cdrom_device_info *cdi, /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCHDR\n"); */ - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; if (copy_from_user(&header, argp, sizeof(header))) return -EFAULT; @@ -2562,8 +2557,6 @@ static int cdrom_ioctl_read_tocentry(struct cdrom_device_info *cdi, /* cdinfo(CD_DO_IOCTL, "entering CDROMREADTOCENTRY\n"); */ - if (!CDROM_CAN(CDC_PLAY_AUDIO)) - return -ENOSYS; if (copy_from_user(&entry, argp, sizeof(entry))) return -EFAULT; -- cgit v1.1 From fc99856a45cab8040f07d93d52fabd11834bf544 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 18 Aug 2008 21:40:04 +0200 Subject: ide-cd: use bcd2bin/bin2bcd Change ide-cd to use the new bcd2bin/bin2bcd functions instead of the obsolete BCD2BIN/BIN2BCD macros. Signed-off-by: Adrian Bunk Acked-by: Borislav Petkov Signed-off-by: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/ide-cd.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 89a112d..49a8c58 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -1272,9 +1272,9 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, */ static void msf_from_bcd(struct atapi_msf *msf) { - msf->minute = BCD2BIN(msf->minute); - msf->second = BCD2BIN(msf->second); - msf->frame = BCD2BIN(msf->frame); + msf->minute = bcd2bin(msf->minute); + msf->second = bcd2bin(msf->second); + msf->frame = bcd2bin(msf->frame); } int cdrom_check_status(ide_drive_t *drive, struct request_sense *sense) @@ -1415,8 +1415,8 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) return stat; if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) { - toc->hdr.first_track = BCD2BIN(toc->hdr.first_track); - toc->hdr.last_track = BCD2BIN(toc->hdr.last_track); + toc->hdr.first_track = bcd2bin(toc->hdr.first_track); + toc->hdr.last_track = bcd2bin(toc->hdr.last_track); } ntracks = toc->hdr.last_track - toc->hdr.first_track + 1; @@ -1456,8 +1456,8 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) return stat; if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) { - toc->hdr.first_track = (u8)BIN2BCD(CDROM_LEADOUT); - toc->hdr.last_track = (u8)BIN2BCD(CDROM_LEADOUT); + toc->hdr.first_track = (u8)bin2bcd(CDROM_LEADOUT); + toc->hdr.last_track = (u8)bin2bcd(CDROM_LEADOUT); } else { toc->hdr.first_track = CDROM_LEADOUT; toc->hdr.last_track = CDROM_LEADOUT; @@ -1470,14 +1470,14 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) toc->hdr.toc_length = be16_to_cpu(toc->hdr.toc_length); if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) { - toc->hdr.first_track = BCD2BIN(toc->hdr.first_track); - toc->hdr.last_track = BCD2BIN(toc->hdr.last_track); + toc->hdr.first_track = bcd2bin(toc->hdr.first_track); + toc->hdr.last_track = bcd2bin(toc->hdr.last_track); } for (i = 0; i <= ntracks; i++) { if (drive->atapi_flags & IDE_AFLAG_TOCADDR_AS_BCD) { if (drive->atapi_flags & IDE_AFLAG_TOCTRACKS_AS_BCD) - toc->ent[i].track = BCD2BIN(toc->ent[i].track); + toc->ent[i].track = bcd2bin(toc->ent[i].track); msf_from_bcd(&toc->ent[i].addr.msf); } toc->ent[i].addr.lba = msf_to_lba(toc->ent[i].addr.msf.minute, -- cgit v1.1 From 1b427a33b06ae76c64c1ad9af899a45b682ba6c6 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Mon, 18 Aug 2008 21:40:04 +0200 Subject: sgiioc4: fixup message on resource allocation failure There can be more than one sgiioc4 card in the system so print also PCI device name on resource allocation failure (so we know which one is the problematic one). Reported-by: Jeremy Higdon Signed-off-by: Bartlomiej Zolnierkiewicz --- drivers/ide/pci/sgiioc4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ide/pci/sgiioc4.c b/drivers/ide/pci/sgiioc4.c index 42eef19..681306c 100644 --- a/drivers/ide/pci/sgiioc4.c +++ b/drivers/ide/pci/sgiioc4.c @@ -621,9 +621,9 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev) if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE, DRV_NAME)) { printk(KERN_ERR - "%s : %s -- ERROR, Addresses " + "%s %s: -- ERROR, Addresses " "0x%p to 0x%p ALREADY in use\n", - __func__, DRV_NAME, (void *) cmd_phys_base, + DRV_NAME, pci_name(dev), (void *)cmd_phys_base, (void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE); return -ENOMEM; } -- cgit v1.1 From e0d94beead4ef652ec1c066be886140eebb06d8b Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 11 Aug 2008 17:47:40 +0200 Subject: PCI: acpi_pcihp: run _OSC on a root bridge _OSC should be ran on a root bridge instead of the device itself. Do this before touching OSHP since PCI fw specs states that _OSC should be preferred over OSHP (however if the device has OSHP but not _OSC -- not a root bridge -- it's not). Cc: kristen.c.accardi@intel.com Acked-by: Alex Chiang Signed-off-by: Jiri Slaby Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/acpi_pcihp.c | 41 ++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index 93e37f0..bd83197 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -382,7 +382,7 @@ EXPORT_SYMBOL_GPL(acpi_get_hp_params_from_firmware); int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) { acpi_status status; - acpi_handle chandle, handle = DEVICE_ACPI_HANDLE(&(dev->dev)); + acpi_handle chandle, handle; struct pci_dev *pdev = dev; struct pci_bus *parent; struct acpi_buffer string = { ACPI_ALLOCATE_BUFFER, NULL }; @@ -399,10 +399,28 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) * Per PCI firmware specification, we should run the ACPI _OSC * method to get control of hotplug hardware before using it. If * an _OSC is missing, we look for an OSHP to do the same thing. - * To handle different BIOS behavior, we look for _OSC and OSHP - * within the scope of the hotplug controller and its parents, + * To handle different BIOS behavior, we look for _OSC on a root + * bridge preferentially (according to PCI fw spec). Later for + * OSHP within the scope of the hotplug controller and its parents, * upto the host bridge under which this controller exists. */ + while (pdev->bus->self) + pdev = pdev->bus->self; + handle = acpi_get_pci_rootbridge_handle(pci_domain_nr(pdev->bus), + pdev->bus->number); + if (handle) { + acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); + dbg("Trying to get hotplug control for %s\n", + (char *)string.pointer); + status = pci_osc_control_set(handle, flags); + if (ACPI_SUCCESS(status)) + goto got_one; + kfree(string.pointer); + string = (struct acpi_buffer){ ACPI_ALLOCATE_BUFFER, NULL }; + } + + pdev = dev; + handle = DEVICE_ACPI_HANDLE(&dev->dev); while (!handle) { /* * This hotplug controller was not listed in the ACPI name @@ -427,15 +445,9 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); dbg("Trying to get hotplug control for %s \n", (char *)string.pointer); - status = pci_osc_control_set(handle, flags); - if (status == AE_NOT_FOUND) - status = acpi_run_oshp(handle); - if (ACPI_SUCCESS(status)) { - dbg("Gained control for hotplug HW for pci %s (%s)\n", - pci_name(dev), (char *)string.pointer); - kfree(string.pointer); - return 0; - } + status = acpi_run_oshp(handle); + if (ACPI_SUCCESS(status)) + goto got_one; if (acpi_root_bridge(handle)) break; chandle = handle; @@ -449,6 +461,11 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) kfree(string.pointer); return -ENODEV; +got_one: + dbg("Gained control for hotplug HW for pci %s (%s)\n", pci_name(dev), + (char *)string.pointer); + kfree(string.pointer); + return 0; } EXPORT_SYMBOL(acpi_get_hp_hw_control_from_firmware); -- cgit v1.1 From 056c58e8eb4d6765214757e541b68095e2eb2bd2 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 18 Aug 2008 20:22:54 +0200 Subject: PCI: add acpi_find_root_bridge_handle Consolidate finding of a root bridge and getting its handle to the one inline function. It's cut & pasted on multiple places. Use this new inline in those. Cc: kristen.c.accardi@intel.com Acked-by: Alex Chiang Signed-off-by: Jiri Slaby Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/acpi_pcihp.c | 5 +---- drivers/pci/pcie/aer/aerdrv_acpi.c | 7 +------ 2 files changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/acpi_pcihp.c b/drivers/pci/hotplug/acpi_pcihp.c index bd83197..e17ef54 100644 --- a/drivers/pci/hotplug/acpi_pcihp.c +++ b/drivers/pci/hotplug/acpi_pcihp.c @@ -404,10 +404,7 @@ int acpi_get_hp_hw_control_from_firmware(struct pci_dev *dev, u32 flags) * OSHP within the scope of the hotplug controller and its parents, * upto the host bridge under which this controller exists. */ - while (pdev->bus->self) - pdev = pdev->bus->self; - handle = acpi_get_pci_rootbridge_handle(pci_domain_nr(pdev->bus), - pdev->bus->number); + handle = acpi_find_root_bridge_handle(pdev); if (handle) { acpi_get_name(handle, ACPI_FULL_PATHNAME, &string); dbg("Trying to get hotplug control for %s\n", diff --git a/drivers/pci/pcie/aer/aerdrv_acpi.c b/drivers/pci/pcie/aer/aerdrv_acpi.c index 30f581b..6dd7b13 100644 --- a/drivers/pci/pcie/aer/aerdrv_acpi.c +++ b/drivers/pci/pcie/aer/aerdrv_acpi.c @@ -36,12 +36,7 @@ int aer_osc_setup(struct pcie_device *pciedev) if (acpi_pci_disabled) return -1; - /* Find root host bridge */ - while (pdev->bus->self) - pdev = pdev->bus->self; - handle = acpi_get_pci_rootbridge_handle( - pci_domain_nr(pdev->bus), pdev->bus->number); - + handle = acpi_find_root_bridge_handle(pdev); if (handle) { pcie_osc_support_set(OSC_EXT_PCI_CONFIG_SUPPORT); status = pci_osc_control_set(handle, -- cgit v1.1 From 9f593653742d1dd816c4e94c6e5154a57ccba6d1 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Mon, 18 Aug 2008 21:32:32 -0700 Subject: nf_nat: use secure_ipv4_port_ephemeral() for NAT port randomization Use incoming network tuple as seed for NAT port randomization. This avoids concerns of leaking net_random() bits, and also gives better port distribution. Don't have NAT server, compile tested only. Signed-off-by: Stephen Hemminger [ added missing EXPORT_SYMBOL_GPL ] Signed-off-by: Patrick McHardy Signed-off-by: David S. Miller --- drivers/char/random.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/char/random.c b/drivers/char/random.c index e0d0e37..1838aa3 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c @@ -1571,6 +1571,7 @@ u32 secure_ipv4_port_ephemeral(__be32 saddr, __be32 daddr, __be16 dport) return half_md4_transform(hash, keyptr->secret); } +EXPORT_SYMBOL_GPL(secure_ipv4_port_ephemeral); #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, -- cgit v1.1 From c85e2031eb55381a5e2f0f66c2e1d62ecd58eb85 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Tue, 19 Aug 2008 11:28:23 -0400 Subject: Input: evdev - fix printf() format for sizeof commit f2afa7711f8585ffc088ba538b9a510e0d5dca12 ("Input: paper over a bug in Synaptics X driver") introduced a compiler warning on 64-bit platforms, as sizeof() returns a size_t, not an (unsigned) int: | drivers/input/evdev.c: In function 'handle_eviocgbit': | drivers/input/evdev.c:684: warning: format '%d' expects type 'int', but argument 3 has type 'long unsigned int' Use the proper `z' modifier for size_t, and make the printf() formats for the sizes unsigned while we're at it. Signed-off-by: Geert Uytterhoeven Signed-off-by: Dmitry Torokhov --- drivers/input/evdev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index a92d815..3524bef 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -677,8 +677,8 @@ static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user len = OLD_KEY_MAX; if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) printk(KERN_WARNING - "evdev.c(EVIOCGBIT): Suspicious buffer size %d, " - "limiting output to %d bytes. See " + "evdev.c(EVIOCGBIT): Suspicious buffer size %u, " + "limiting output to %zu bytes. See " "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n", OLD_KEY_MAX, BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); -- cgit v1.1 From 6848408abf1bc18d9a4d5fed3fcca812745ece05 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 16 Aug 2008 13:36:47 +0200 Subject: ieee1394: regression in 2.6.25: updates should happen before probes Regression since commit 73cf60232ef16e1f8a64defa97214a1722db1e6c, "ieee1394: use class iteration api": The two loops for (1.) driver updates and (2.) driver probes were replaced by a single loop with bogus needs_probe checks. Hence updates and probes were now intermixed, and especially sbp2 updates (reconnects) held up longer than necessary. While we fix it, change the needs_probe flag to bool type for clarity. Tested by Damien Benoist. Signed-off-by: Stefan Richter --- drivers/ieee1394/nodemgr.c | 29 +++++++++++++++-------------- drivers/ieee1394/nodemgr.h | 2 +- 2 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 994a21e..2ebd09a8 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -844,7 +844,7 @@ static struct node_entry *nodemgr_create_node(octlet_t guid, struct csr1212_csr ne->host = host; ne->nodeid = nodeid; ne->generation = generation; - ne->needs_probe = 1; + ne->needs_probe = true; ne->guid = guid; ne->guid_vendor_id = (guid >> 40) & 0xffffff; @@ -1144,7 +1144,7 @@ static void nodemgr_process_root_directory(struct host_info *hi, struct node_ent struct csr1212_keyval *kv, *vendor_name_kv = NULL; u8 last_key_id = 0; - ne->needs_probe = 0; + ne->needs_probe = false; csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) { switch (kv->key.id) { @@ -1295,7 +1295,7 @@ static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr, nodemgr_update_bus_options(ne); /* Mark the node as new, so it gets re-probed */ - ne->needs_probe = 1; + ne->needs_probe = true; } else { /* old cache is valid, so update its generation */ struct nodemgr_csr_info *ci = ne->csr->private; @@ -1566,28 +1566,27 @@ static void nodemgr_probe_ne(struct host_info *hi, struct node_entry *ne, int ge struct probe_param { struct host_info *hi; int generation; + bool probe_now; }; -static int __nodemgr_node_probe(struct device *dev, void *data) +static int node_probe(struct device *dev, void *data) { - struct probe_param *param = (struct probe_param *)data; + struct probe_param *p = data; struct node_entry *ne; ne = container_of(dev, struct node_entry, node_dev); - if (!ne->needs_probe) - nodemgr_probe_ne(param->hi, ne, param->generation); - if (ne->needs_probe) - nodemgr_probe_ne(param->hi, ne, param->generation); + if (ne->needs_probe == p->probe_now) + nodemgr_probe_ne(p->hi, ne, p->generation); return 0; } static void nodemgr_node_probe(struct host_info *hi, int generation) { struct hpsb_host *host = hi->host; - struct probe_param param; + struct probe_param p; - param.hi = hi; - param.generation = generation; + p.hi = hi; + p.generation = generation; /* Do some processing of the nodes we've probed. This pulls them * into the sysfs layer if needed, and can result in processing of * unit-directories, or just updating the node and it's @@ -1597,8 +1596,10 @@ static void nodemgr_node_probe(struct host_info *hi, int generation) * while probes are time-consuming. (Well, those probes need some * improvement...) */ - class_for_each_device(&nodemgr_ne_class, NULL, ¶m, - __nodemgr_node_probe); + p.probe_now = false; + class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe); + p.probe_now = true; + class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe); /* If we had a bus reset while we were scanning the bus, it is * possible that we did not probe all nodes. In that case, we diff --git a/drivers/ieee1394/nodemgr.h b/drivers/ieee1394/nodemgr.h index 919e92e..6eb2646 100644 --- a/drivers/ieee1394/nodemgr.h +++ b/drivers/ieee1394/nodemgr.h @@ -97,7 +97,7 @@ struct node_entry { struct hpsb_host *host; /* Host this node is attached to */ nodeid_t nodeid; /* NodeID */ struct bus_options busopt; /* Bus Options */ - int needs_probe; + bool needs_probe; unsigned int generation; /* Synced with hpsb generation */ /* The following is read from the config rom */ -- cgit v1.1 From c921a9745705ed62a949192ef9128c60d6c63874 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 16 Aug 2008 13:38:11 +0200 Subject: ieee1394: don't drop nodes during bus reset series nodemgr_node_probe checked for generation increments too late and therefore prematurely reported nodes as "suspended". Fixes http://bugzilla.kernel.org/show_bug.cgi?id=11349. Reported and tested by Damien Benoist. Signed-off-by: Stefan Richter --- drivers/ieee1394/nodemgr.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 2ebd09a8..16240a7 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -1574,6 +1574,9 @@ static int node_probe(struct device *dev, void *data) struct probe_param *p = data; struct node_entry *ne; + if (p->generation != get_hpsb_generation(p->hi->host)) + return -EAGAIN; + ne = container_of(dev, struct node_entry, node_dev); if (ne->needs_probe == p->probe_now) nodemgr_probe_ne(p->hi, ne, p->generation); @@ -1582,42 +1585,41 @@ static int node_probe(struct device *dev, void *data) static void nodemgr_node_probe(struct host_info *hi, int generation) { - struct hpsb_host *host = hi->host; struct probe_param p; p.hi = hi; p.generation = generation; - /* Do some processing of the nodes we've probed. This pulls them + /* + * Do some processing of the nodes we've probed. This pulls them * into the sysfs layer if needed, and can result in processing of * unit-directories, or just updating the node and it's * unit-directories. * * Run updates before probes. Usually, updates are time-critical - * while probes are time-consuming. (Well, those probes need some - * improvement...) */ - + * while probes are time-consuming. + * + * Meanwhile, another bus reset may have happened. In this case we + * skip everything here and let the next bus scan handle it. + * Otherwise we may prematurely remove nodes which are still there. + */ p.probe_now = false; - class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe); - p.probe_now = true; - class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe); + if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0) + return; - /* If we had a bus reset while we were scanning the bus, it is - * possible that we did not probe all nodes. In that case, we - * skip the clean up for now, since we could remove nodes that - * were still on the bus. Another bus scan is pending which will - * do the clean up eventually. - * + p.probe_now = true; + if (class_for_each_device(&nodemgr_ne_class, NULL, &p, node_probe) != 0) + return; + /* * Now let's tell the bus to rescan our devices. This may seem * like overhead, but the driver-model core will only scan a * device for a driver when either the device is added, or when a * new driver is added. A bus reset is a good reason to rescan * devices that were there before. For example, an sbp2 device * may become available for login, if the host that held it was - * just removed. */ - - if (generation == get_hpsb_generation(host)) - if (bus_rescan_devices(&ieee1394_bus_type)) - HPSB_DEBUG("bus_rescan_devices had an error"); + * just removed. + */ + if (bus_rescan_devices(&ieee1394_bus_type) != 0) + HPSB_DEBUG("bus_rescan_devices had an error"); } static int nodemgr_send_resume_packet(struct hpsb_host *host) -- cgit v1.1 From a3384067fb0df9c58e112ac6a5ec9beb7d169482 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 16 Aug 2008 13:39:26 +0200 Subject: ieee1394: sbp2: let nodemgr retry node updates during bus reset series sbp2 was too quick to report .update() to the ieee1394 core as failed. (Logged as "Failed to reconnect to sbp2 device!".) The core would then unbind sbp2 from the device. This is not justified if the .update() failed because another bus reset happened. We check this and tell the ieee1394 that .update() succeeded, and the core will call sbp2's .update() for the new bus reset as well. This improves reconnection/re-login especially on buses with several disks as they may issue bus resets in close succession when they come online. Tested by Damien Benoist. Signed-off-by: Stefan Richter --- drivers/ieee1394/sbp2.c | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/ieee1394/sbp2.c b/drivers/ieee1394/sbp2.c index 9cbf315..1d6ad34 100644 --- a/drivers/ieee1394/sbp2.c +++ b/drivers/ieee1394/sbp2.c @@ -731,15 +731,26 @@ static int sbp2_update(struct unit_directory *ud) { struct sbp2_lu *lu = ud->device.driver_data; - if (sbp2_reconnect_device(lu)) { - /* Reconnect has failed. Perhaps we didn't reconnect fast - * enough. Try a regular login, but first log out just in - * case of any weirdness. */ + if (sbp2_reconnect_device(lu) != 0) { + /* + * Reconnect failed. If another bus reset happened, + * let nodemgr proceed and call sbp2_update again later + * (or sbp2_remove if this node went away). + */ + if (!hpsb_node_entry_valid(lu->ne)) + return 0; + /* + * Or the target rejected the reconnect because we weren't + * fast enough. Try a regular login, but first log out + * just in case of any weirdness. + */ sbp2_logout_device(lu); - if (sbp2_login_device(lu)) { - /* Login failed too, just fail, and the backend - * will call our sbp2_remove for us */ + if (sbp2_login_device(lu) != 0) { + if (!hpsb_node_entry_valid(lu->ne)) + return 0; + + /* Maybe another initiator won the login. */ SBP2_ERR("Failed to reconnect to sbp2 device!"); return -EBUSY; } -- cgit v1.1 From 30b0aa7c9a5e769a874a456cd56396eebf164b91 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Sat, 16 Aug 2008 21:52:28 +0200 Subject: firewire: Kconfig help update Signed-off-by: Stefan Richter --- drivers/firewire/Kconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/firewire/Kconfig b/drivers/firewire/Kconfig index fa6d6ab..4509024 100644 --- a/drivers/firewire/Kconfig +++ b/drivers/firewire/Kconfig @@ -12,8 +12,8 @@ config FIREWIRE This is the "Juju" FireWire stack, a new alternative implementation designed for robustness and simplicity. You can build either this stack, or the old stack (the ieee1394 driver, ohci1394 etc.) or both. - Please read http://wiki.linux1394.org/JujuMigration before you - enable the new stack. + Please read http://ieee1394.wiki.kernel.org/index.php/Juju_Migration + before you enable the new stack. To compile this driver as a module, say M here: the module will be called firewire-core. -- cgit v1.1 From a77a57a1a22afc31891d95879fe3cf2ab03838b0 Mon Sep 17 00:00:00 2001 From: Roland Dreier Date: Tue, 19 Aug 2008 15:01:32 -0700 Subject: IPoIB: Fix deadlock on RTNL in ipoib_stop() Commit c8c2afe3 ("IPoIB: Use rtnl lock/unlock when changing device flags") added a call to rtnl_lock() in ipoib_mcast_join_task(), which is run from the ipoib_workqueue. However, ipoib_stop() (which is run inside rtnl_lock()) flushes this workqueue, which leads to a deadlock if the join task is pending. Fix this by simply not flushing the workqueue from ipoib_stop(). It turns out that we really don't care about workqueue tasks running during or after ipoib_stop(), as long as we make sure to flush the workqueue before unregistering a netdev. This fixes . Signed-off-by: Roland Dreier --- drivers/infiniband/ulp/ipoib/ipoib_main.c | 19 +++++++++---------- drivers/infiniband/ulp/ipoib/ipoib_multicast.c | 10 +++++++++- 2 files changed, 18 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index f51201b..7e9e218 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -156,14 +156,8 @@ static int ipoib_stop(struct net_device *dev) netif_stop_queue(dev); - /* - * Now flush workqueue to make sure a scheduled task doesn't - * bring our internal state back up. - */ - flush_workqueue(ipoib_workqueue); - - ipoib_ib_dev_down(dev, 1); - ipoib_ib_dev_stop(dev, 1); + ipoib_ib_dev_down(dev, 0); + ipoib_ib_dev_stop(dev, 0); if (!test_bit(IPOIB_FLAG_SUBINTERFACE, &priv->flags)) { struct ipoib_dev_priv *cpriv; @@ -1314,7 +1308,7 @@ sysfs_failed: register_failed: ib_unregister_event_handler(&priv->event_handler); - flush_scheduled_work(); + flush_workqueue(ipoib_workqueue); event_failed: ipoib_dev_cleanup(priv->dev); @@ -1373,7 +1367,12 @@ static void ipoib_remove_one(struct ib_device *device) list_for_each_entry_safe(priv, tmp, dev_list, list) { ib_unregister_event_handler(&priv->event_handler); - flush_scheduled_work(); + + rtnl_lock(); + dev_change_flags(priv->dev, priv->dev->flags & ~IFF_UP); + rtnl_unlock(); + + flush_workqueue(ipoib_workqueue); unregister_netdev(priv->dev); ipoib_dev_cleanup(priv->dev); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index 8950e95..ac33c8f 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -392,8 +392,16 @@ static int ipoib_mcast_join_complete(int status, &priv->mcast_task, 0); mutex_unlock(&mcast_mutex); - if (mcast == priv->broadcast) + if (mcast == priv->broadcast) { + /* + * Take RTNL lock here to avoid racing with + * ipoib_stop() and turning the carrier back + * on while a device is being removed. + */ + rtnl_lock(); netif_carrier_on(dev); + rtnl_unlock(); + } return 0; } -- cgit v1.1 From 4589f1fe570c2c786b72eff146b2f168821882c6 Mon Sep 17 00:00:00 2001 From: Joachim Fenkes Date: Wed, 6 Aug 2008 00:30:18 +1000 Subject: powerpc/ibmebus: Restore "name" sysfs attribute on ibmebus devices Recent of_platform changes made of_bus_type_init() overwrite the bus type's .dev_attrs list, meaning that the "name" attribute that ibmebus devices previously had is no longer present. This is a user-visible regression which breaks the userspace eHCA support, since the eHCA userspace driver relies on the name attribute to check for valid adapters. This fixes it by providing the "name" attribute in the generic OF device code instead. Tested on POWER. Signed-off-by: Joachim Fenkes Signed-off-by: Paul Mackerras --- drivers/of/device.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'drivers') diff --git a/drivers/of/device.c b/drivers/of/device.c index 8a1d93a..51e5214 100644 --- a/drivers/of/device.c +++ b/drivers/of/device.c @@ -57,6 +57,15 @@ static ssize_t devspec_show(struct device *dev, return sprintf(buf, "%s\n", ofdev->node->full_name); } +static ssize_t name_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + return sprintf(buf, "%s\n", ofdev->node->name); +} + static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, char *buf) { @@ -71,6 +80,7 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute of_platform_device_attrs[] = { __ATTR_RO(devspec), + __ATTR_RO(name), __ATTR_RO(modalias), __ATTR_NULL }; -- cgit v1.1 From f14413184b1de4dcbd5ec3e7c129c3ce2079f543 Mon Sep 17 00:00:00 2001 From: Matthew Garrett Date: Wed, 20 Aug 2008 14:08:57 -0700 Subject: eeepc-laptop: fix use after free eeepc-laptop uses the hwmon struct after unregistering the device, causing an oops on module unload. Flip the ordering to fix. Signed-off-by: Matthew Garrett Cc: Henrique de Moraes Holschuh Cc: Corentin Chary Cc: Karol Kozimor Cc: [2.6.26.x] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/misc/eeepc-laptop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/misc/eeepc-laptop.c b/drivers/misc/eeepc-laptop.c index 9e8d79e..facdb98 100644 --- a/drivers/misc/eeepc-laptop.c +++ b/drivers/misc/eeepc-laptop.c @@ -553,9 +553,9 @@ static void eeepc_hwmon_exit(void) hwmon = eeepc_hwmon_device; if (!hwmon) return ; - hwmon_device_unregister(hwmon); sysfs_remove_group(&hwmon->kobj, &hwmon_attribute_group); + hwmon_device_unregister(hwmon); eeepc_hwmon_device = NULL; } -- cgit v1.1 From fe2e1cf83a46c879a66ec5146ba7a09a6aef0a5c Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 20 Aug 2008 14:09:01 -0700 Subject: Blackfin RTC Driver: move irq request/free out of open/release and into probe/remove so that the non-dev interfaces (like sysfs) work as expected Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 51 ++++++++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 31 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index a1af4c2..51741dc 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -218,26 +218,6 @@ static irqreturn_t bfin_rtc_interrupt(int irq, void *dev_id) return IRQ_NONE; } -static int bfin_rtc_open(struct device *dev) -{ - int ret; - - dev_dbg_stamp(dev); - - ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, to_platform_device(dev)->name, dev); - if (!ret) - bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); - - return ret; -} - -static void bfin_rtc_release(struct device *dev) -{ - dev_dbg_stamp(dev); - bfin_rtc_reset(dev, 0); - free_irq(IRQ_RTC, dev); -} - static void bfin_rtc_int_set(u16 rtc_int) { bfin_write_RTC_ISTAT(rtc_int); @@ -370,8 +350,6 @@ static int bfin_rtc_proc(struct device *dev, struct seq_file *seq) } static struct rtc_class_ops bfin_rtc_ops = { - .open = bfin_rtc_open, - .release = bfin_rtc_release, .ioctl = bfin_rtc_ioctl, .read_time = bfin_rtc_read_time, .set_time = bfin_rtc_set_time, @@ -383,29 +361,37 @@ static struct rtc_class_ops bfin_rtc_ops = { static int __devinit bfin_rtc_probe(struct platform_device *pdev) { struct bfin_rtc *rtc; + struct device *dev = &pdev->dev; int ret = 0; - dev_dbg_stamp(&pdev->dev); + dev_dbg_stamp(dev); + /* Allocate memory for our RTC struct */ rtc = kzalloc(sizeof(*rtc), GFP_KERNEL); if (unlikely(!rtc)) return -ENOMEM; + platform_set_drvdata(pdev, rtc); - rtc->rtc_dev = rtc_device_register(pdev->name, &pdev->dev, &bfin_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc)) { - ret = PTR_ERR(rtc->rtc_dev); + /* Grab the IRQ and init the hardware */ + ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); + if (unlikely(ret)) goto err; - } - - /* see comment at top of file about stopwatch/PIE */ + bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); bfin_write_RTC_SWCNT(0); - platform_set_drvdata(pdev, rtc); + /* Register our RTC with the RTC framework */ + rtc->rtc_dev = rtc_device_register(pdev->name, dev, &bfin_rtc_ops, THIS_MODULE); + if (unlikely(IS_ERR(rtc))) { + ret = PTR_ERR(rtc->rtc_dev); + goto err_irq; + } - device_init_wakeup(&pdev->dev, 1); + device_init_wakeup(dev, 1); return 0; + err_irq: + free_irq(IRQ_RTC, dev); err: kfree(rtc); return ret; @@ -414,7 +400,10 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) static int __devexit bfin_rtc_remove(struct platform_device *pdev) { struct bfin_rtc *rtc = platform_get_drvdata(pdev); + struct device *dev = &pdev->dev; + bfin_rtc_reset(dev, 0); + free_irq(IRQ_RTC, dev); rtc_device_unregister(rtc->rtc_dev); platform_set_drvdata(pdev, NULL); kfree(rtc); -- cgit v1.1 From 8c9166f7a60b67909632ea60a032c18d84ed8af0 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 20 Aug 2008 14:09:02 -0700 Subject: Blackfin RTC Driver: do all initialization before we register the rtc and make it available Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 51741dc..9d2da1c 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -371,6 +371,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) if (unlikely(!rtc)) return -ENOMEM; platform_set_drvdata(pdev, rtc); + device_init_wakeup(dev, 1); /* Grab the IRQ and init the hardware */ ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); @@ -386,8 +387,6 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) goto err_irq; } - device_init_wakeup(dev, 1); - return 0; err_irq: -- cgit v1.1 From 7f60459921bd24e86b21e07c42244c510b4f46b2 Mon Sep 17 00:00:00 2001 From: Graf Yang Date: Wed, 20 Aug 2008 14:09:02 -0700 Subject: Blackfin RTC Driver: BF561 not have on-chip RTC Signed-off-by: Graf Yang Signed-off-by: Bryan Wu Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 90ab738..9a9755c 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -561,7 +561,7 @@ config RTC_DRV_AT91SAM9_GPBR config RTC_DRV_BFIN tristate "Blackfin On-Chip RTC" - depends on BLACKFIN + depends on BLACKFIN && !BF561 help If you say yes here you will get support for the Blackfin On-Chip Real Time Clock. -- cgit v1.1 From d0fd93781c49cbe127f9e7a5b402e9b167c105a6 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 20 Aug 2008 14:09:03 -0700 Subject: Blackfin RTC Driver: dont let RTC programming in bootloaders randomly cause ~5 second boot delays Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Cc: Alessandro Zummo Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-bfin.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/rtc/rtc-bfin.c b/drivers/rtc/rtc-bfin.c index 9d2da1c..34439ce 100644 --- a/drivers/rtc/rtc-bfin.c +++ b/drivers/rtc/rtc-bfin.c @@ -363,6 +363,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) struct bfin_rtc *rtc; struct device *dev = &pdev->dev; int ret = 0; + unsigned long timeout; dev_dbg_stamp(dev); @@ -377,6 +378,13 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); if (unlikely(ret)) goto err; + /* sometimes the bootloader touched things, but the write complete was not + * enabled, so let's just do a quick timeout here since the IRQ will not fire ... + */ + timeout = jiffies + HZ; + while (bfin_read_RTC_ISTAT() & RTC_ISTAT_WRITE_PENDING) + if (time_after(jiffies, timeout)) + break; bfin_rtc_reset(dev, RTC_ISTAT_WRITE_COMPLETE); bfin_write_RTC_SWCNT(0); -- cgit v1.1 From f3944d61ddc65722539ffd7b6f5b7c7217c136cc Mon Sep 17 00:00:00 2001 From: Sven Wegener Date: Wed, 20 Aug 2008 14:09:07 -0700 Subject: nbd: fix memory leak of nbd_dev array We leak the memory allocated for the nbd_dev array at multiple places. Fix them by either adding a kfree() or by rearranging code to return before we allocate the memory. Signed-off-by: Sven Wegener Cc: Paul Clements Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/nbd.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index ad98dda..1778e4a 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c @@ -707,15 +707,15 @@ static int __init nbd_init(void) BUILD_BUG_ON(sizeof(struct nbd_request) != 28); - nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); - if (!nbd_dev) - return -ENOMEM; - if (max_part < 0) { printk(KERN_CRIT "nbd: max_part must be >= 0\n"); return -EINVAL; } + nbd_dev = kcalloc(nbds_max, sizeof(*nbd_dev), GFP_KERNEL); + if (!nbd_dev) + return -ENOMEM; + part_shift = 0; if (max_part > 0) part_shift = fls(max_part); @@ -779,6 +779,7 @@ out: blk_cleanup_queue(nbd_dev[i].disk->queue); put_disk(nbd_dev[i].disk); } + kfree(nbd_dev); return err; } @@ -795,6 +796,7 @@ static void __exit nbd_cleanup(void) } } unregister_blkdev(NBD_MAJOR, "nbd"); + kfree(nbd_dev); printk(KERN_INFO "nbd: unregistered device at major %d\n", NBD_MAJOR); } -- cgit v1.1 From c82f2966015a2c9708fb8f20694ef7ba8567d2e1 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 20 Aug 2008 14:09:09 -0700 Subject: brd: fix name argument of unregister_blkdev() The name of brd block device is "ramdisk", it's not "brd". (The block device is registered by register_blkdev(RAMDISK_MAJOR, "ramdisk") So it should be unregistered by unregister_blkdev(RAMDISK_MAJOR, "ramdisk") Signed-off-by: Akinobu Mita Acked-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/block/brd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 24b97b0..d070d49 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c @@ -571,8 +571,8 @@ out_free: list_del(&brd->brd_list); brd_free(brd); } + unregister_blkdev(RAMDISK_MAJOR, "ramdisk"); - unregister_blkdev(RAMDISK_MAJOR, "brd"); return -ENOMEM; } -- cgit v1.1 From 1d96469a34781340b2cc9bdf97d5913eecdaa038 Mon Sep 17 00:00:00 2001 From: Atsushi Nemoto Date: Wed, 20 Aug 2008 14:09:11 -0700 Subject: rtc: fix double lock on UIE emulation With commit 5ad31a575157147b43fa84ef1e21471661653878 ("rtc: remove BKL for ioctl()"), RTC_UIE_ON ioctl cause double lock on rtc->ops_lock. The ops_lock must not be held while set_uie() calls rtc_read_time() which takes the lock. Also clear_uie() does not need ops_lock. This patch fixes return value of RTC_UIE_OFF ioctl too. Signed-off-by: Atsushi Nemoto Cc: David Brownell Cc: Russell King Cc: Alessandro Zummo Cc: "Rafael J. Wysocki" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-dev.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-dev.c b/drivers/rtc/rtc-dev.c index 35dcc06..f118252 100644 --- a/drivers/rtc/rtc-dev.c +++ b/drivers/rtc/rtc-dev.c @@ -403,11 +403,14 @@ static long rtc_dev_ioctl(struct file *file, #ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL case RTC_UIE_OFF: + mutex_unlock(&rtc->ops_lock); clear_uie(rtc); - break; + return 0; case RTC_UIE_ON: + mutex_unlock(&rtc->ops_lock); err = set_uie(rtc); + return err; #endif default: err = -ENOTTY; -- cgit v1.1 From 27aa069a8850a36b8aef0160e73cfd928c6bbcc4 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Wed, 20 Aug 2008 14:09:11 -0700 Subject: pm2fb: free cmap memory on module remove Release cmap memory allocated in the probe function. Signed-off-by: Krzysztof Helt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/pm2fb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/video/pm2fb.c b/drivers/video/pm2fb.c index 3f1ca2a..c6dd924 100644 --- a/drivers/video/pm2fb.c +++ b/drivers/video/pm2fb.c @@ -1746,6 +1746,7 @@ static void __devexit pm2fb_remove(struct pci_dev *pdev) release_mem_region(fix->mmio_start, fix->mmio_len); pci_set_drvdata(pdev, NULL); + fb_dealloc_cmap(&info->cmap); kfree(info->pixmap.addr); kfree(info); } -- cgit v1.1 From a09f48551273ee89d4e9ae37474807dc2da1d757 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Wed, 20 Aug 2008 14:09:14 -0700 Subject: drivers/char/ipmi/ipmi_si_intf.c:default_find_bmc(): fix leak If check_legacy_ioport() returns true, we leak *info. Addresses http://bugzilla.kernel.org/show_bug.cgi?id=11362 Reported-by: Daniel Marjamki Cc: Christian Krafft Cc: Michael Ellerman Cc: Corey Minyard Cc: Paul Mackerras Cc: Benjamin Herrenschmidt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/char/ipmi/ipmi_si_intf.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index f52931e..8e8afb6 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c @@ -2695,15 +2695,13 @@ static __devinit void default_find_bmc(void) for (i = 0; ; i++) { if (!ipmi_defaults[i].port) break; - - info = kzalloc(sizeof(*info), GFP_KERNEL); - if (!info) - return; - #ifdef CONFIG_PPC_MERGE if (check_legacy_ioport(ipmi_defaults[i].port)) continue; #endif + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return; info->addr_source = NULL; -- cgit v1.1 From 141d87e7debe3334018e46859c7565c44cebda65 Mon Sep 17 00:00:00 2001 From: Michael Hennerich Date: Wed, 20 Aug 2008 14:09:16 -0700 Subject: Video/Framebuffer: add fuctional power management support to Blackfin BF54x LQ043 framebuffer driver Fix bug: does nor properply resume after suspend mem Fix for PM_SUSPEND_MEM: Save and restore peripheral base and DMA registers Signed-off-by: Michael Hennerich Signed-off-by: Bryan Wu Acked-by: Krzysztof Helt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/bf54x-lq043fb.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 940467a..6d5aa80 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -733,7 +733,6 @@ static int bfin_bf54x_remove(struct platform_device *pdev) static int bfin_bf54x_suspend(struct platform_device *pdev, pm_message_t state) { struct fb_info *fbinfo = platform_get_drvdata(pdev); - struct bfin_bf54xfb_info *info = fbinfo->par; bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() & ~EPPI_EN); disable_dma(CH_EPPI0); @@ -747,8 +746,18 @@ static int bfin_bf54x_resume(struct platform_device *pdev) struct fb_info *fbinfo = platform_get_drvdata(pdev); struct bfin_bf54xfb_info *info = fbinfo->par; - enable_dma(CH_EPPI0); - bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN); + if (info->lq043_open_cnt) { + + bfin_write_EPPI0_CONTROL(0); + SSYNC(); + + config_dma(info); + config_ppi(info); + + /* start dma */ + enable_dma(CH_EPPI0); + bfin_write_EPPI0_CONTROL(bfin_read_EPPI0_CONTROL() | EPPI_EN); + } return 0; } -- cgit v1.1 From b42f931737bea8ca3982449d63ec46410d13e891 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Wed, 20 Aug 2008 14:09:21 -0700 Subject: rtc: rtc-ds1374: fix 'no irq' case handling On a PowerPC board with ds1374 RTC I'm getting this error while RTC tries to probe: rtc-ds1374 0-0068: unable to request IRQ This happens because I2C probing code (drivers/of/of_i2c.c) is specifying IRQ0 for 'no irq' case, which is correct. The driver handles this incorrectly, though. This patch fixes it. Signed-off-by: Anton Vorontsov Cc: David Brownell Cc: Alessandro Zummo Acked-by: Peter Korsgaard Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/rtc/rtc-ds1374.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/rtc/rtc-ds1374.c b/drivers/rtc/rtc-ds1374.c index 640acd2..a150418 100644 --- a/drivers/rtc/rtc-ds1374.c +++ b/drivers/rtc/rtc-ds1374.c @@ -173,7 +173,7 @@ static int ds1374_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) int cr, sr; int ret = 0; - if (client->irq < 0) + if (client->irq <= 0) return -EINVAL; mutex_lock(&ds1374->mutex); @@ -212,7 +212,7 @@ static int ds1374_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) int cr; int ret = 0; - if (client->irq < 0) + if (client->irq <= 0) return -EINVAL; ret = ds1374_read_time(dev, &now); @@ -381,7 +381,7 @@ static int ds1374_probe(struct i2c_client *client, if (ret) goto out_free; - if (client->irq >= 0) { + if (client->irq > 0) { ret = request_irq(client->irq, ds1374_irq, 0, "ds1374", client); if (ret) { @@ -401,7 +401,7 @@ static int ds1374_probe(struct i2c_client *client, return 0; out_irq: - if (client->irq >= 0) + if (client->irq > 0) free_irq(client->irq, client); out_free: @@ -414,7 +414,7 @@ static int __devexit ds1374_remove(struct i2c_client *client) { struct ds1374 *ds1374 = i2c_get_clientdata(client); - if (client->irq >= 0) { + if (client->irq > 0) { mutex_lock(&ds1374->mutex); ds1374->exiting = 1; mutex_unlock(&ds1374->mutex); -- cgit v1.1 From d847471d063663b9f36927d265c66a270c0cfaab Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 20 Aug 2008 14:09:23 -0700 Subject: fbdefio: add set_page_dirty handler to deferred IO FB Fixes kernel BUG at lib/radix-tree.c:473. Previously the handler was incidentally provided by tmpfs but this was removed with: commit 14fcc23fdc78e9d32372553ccf21758a9bd56fa1 Author: Hugh Dickins Date: Mon Jul 28 15:46:19 2008 -0700 tmpfs: fix kernel BUG in shmem_delete_inode relying on this behaviour was incorrect in any case and the BUG also appeared when the device node was on an ext3 filesystem. v2: override a_ops at open() time rather than mmap() time to minimise races per AKPM's concerns. Signed-off-by: Ian Campbell Cc: Jaya Kumar Cc: Nick Piggin Cc: Peter Zijlstra Cc: Hugh Dickins Cc: Johannes Weiner Cc: Jeremy Fitzhardinge Cc: Kel Modderman Cc: Markus Armbruster Cc: Krzysztof Helt Cc: [14fcc23fd is in 2.6.25.14 and 2.6.26.1] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- drivers/video/fb_defio.c | 19 +++++++++++++++++++ drivers/video/fbmem.c | 4 ++++ 2 files changed, 23 insertions(+) (limited to 'drivers') diff --git a/drivers/video/fb_defio.c b/drivers/video/fb_defio.c index 59df132..4835bdc 100644 --- a/drivers/video/fb_defio.c +++ b/drivers/video/fb_defio.c @@ -114,6 +114,17 @@ static struct vm_operations_struct fb_deferred_io_vm_ops = { .page_mkwrite = fb_deferred_io_mkwrite, }; +static int fb_deferred_io_set_page_dirty(struct page *page) +{ + if (!PageDirty(page)) + SetPageDirty(page); + return 0; +} + +static const struct address_space_operations fb_deferred_io_aops = { + .set_page_dirty = fb_deferred_io_set_page_dirty, +}; + static int fb_deferred_io_mmap(struct fb_info *info, struct vm_area_struct *vma) { vma->vm_ops = &fb_deferred_io_vm_ops; @@ -163,6 +174,14 @@ void fb_deferred_io_init(struct fb_info *info) } EXPORT_SYMBOL_GPL(fb_deferred_io_init); +void fb_deferred_io_open(struct fb_info *info, + struct inode *inode, + struct file *file) +{ + file->f_mapping->a_ops = &fb_deferred_io_aops; +} +EXPORT_SYMBOL_GPL(fb_deferred_io_open); + void fb_deferred_io_cleanup(struct fb_info *info) { void *screen_base = (void __force *) info->screen_base; diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 6b48780..98843c2 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1344,6 +1344,10 @@ fb_open(struct inode *inode, struct file *file) if (res) module_put(info->fbops->owner); } +#ifdef CONFIG_FB_DEFERRED_IO + if (info->fbdefio) + fb_deferred_io_open(info, inode, file); +#endif out: unlock_kernel(); return res; -- cgit v1.1 From 26d02d1db7d84729b1e49789341e69a493c60ceb Mon Sep 17 00:00:00 2001 From: Joe Perches Date: Wed, 30 Jul 2008 12:29:20 -0700 Subject: drivers/base/driver.c: remove unused to_dev() macro Signed-off-by: Joe Perches Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/driver.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'drivers') diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 2ef5acf..1e2bda7 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -16,9 +16,6 @@ #include #include "base.h" -#define to_dev(node) container_of(node, struct device, driver_list) - - static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); -- cgit v1.1 From bf9ca69fc8d19d4034391d3df4c35dccdef9d28c Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Wed, 30 Jul 2008 12:29:21 -0700 Subject: dev_printk(): constify the `dev' argument Add const markings to dev_name and dev_driver_string to make it clear that dev_printk doesn't modify dev. This is a prerequisite to adding more const markings to other functions make it clearer, which functions can modify dev and which can't. Signed-off-by: Jean Delvare Cc: Kay Sievers Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 068aa1c..44bad73 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -53,7 +53,7 @@ static inline int device_is_not_partition(struct device *dev) * it is attached to. If it is not attached to a bus either, an empty * string will be returned. */ -const char *dev_driver_string(struct device *dev) +const char *dev_driver_string(const struct device *dev) { return dev->driver ? dev->driver->name : (dev->bus ? dev->bus->name : -- cgit v1.1 From 7c2250352e11bf956c4cfa20b01ae6ba72882788 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Wed, 6 Aug 2008 18:52:44 -0700 Subject: driver model: anti-oopsing medicine Anti-oops medicine for the class iterators ... the oops was observed when a class was implicitly referenced before it was initialized. [Modified by Greg to spit a warning back so someone knows to fix their code] Signed-off-by: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/base/class.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/base/class.c b/drivers/base/class.c index 5667c2f..cc5e28c 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -295,6 +295,12 @@ int class_for_each_device(struct class *class, struct device *start, if (!class) return -EINVAL; + if (!class->p) { + WARN(1, "%s called for class '%s' before it was initialized", + __func__, class->name); + return -EINVAL; + } + mutex_lock(&class->p->class_mutex); list_for_each_entry(dev, &class->p->class_devices, node) { if (start) { @@ -344,6 +350,11 @@ struct device *class_find_device(struct class *class, struct device *start, if (!class) return NULL; + if (!class->p) { + WARN(1, "%s called for class '%s' before it was initialized", + __func__, class->name); + return NULL; + } mutex_lock(&class->p->class_mutex); list_for_each_entry(dev, &class->p->class_devices, node) { -- cgit v1.1 From 3b98aeaf3a75f544dc945694f4fcf6e1c4bab89d Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Thu, 7 Aug 2008 13:06:12 -0400 Subject: PM: don't skip device PM init when CONFIG_PM_SLEEP isn't set and CONFIG_PM is set This patch (as1124) fixes a couple of bugs in the PM core. The new dev->power.status field should be initialized regardless of whether CONFIG_PM_SLEEP is enabled, and similarly dpm_sysfs_add() should be called whenever CONFIG_PM is enabled. The patch separates out the call to dpm_sysfs_add() from the call to device_pm_add(). As a result device_pm_add() can no longer return an error, so its return type is changed to void. Signed-off-by: Alan Stern Tested-by: Romit Dasgupta Acked-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 9 ++++++--- drivers/base/power/main.c | 13 +++---------- drivers/base/power/power.h | 9 +++++++-- 3 files changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 44bad73..4004131 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -541,6 +541,7 @@ void device_initialize(struct device *dev) spin_lock_init(&dev->devres_lock); INIT_LIST_HEAD(&dev->devres_head); device_init_wakeup(dev, 0); + device_pm_init(dev); set_dev_node(dev, -1); } @@ -897,9 +898,10 @@ int device_add(struct device *dev) error = bus_add_device(dev); if (error) goto BusError; - error = device_pm_add(dev); + error = dpm_sysfs_add(dev); if (error) - goto PMError; + goto DPMError; + device_pm_add(dev); kobject_uevent(&dev->kobj, KOBJ_ADD); bus_attach_device(dev); if (parent) @@ -920,7 +922,7 @@ int device_add(struct device *dev) Done: put_device(dev); return error; - PMError: + DPMError: bus_remove_device(dev); BusError: if (dev->bus) @@ -1007,6 +1009,7 @@ void device_del(struct device *dev) struct class_interface *class_intf; device_pm_remove(dev); + dpm_sysfs_remove(dev); if (parent) klist_del(&dev->knode_parent); if (MAJOR(dev->devt)) { diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 3250c52..284f564 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -67,10 +67,8 @@ void device_pm_unlock(void) * device_pm_add - add a device to the list of active devices * @dev: Device to be added to the list */ -int device_pm_add(struct device *dev) +void device_pm_add(struct device *dev) { - int error; - pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); @@ -89,13 +87,9 @@ int device_pm_add(struct device *dev) */ WARN_ON(true); } - error = dpm_sysfs_add(dev); - if (!error) { - dev->power.status = DPM_ON; - list_add_tail(&dev->power.entry, &dpm_list); - } + + list_add_tail(&dev->power.entry, &dpm_list); mutex_unlock(&dpm_list_mtx); - return error; } /** @@ -110,7 +104,6 @@ void device_pm_remove(struct device *dev) dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); - dpm_sysfs_remove(dev); list_del_init(&dev->power.entry); mutex_unlock(&dpm_list_mtx); } diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index a3252c0..41f51fa 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -1,3 +1,8 @@ +static inline void device_pm_init(struct device *dev) +{ + dev->power.status = DPM_ON; +} + #ifdef CONFIG_PM_SLEEP /* @@ -11,12 +16,12 @@ static inline struct device *to_device(struct list_head *entry) return container_of(entry, struct device, power.entry); } -extern int device_pm_add(struct device *); +extern void device_pm_add(struct device *); extern void device_pm_remove(struct device *); #else /* CONFIG_PM_SLEEP */ -static inline int device_pm_add(struct device *dev) { return 0; } +static inline void device_pm_add(struct device *dev) {} static inline void device_pm_remove(struct device *dev) {} #endif -- cgit v1.1 From c906a48adc74fc455378137ac5124b13e7030a15 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 30 May 2008 10:45:12 -0700 Subject: driver core: add init_name to struct device This gives us a way to handle both the bus_id and init_name values being used for a while during the transition period. Cc: Kay Sievers Signed-off-by: Greg Kroah-Hartman --- drivers/base/core.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/base/core.c b/drivers/base/core.c index 4004131..d021c98 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -844,13 +844,19 @@ int device_add(struct device *dev) { struct device *parent = NULL; struct class_interface *class_intf; - int error; + int error = -EINVAL; dev = get_device(dev); - if (!dev || !strlen(dev->bus_id)) { - error = -EINVAL; - goto Done; - } + 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); + + if (!strlen(dev->bus_id)) + goto done; pr_debug("device: '%s': %s\n", dev->bus_id, __func__); @@ -919,7 +925,7 @@ int device_add(struct device *dev) class_intf->add_dev(dev, class_intf); mutex_unlock(&dev->class->p->class_mutex); } - Done: +done: put_device(dev); return error; DPMError: @@ -946,7 +952,7 @@ int device_add(struct device *dev) cleanup_device_parent(dev); if (parent) put_device(parent); - goto Done; + goto done; } /** -- cgit v1.1 From f5a6d958b5d0a10e7e7a9dee1862fb31d08c6d26 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sat, 9 Aug 2008 01:05:13 +0200 Subject: PM: Remove WARN_ON from device_pm_add PM: Remove WARN_ON from device_pm_add Fix message in device_pm_add() saying that the device will not be added to dpm_list, although in fact the device is going to be added to the list regardless of the ordering violation. Remove the WARN_ON(true) triggered in that situation, because it is hit by USB very often and spams the users' logs. This patch fixes bug #11263 Signed-off-by: Rafael J. Wysocki Signed-off-by: Greg Kroah-Hartman --- drivers/base/power/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 284f564..273a944 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -74,11 +74,9 @@ void device_pm_add(struct device *dev) kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); if (dev->parent) { - if (dev->parent->power.status >= DPM_SUSPENDING) { - dev_warn(dev, "parent %s is sleeping, will not add\n", + if (dev->parent->power.status >= DPM_SUSPENDING) + dev_warn(dev, "parent %s should not be sleeping\n", dev->parent->bus_id); - WARN_ON(true); - } } else if (transition_started) { /* * We refuse to register parentless devices while a PM -- cgit v1.1 From 331995e78385a0b9860f4c4c1766e842e61c450a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 11 Jul 2008 11:10:36 +0200 Subject: UIO: uio_pdrv: fix memory leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to Magnus Damm for pointing that out. Signed-off-by: Uwe Kleine-König Cc: Magnus Damm Acked-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_pdrv.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c index 5d0d2e8..aa3bff8 100644 --- a/drivers/uio/uio_pdrv.c +++ b/drivers/uio/uio_pdrv.c @@ -88,6 +88,8 @@ static int uio_pdrv_remove(struct platform_device *pdev) uio_unregister_device(pdata->uioinfo); + kfree(pdata); + return 0; } -- cgit v1.1 From 0f90927da11d596802d196cf299e91293abc90c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= Date: Fri, 11 Jul 2008 11:10:37 +0200 Subject: UIO: uio_pdrv: fix license specification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Thanks to Magnus Damm for pointing that out. Signed-off-by: Uwe Kleine-König Cc: Magnus Damm Acked-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/uio_pdrv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/uio/uio_pdrv.c b/drivers/uio/uio_pdrv.c index aa3bff8..0b4ef39 100644 --- a/drivers/uio/uio_pdrv.c +++ b/drivers/uio/uio_pdrv.c @@ -116,5 +116,5 @@ module_exit(uio_pdrv_exit); MODULE_AUTHOR("Uwe Kleine-Koenig"); MODULE_DESCRIPTION("Userspace I/O platform driver"); -MODULE_LICENSE("GPL"); +MODULE_LICENSE("GPL v2"); MODULE_ALIAS("platform:" DRIVER_NAME); -- cgit v1.1 From c767db0ab4bc85f06119f2b42369e31b29991f16 Mon Sep 17 00:00:00 2001 From: Magnus Damm Date: Fri, 11 Jul 2008 18:55:27 +0900 Subject: UIO: generic irq handling for some uio platform devices This is V3 of uio_pdrv_genirq.c, a platform driver for UIO with generic IRQ handling code. This driver is very similar to the regular UIO platform driver, but is only suitable for devices that are connected to the interrupt controller using unique interrupt lines. The uio_pdrv_genirq driver includes generic interrupt handling code which disables the serviced interrupt in the interrupt controller and makes the user space driver responsible for acknowledging the interrupt in the device and reenabling the interrupt in the interrupt controller. Shared interrupts are not supported since the in-kernel interrupt handler will disable the interrupt line in the interrupt controller, and in a shared interrupt configuration this will stop other devices from delivering interrupts. Signed-off-by: Magnus Damm Signed-off-by: Hans J. Koch Signed-off-by: Greg Kroah-Hartman --- drivers/uio/Kconfig | 13 +++ drivers/uio/Makefile | 1 + drivers/uio/uio_pdrv_genirq.c | 188 ++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 202 insertions(+) create mode 100644 drivers/uio/uio_pdrv_genirq.c (limited to 'drivers') diff --git a/drivers/uio/Kconfig b/drivers/uio/Kconfig index 2e9079d..4190be6 100644 --- a/drivers/uio/Kconfig +++ b/drivers/uio/Kconfig @@ -33,6 +33,19 @@ config UIO_PDRV If you don't know what to do here, say N. +config UIO_PDRV_GENIRQ + tristate "Userspace I/O platform driver with generic IRQ handling" + help + Platform driver for Userspace I/O devices, including generic + interrupt handling code. Shared interrupts are not supported. + + This kernel driver requires that the matching userspace driver + handles interrupts in a special way. Userspace is responsible + for acknowledging the hardware device if needed, and re-enabling + interrupts in the interrupt controller using the write() syscall. + + If you don't know what to do here, say N. + config UIO_SMX tristate "SMX cryptengine UIO interface" default n diff --git a/drivers/uio/Makefile b/drivers/uio/Makefile index e00ce0d..8667bbd 100644 --- a/drivers/uio/Makefile +++ b/drivers/uio/Makefile @@ -1,4 +1,5 @@ obj-$(CONFIG_UIO) += uio.o 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 diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c new file mode 100644 index 0000000..1f82c83 --- /dev/null +++ b/drivers/uio/uio_pdrv_genirq.c @@ -0,0 +1,188 @@ +/* + * drivers/uio/uio_pdrv_genirq.c + * + * Userspace I/O platform driver with generic IRQ handling code. + * + * Copyright (C) 2008 Magnus Damm + * + * Based on uio_pdrv.c by Uwe Kleine-Koenig, + * Copyright (C) 2008 by Digi International Inc. + * 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. + */ + +#include +#include +#include +#include +#include +#include + +#define DRIVER_NAME "uio_pdrv_genirq" + +struct uio_pdrv_genirq_platdata { + struct uio_info *uioinfo; + spinlock_t lock; + unsigned long flags; +}; + +static irqreturn_t uio_pdrv_genirq_handler(int irq, struct uio_info *dev_info) +{ + struct uio_pdrv_genirq_platdata *priv = dev_info->priv; + + /* Just disable the interrupt in the interrupt controller, and + * remember the state so we can allow user space to enable it later. + */ + + if (!test_and_set_bit(0, &priv->flags)) + disable_irq_nosync(irq); + + return IRQ_HANDLED; +} + +static int uio_pdrv_genirq_irqcontrol(struct uio_info *dev_info, s32 irq_on) +{ + struct uio_pdrv_genirq_platdata *priv = dev_info->priv; + unsigned long flags; + + /* Allow user space to enable and disable the interrupt + * in the interrupt controller, but keep track of the + * state to prevent per-irq depth damage. + * + * Serialize this operation to support multiple tasks. + */ + + spin_lock_irqsave(&priv->lock, flags); + if (irq_on) { + if (test_and_clear_bit(0, &priv->flags)) + enable_irq(dev_info->irq); + } else { + if (!test_and_set_bit(0, &priv->flags)) + disable_irq(dev_info->irq); + } + spin_unlock_irqrestore(&priv->lock, flags); + + return 0; +} + +static int uio_pdrv_genirq_probe(struct platform_device *pdev) +{ + struct uio_info *uioinfo = pdev->dev.platform_data; + struct uio_pdrv_genirq_platdata *priv; + struct uio_mem *uiomem; + int ret = -EINVAL; + int i; + + if (!uioinfo || !uioinfo->name || !uioinfo->version) { + dev_err(&pdev->dev, "missing platform_data\n"); + goto bad0; + } + + if (uioinfo->handler || uioinfo->irqcontrol || uioinfo->irq_flags) { + dev_err(&pdev->dev, "interrupt configuration error\n"); + goto bad0; + } + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) { + ret = -ENOMEM; + dev_err(&pdev->dev, "unable to kmalloc\n"); + goto bad0; + } + + priv->uioinfo = uioinfo; + spin_lock_init(&priv->lock); + priv->flags = 0; /* interrupt is enabled to begin with */ + + uiomem = &uioinfo->mem[0]; + + for (i = 0; i < pdev->num_resources; ++i) { + struct resource *r = &pdev->resource[i]; + + if (r->flags != IORESOURCE_MEM) + continue; + + if (uiomem >= &uioinfo->mem[MAX_UIO_MAPS]) { + dev_warn(&pdev->dev, "device has more than " + __stringify(MAX_UIO_MAPS) + " I/O memory resources.\n"); + break; + } + + uiomem->memtype = UIO_MEM_PHYS; + uiomem->addr = r->start; + uiomem->size = r->end - r->start + 1; + ++uiomem; + } + + while (uiomem < &uioinfo->mem[MAX_UIO_MAPS]) { + uiomem->size = 0; + ++uiomem; + } + + /* This driver requires no hardware specific kernel code to handle + * interrupts. Instead, the interrupt handler simply disables the + * interrupt in the interrupt controller. User space is responsible + * for performing hardware specific acknowledge and re-enabling of + * the interrupt in the interrupt controller. + * + * Interrupt sharing is not supported. + */ + + uioinfo->irq_flags = IRQF_DISABLED; + uioinfo->handler = uio_pdrv_genirq_handler; + uioinfo->irqcontrol = uio_pdrv_genirq_irqcontrol; + uioinfo->priv = priv; + + ret = uio_register_device(&pdev->dev, priv->uioinfo); + if (ret) { + dev_err(&pdev->dev, "unable to register uio device\n"); + goto bad1; + } + + platform_set_drvdata(pdev, priv); + return 0; + bad1: + kfree(priv); + bad0: + return ret; +} + +static int uio_pdrv_genirq_remove(struct platform_device *pdev) +{ + struct uio_pdrv_genirq_platdata *priv = platform_get_drvdata(pdev); + + uio_unregister_device(priv->uioinfo); + kfree(priv); + return 0; +} + +static struct platform_driver uio_pdrv_genirq = { + .probe = uio_pdrv_genirq_probe, + .remove = uio_pdrv_genirq_remove, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + }, +}; + +static int __init uio_pdrv_genirq_init(void) +{ + return platform_driver_register(&uio_pdrv_genirq); +} + +static void __exit uio_pdrv_genirq_exit(void) +{ + platform_driver_unregister(&uio_pdrv_genirq); +} + +module_init(uio_pdrv_genirq_init); +module_exit(uio_pdrv_genirq_exit); + +MODULE_AUTHOR("Magnus Damm"); +MODULE_DESCRIPTION("Userspace I/O platform driver with generic IRQ handling"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:" DRIVER_NAME); -- cgit v1.1 From 380ec6780a0461bb4a4592484d6fe75aa096edeb Mon Sep 17 00:00:00 2001 From: Enrico Scholz Date: Wed, 20 Aug 2008 00:06:22 +0200 Subject: USB: ISP1760: fixed trivial math in comment Signed-off-by: Enrico Scholz Acked-by: Sebastian Siewior Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/isp1760-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index d22a84f..8017f1c 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c @@ -988,7 +988,7 @@ static void do_atl_int(struct usb_hcd *usb_hcd) /* * write bank1 address twice to ensure the 90ns delay (time * between BANK0 write and the priv_read_copy() call is at - * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 92ns) + * least 3*t_WHWL + 2*t_w11 = 3*25ns + 2*17ns = 109ns) */ isp1760_writel(payload + ISP_BANK(1), usb_hcd->regs + HC_MEMORY_REG); -- cgit v1.1 From f8033827d8e92db6159d34ed45c608522674ecd8 Mon Sep 17 00:00:00 2001 From: Hiroshi Miura Date: Tue, 19 Aug 2008 10:58:25 +0200 Subject: usb-serial: option support HSDPA modem A2502 This patch support NTT DoCoMo A2502 3G/HSDPA modem on option driver. It is produced by AnyDATA Corp. and also sold as KT Freetelecom (Korea) ADU 620UW. It support 3.6Mbps/7.2Mbps hight speed communication. I have tested A2502 with NTT DoCoMo MoperaU ISP service. Signed-off-by: Hiroshi Miura Signed-off-by: Matthias Urlichs 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 e143198..9f9cd36 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c @@ -173,6 +173,7 @@ static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *po #define KYOCERA_PRODUCT_KPC680 0x180a #define ANYDATA_VENDOR_ID 0x16d5 +#define ANYDATA_PRODUCT_ADU_620UW 0x6202 #define ANYDATA_PRODUCT_ADU_E100A 0x6501 #define ANYDATA_PRODUCT_ADU_500A 0x6502 @@ -318,6 +319,7 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(DELL_VENDOR_ID, 0x8138) }, /* Dell Wireless 5520 Voda I Mobile Broadband (3G HSDPA) Minicard */ { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_E100A) }, { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_500A) }, + { USB_DEVICE(ANYDATA_VENDOR_ID, ANYDATA_PRODUCT_ADU_620UW) }, { USB_DEVICE(AXESSTEL_VENDOR_ID, AXESSTEL_PRODUCT_MV110H) }, { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_MSA501HS) }, { USB_DEVICE(ONDA_VENDOR_ID, ONDA_PRODUCT_ET502HS) }, -- cgit v1.1 From 77571f05a483c0259e42ba2f482c82debc9a63af Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Mon, 18 Aug 2008 16:36:52 +0200 Subject: USB: fix bug in usb_unlink_anchored_urbs() Irqs must not accidentally be reenabled. Signed-off-by: Oliver Neukum Acked-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/urb.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/urb.c b/drivers/usb/core/urb.c index c0b1ae2..47111e8 100644 --- a/drivers/usb/core/urb.c +++ b/drivers/usb/core/urb.c @@ -601,15 +601,20 @@ EXPORT_SYMBOL_GPL(usb_kill_anchored_urbs); void usb_unlink_anchored_urbs(struct usb_anchor *anchor) { struct urb *victim; + unsigned long flags; - spin_lock_irq(&anchor->lock); + spin_lock_irqsave(&anchor->lock, flags); while (!list_empty(&anchor->urb_list)) { victim = list_entry(anchor->urb_list.prev, struct urb, anchor_list); + usb_get_urb(victim); + spin_unlock_irqrestore(&anchor->lock, flags); /* this will unanchor the URB */ usb_unlink_urb(victim); + usb_put_urb(victim); + spin_lock_irqsave(&anchor->lock, flags); } - spin_unlock_irq(&anchor->lock); + spin_unlock_irqrestore(&anchor->lock, flags); } EXPORT_SYMBOL_GPL(usb_unlink_anchored_urbs); -- cgit v1.1 From c8fd2c37b99c55c8d24888e0ed9d5f4f73458c9c Mon Sep 17 00:00:00 2001 From: Eric Sandeen Date: Thu, 14 Aug 2008 08:25:40 -0500 Subject: USB: cdc-acm: quirk for Conexant CX93010 USB modem This patch gets my Rosewill RNX-56USB USB modem (with Conexant CX93010 chipset) up and running to the point where I can send AT commands and retrieve caller ID data, which is all I want to do with it. Signed-off-by: Eric Sandeen Acked-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index efc4373..382522e 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1362,6 +1362,9 @@ static struct usb_device_id acm_ids[] = { { USB_DEVICE(0x0803, 0x3095), /* Zoom Telephonics Model 3095F USB MODEM */ .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ }, + { USB_DEVICE(0x0572, 0x1321), /* Conexant USB MODEM CX93010 */ + .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ + }, /* control interfaces with various AT-command sets */ { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, -- cgit v1.1 From bf31338bfd5d04434adf2294255847bb7dad687a Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Mon, 11 Aug 2008 18:28:13 +0200 Subject: USB: Fix pxa27x_udc usb speed handling. The new composite framework revealed a weakness in the pxa27x_udc driver gadget register function. Instead of checking if speed asked for was USB_LOW_SPEED upon usb_gadget_register() to deny service, it checked only for USB_FULL_SPEED, thus denying service to usb high speed capable gadgets (like g_ether). Signed-off-by: Robert Jarzmik Cc: David Brownell Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/pxa27x_udc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index a28513e..7cbc78a 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c @@ -1622,7 +1622,7 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) struct pxa_udc *udc = the_controller; int retval; - if (!driver || driver->speed != USB_SPEED_FULL || !driver->bind + if (!driver || driver->speed < USB_SPEED_FULL || !driver->bind || !driver->disconnect || !driver->setup) return -EINVAL; if (!udc) -- cgit v1.1 From 746cdd0b2d1254b11382789b6630c4d379bdcf13 Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sun, 10 Aug 2008 21:22:34 +0300 Subject: usb: musb: get rid of procfs entry Drivers should not add procfs. The functionality in the old procfs file will be moved to debugfs. Cc: Anand Gadiyar Cc: Bryan Wu Cc: David Brownell Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Makefile | 5 - drivers/usb/musb/musb_core.c | 21 +- drivers/usb/musb/musb_core.h | 19 - drivers/usb/musb/musb_procfs.c | 830 ----------------------------------------- 4 files changed, 11 insertions(+), 864 deletions(-) delete mode 100644 drivers/usb/musb/musb_procfs.c (limited to 'drivers') diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 88eb67d..860369c 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -76,11 +76,6 @@ endif ifneq ($(MUSB_DEBUG),0) EXTRA_CFLAGS += -DDEBUG - - ifeq ($(CONFIG_PROC_FS),y) - musb_hdrc-objs += musb_procfs.o - endif - endif EXTRA_CFLAGS += -DMUSB_DEBUG=$(MUSB_DEBUG) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index d68ec6d..99690ba 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2037,6 +2037,8 @@ bad_config: musb->xceiv.state = OTG_STATE_A_IDLE; status = usb_add_hcd(musb_to_hcd(musb), -1, 0); + if (status) + goto fail; DBG(1, "%s mode, status %d, devctl %02x %c\n", "HOST", status, @@ -2051,6 +2053,8 @@ bad_config: musb->xceiv.state = OTG_STATE_B_IDLE; status = musb_gadget_setup(musb); + if (status) + goto fail; DBG(1, "%s mode, status %d, dev%02x\n", is_otg_enabled(musb) ? "OTG" : "PERIPHERAL", @@ -2059,16 +2063,14 @@ bad_config: } - if (status == 0) - musb_debug_create("driver/musb_hdrc", musb); - else { + return 0; + fail: - if (musb->clock) - clk_put(musb->clock); - device_init_wakeup(dev, 0); - musb_free(musb); - return status; - } + if (musb->clock) + clk_put(musb->clock); + device_init_wakeup(dev, 0); + musb_free(musb); + return status; #ifdef CONFIG_SYSFS status = device_create_file(dev, &dev_attr_mode); @@ -2131,7 +2133,6 @@ static int __devexit musb_remove(struct platform_device *pdev) * - OTG mode: both roles are deactivated (or never-activated) */ musb_shutdown(pdev); - musb_debug_delete("driver/musb_hdrc", musb); #ifdef CONFIG_USB_MUSB_HDRC_HCD if (musb->board_mode == MUSB_HOST) usb_remove_hcd(musb_to_hcd(musb)); diff --git a/drivers/usb/musb/musb_core.h b/drivers/usb/musb/musb_core.h index eade46d..8222725 100644 --- a/drivers/usb/musb/musb_core.h +++ b/drivers/usb/musb/musb_core.h @@ -485,23 +485,4 @@ extern int musb_platform_get_vbus_status(struct musb *musb); extern int __init musb_platform_init(struct musb *musb); extern int musb_platform_exit(struct musb *musb); -/*-------------------------- ProcFS definitions ---------------------*/ - -struct proc_dir_entry; - -#if (MUSB_DEBUG > 0) && defined(MUSB_CONFIG_PROC_FS) -extern struct proc_dir_entry *musb_debug_create(char *name, struct musb *data); -extern void musb_debug_delete(char *name, struct musb *data); - -#else -static inline struct proc_dir_entry * -musb_debug_create(char *name, struct musb *data) -{ - return NULL; -} -static inline void musb_debug_delete(char *name, struct musb *data) -{ -} -#endif - #endif /* __MUSB_CORE_H__ */ diff --git a/drivers/usb/musb/musb_procfs.c b/drivers/usb/musb/musb_procfs.c deleted file mode 100644 index 55e6b78..0000000 --- a/drivers/usb/musb/musb_procfs.c +++ /dev/null @@ -1,830 +0,0 @@ -/* - * MUSB OTG driver debug support - * - * Copyright 2005 Mentor Graphics Corporation - * Copyright (C) 2005-2006 by Texas Instruments - * Copyright (C) 2006-2007 Nokia Corporation - * - * 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., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -#include -#include -#include /* FIXME remove procfs writes */ -#include - -#include "musb_core.h" - -#include "davinci.h" - -#ifdef CONFIG_USB_MUSB_HDRC_HCD - -static int dump_qh(struct musb_qh *qh, char *buf, unsigned max) -{ - int count; - int tmp; - struct usb_host_endpoint *hep = qh->hep; - struct urb *urb; - - count = snprintf(buf, max, " qh %p dev%d ep%d%s max%d\n", - qh, qh->dev->devnum, qh->epnum, - ({ char *s; switch (qh->type) { - case USB_ENDPOINT_XFER_BULK: - s = "-bulk"; break; - case USB_ENDPOINT_XFER_INT: - s = "-int"; break; - case USB_ENDPOINT_XFER_CONTROL: - s = ""; break; - default: - s = "iso"; break; - }; s; }), - qh->maxpacket); - if (count <= 0) - return 0; - buf += count; - max -= count; - - list_for_each_entry(urb, &hep->urb_list, urb_list) { - tmp = snprintf(buf, max, "\t%s urb %p %d/%d\n", - usb_pipein(urb->pipe) ? "in" : "out", - urb, urb->actual_length, - urb->transfer_buffer_length); - if (tmp <= 0) - break; - tmp = min(tmp, (int)max); - count += tmp; - buf += tmp; - max -= tmp; - } - return count; -} - -static int -dump_queue(struct list_head *q, char *buf, unsigned max) -{ - int count = 0; - struct musb_qh *qh; - - list_for_each_entry(qh, q, ring) { - int tmp; - - tmp = dump_qh(qh, buf, max); - if (tmp <= 0) - break; - tmp = min(tmp, (int)max); - count += tmp; - buf += tmp; - max -= tmp; - } - return count; -} - -#endif /* HCD */ - -#ifdef CONFIG_USB_GADGET_MUSB_HDRC -static int dump_ep(struct musb_ep *ep, char *buffer, unsigned max) -{ - char *buf = buffer; - int code = 0; - void __iomem *regs = ep->hw_ep->regs; - char *mode = "1buf"; - - if (ep->is_in) { - if (ep->hw_ep->tx_double_buffered) - mode = "2buf"; - } else { - if (ep->hw_ep->rx_double_buffered) - mode = "2buf"; - } - - do { - struct usb_request *req; - - code = snprintf(buf, max, - "\n%s (hw%d): %s%s, csr %04x maxp %04x\n", - ep->name, ep->current_epnum, - mode, ep->dma ? " dma" : "", - musb_readw(regs, - (ep->is_in || !ep->current_epnum) - ? MUSB_TXCSR - : MUSB_RXCSR), - musb_readw(regs, ep->is_in - ? MUSB_TXMAXP - : MUSB_RXMAXP) - ); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - - if (is_cppi_enabled() && ep->current_epnum) { - unsigned cppi = ep->current_epnum - 1; - void __iomem *base = ep->musb->ctrl_base; - unsigned off1 = cppi << 2; - void __iomem *ram = base; - char tmp[16]; - - if (ep->is_in) { - ram += DAVINCI_TXCPPI_STATERAM_OFFSET(cppi); - tmp[0] = 0; - } else { - ram += DAVINCI_RXCPPI_STATERAM_OFFSET(cppi); - snprintf(tmp, sizeof tmp, "%d left, ", - musb_readl(base, - DAVINCI_RXCPPI_BUFCNT0_REG + off1)); - } - - code = snprintf(buf, max, "%cX DMA%d: %s" - "%08x %08x, %08x %08x; " - "%08x %08x %08x .. %08x\n", - ep->is_in ? 'T' : 'R', - ep->current_epnum - 1, tmp, - musb_readl(ram, 0 * 4), - musb_readl(ram, 1 * 4), - musb_readl(ram, 2 * 4), - musb_readl(ram, 3 * 4), - musb_readl(ram, 4 * 4), - musb_readl(ram, 5 * 4), - musb_readl(ram, 6 * 4), - musb_readl(ram, 7 * 4)); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - - if (list_empty(&ep->req_list)) { - code = snprintf(buf, max, "\t(queue empty)\n"); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - break; - } - list_for_each_entry(req, &ep->req_list, list) { - code = snprintf(buf, max, "\treq %p, %s%s%d/%d\n", - req, - req->zero ? "zero, " : "", - req->short_not_ok ? "!short, " : "", - req->actual, req->length); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - } while (0); - return buf - buffer; -} -#endif - -static int -dump_end_info(struct musb *musb, u8 epnum, char *aBuffer, unsigned max) -{ - int code = 0; - char *buf = aBuffer; - struct musb_hw_ep *hw_ep = &musb->endpoints[epnum]; - - do { - musb_ep_select(musb->mregs, epnum); -#ifdef CONFIG_USB_MUSB_HDRC_HCD - if (is_host_active(musb)) { - int dump_rx, dump_tx; - void __iomem *regs = hw_ep->regs; - - /* TEMPORARY (!) until we have a real periodic - * schedule tree ... - */ - if (!epnum) { - /* control is shared, uses RX queue - * but (mostly) shadowed tx registers - */ - dump_tx = !list_empty(&musb->control); - dump_rx = 0; - } else if (hw_ep == musb->bulk_ep) { - dump_tx = !list_empty(&musb->out_bulk); - dump_rx = !list_empty(&musb->in_bulk); - } else if (musb->periodic[epnum]) { - struct usb_host_endpoint *hep; - - hep = musb->periodic[epnum]->hep; - dump_rx = hep->desc.bEndpointAddress - & USB_ENDPOINT_DIR_MASK; - dump_tx = !dump_rx; - } else - break; - /* END TEMPORARY */ - - - if (dump_rx) { - code = snprintf(buf, max, - "\nRX%d: %s rxcsr %04x interval %02x " - "max %04x type %02x; " - "dev %d hub %d port %d" - "\n", - epnum, - hw_ep->rx_double_buffered - ? "2buf" : "1buf", - musb_readw(regs, MUSB_RXCSR), - musb_readb(regs, MUSB_RXINTERVAL), - musb_readw(regs, MUSB_RXMAXP), - musb_readb(regs, MUSB_RXTYPE), - /* FIXME: assumes multipoint */ - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_RXFUNCADDR)), - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_RXHUBADDR)), - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_RXHUBPORT)) - ); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - - if (is_cppi_enabled() - && epnum - && hw_ep->rx_channel) { - unsigned cppi = epnum - 1; - unsigned off1 = cppi << 2; - void __iomem *base; - void __iomem *ram; - char tmp[16]; - - base = musb->ctrl_base; - ram = DAVINCI_RXCPPI_STATERAM_OFFSET( - cppi) + base; - snprintf(tmp, sizeof tmp, "%d left, ", - musb_readl(base, - DAVINCI_RXCPPI_BUFCNT0_REG - + off1)); - - code = snprintf(buf, max, - " rx dma%d: %s" - "%08x %08x, %08x %08x; " - "%08x %08x %08x .. %08x\n", - cppi, tmp, - musb_readl(ram, 0 * 4), - musb_readl(ram, 1 * 4), - musb_readl(ram, 2 * 4), - musb_readl(ram, 3 * 4), - musb_readl(ram, 4 * 4), - musb_readl(ram, 5 * 4), - musb_readl(ram, 6 * 4), - musb_readl(ram, 7 * 4)); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - - if (hw_ep == musb->bulk_ep - && !list_empty( - &musb->in_bulk)) { - code = dump_queue(&musb->in_bulk, - buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } else if (musb->periodic[epnum]) { - code = dump_qh(musb->periodic[epnum], - buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - } - - if (dump_tx) { - code = snprintf(buf, max, - "\nTX%d: %s txcsr %04x interval %02x " - "max %04x type %02x; " - "dev %d hub %d port %d" - "\n", - epnum, - hw_ep->tx_double_buffered - ? "2buf" : "1buf", - musb_readw(regs, MUSB_TXCSR), - musb_readb(regs, MUSB_TXINTERVAL), - musb_readw(regs, MUSB_TXMAXP), - musb_readb(regs, MUSB_TXTYPE), - /* FIXME: assumes multipoint */ - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_TXFUNCADDR)), - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_TXHUBADDR)), - musb_readb(musb->mregs, - MUSB_BUSCTL_OFFSET(epnum, - MUSB_TXHUBPORT)) - ); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - - if (is_cppi_enabled() - && epnum - && hw_ep->tx_channel) { - unsigned cppi = epnum - 1; - void __iomem *base; - void __iomem *ram; - - base = musb->ctrl_base; - ram = DAVINCI_RXCPPI_STATERAM_OFFSET( - cppi) + base; - code = snprintf(buf, max, - " tx dma%d: " - "%08x %08x, %08x %08x; " - "%08x %08x %08x .. %08x\n", - cppi, - musb_readl(ram, 0 * 4), - musb_readl(ram, 1 * 4), - musb_readl(ram, 2 * 4), - musb_readl(ram, 3 * 4), - musb_readl(ram, 4 * 4), - musb_readl(ram, 5 * 4), - musb_readl(ram, 6 * 4), - musb_readl(ram, 7 * 4)); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - - if (hw_ep == musb->control_ep - && !list_empty( - &musb->control)) { - code = dump_queue(&musb->control, - buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } else if (hw_ep == musb->bulk_ep - && !list_empty( - &musb->out_bulk)) { - code = dump_queue(&musb->out_bulk, - buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } else if (musb->periodic[epnum]) { - code = dump_qh(musb->periodic[epnum], - buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - } - } -#endif -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - if (is_peripheral_active(musb)) { - code = 0; - - if (hw_ep->ep_in.desc || !epnum) { - code = dump_ep(&hw_ep->ep_in, buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - if (hw_ep->ep_out.desc) { - code = dump_ep(&hw_ep->ep_out, buf, max); - if (code <= 0) - break; - code = min(code, (int) max); - buf += code; - max -= code; - } - } -#endif - } while (0); - - return buf - aBuffer; -} - -/* Dump the current status and compile options. - * @param musb the device driver instance - * @param buffer where to dump the status; it must be big enough to hold the - * result otherwise "BAD THINGS HAPPENS(TM)". - */ -static int dump_header_stats(struct musb *musb, char *buffer) -{ - int code, count = 0; - const void __iomem *mbase = musb->mregs; - - *buffer = 0; - count = sprintf(buffer, "Status: %sHDRC, Mode=%s " - "(Power=%02x, DevCtl=%02x)\n", - (musb->is_multipoint ? "M" : ""), MUSB_MODE(musb), - musb_readb(mbase, MUSB_POWER), - musb_readb(mbase, MUSB_DEVCTL)); - if (count <= 0) - return 0; - buffer += count; - - code = sprintf(buffer, "OTG state: %s; %sactive\n", - otg_state_string(musb), - musb->is_active ? "" : "in"); - if (code <= 0) - goto done; - buffer += code; - count += code; - - code = sprintf(buffer, - "Options: " -#ifdef CONFIG_MUSB_PIO_ONLY - "pio" -#elif defined(CONFIG_USB_TI_CPPI_DMA) - "cppi-dma" -#elif defined(CONFIG_USB_INVENTRA_DMA) - "musb-dma" -#elif defined(CONFIG_USB_TUSB_OMAP_DMA) - "tusb-omap-dma" -#else - "?dma?" -#endif - ", " -#ifdef CONFIG_USB_MUSB_OTG - "otg (peripheral+host)" -#elif defined(CONFIG_USB_GADGET_MUSB_HDRC) - "peripheral" -#elif defined(CONFIG_USB_MUSB_HDRC_HCD) - "host" -#endif - ", debug=%d [eps=%d]\n", - debug, - musb->nr_endpoints); - if (code <= 0) - goto done; - count += code; - buffer += code; - -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - code = sprintf(buffer, "Peripheral address: %02x\n", - musb_readb(musb->ctrl_base, MUSB_FADDR)); - if (code <= 0) - goto done; - buffer += code; - count += code; -#endif - -#ifdef CONFIG_USB_MUSB_HDRC_HCD - code = sprintf(buffer, "Root port status: %08x\n", - musb->port1_status); - if (code <= 0) - goto done; - buffer += code; - count += code; -#endif - -#ifdef CONFIG_ARCH_DAVINCI - code = sprintf(buffer, - "DaVinci: ctrl=%02x stat=%1x phy=%03x\n" - "\trndis=%05x auto=%04x intsrc=%08x intmsk=%08x" - "\n", - musb_readl(musb->ctrl_base, DAVINCI_USB_CTRL_REG), - musb_readl(musb->ctrl_base, DAVINCI_USB_STAT_REG), - __raw_readl((void __force __iomem *) - IO_ADDRESS(USBPHY_CTL_PADDR)), - musb_readl(musb->ctrl_base, DAVINCI_RNDIS_REG), - musb_readl(musb->ctrl_base, DAVINCI_AUTOREQ_REG), - musb_readl(musb->ctrl_base, - DAVINCI_USB_INT_SOURCE_REG), - musb_readl(musb->ctrl_base, - DAVINCI_USB_INT_MASK_REG)); - if (code <= 0) - goto done; - count += code; - buffer += code; -#endif /* DAVINCI */ - -#ifdef CONFIG_USB_TUSB6010 - code = sprintf(buffer, - "TUSB6010: devconf %08x, phy enable %08x drive %08x" - "\n\totg %03x timer %08x" - "\n\tprcm conf %08x mgmt %08x; int src %08x mask %08x" - "\n", - musb_readl(musb->ctrl_base, TUSB_DEV_CONF), - musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL_ENABLE), - musb_readl(musb->ctrl_base, TUSB_PHY_OTG_CTRL), - musb_readl(musb->ctrl_base, TUSB_DEV_OTG_STAT), - musb_readl(musb->ctrl_base, TUSB_DEV_OTG_TIMER), - musb_readl(musb->ctrl_base, TUSB_PRCM_CONF), - musb_readl(musb->ctrl_base, TUSB_PRCM_MNGMT), - musb_readl(musb->ctrl_base, TUSB_INT_SRC), - musb_readl(musb->ctrl_base, TUSB_INT_MASK)); - if (code <= 0) - goto done; - count += code; - buffer += code; -#endif /* DAVINCI */ - - if (is_cppi_enabled() && musb->dma_controller) { - code = sprintf(buffer, - "CPPI: txcr=%d txsrc=%01x txena=%01x; " - "rxcr=%d rxsrc=%01x rxena=%01x " - "\n", - musb_readl(musb->ctrl_base, - DAVINCI_TXCPPI_CTRL_REG), - musb_readl(musb->ctrl_base, - DAVINCI_TXCPPI_RAW_REG), - musb_readl(musb->ctrl_base, - DAVINCI_TXCPPI_INTENAB_REG), - musb_readl(musb->ctrl_base, - DAVINCI_RXCPPI_CTRL_REG), - musb_readl(musb->ctrl_base, - DAVINCI_RXCPPI_RAW_REG), - musb_readl(musb->ctrl_base, - DAVINCI_RXCPPI_INTENAB_REG)); - if (code <= 0) - goto done; - count += code; - buffer += code; - } - -#ifdef CONFIG_USB_GADGET_MUSB_HDRC - if (is_peripheral_enabled(musb)) { - code = sprintf(buffer, "Gadget driver: %s\n", - musb->gadget_driver - ? musb->gadget_driver->driver.name - : "(none)"); - if (code <= 0) - goto done; - count += code; - buffer += code; - } -#endif - -done: - return count; -} - -/* Write to ProcFS - * - * C soft-connect - * c soft-disconnect - * I enable HS - * i disable HS - * s stop session - * F force session (OTG-unfriendly) - * E rElinquish bus (OTG) - * H request host mode - * h cancel host request - * T start sending TEST_PACKET - * D set/query the debug level - */ -static int musb_proc_write(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - char cmd; - u8 reg; - struct musb *musb = (struct musb *)data; - void __iomem *mbase = musb->mregs; - - /* MOD_INC_USE_COUNT; */ - - if (unlikely(copy_from_user(&cmd, buffer, 1))) - return -EFAULT; - - switch (cmd) { - case 'C': - if (mbase) { - reg = musb_readb(mbase, MUSB_POWER) - | MUSB_POWER_SOFTCONN; - musb_writeb(mbase, MUSB_POWER, reg); - } - break; - - case 'c': - if (mbase) { - reg = musb_readb(mbase, MUSB_POWER) - & ~MUSB_POWER_SOFTCONN; - musb_writeb(mbase, MUSB_POWER, reg); - } - break; - - case 'I': - if (mbase) { - reg = musb_readb(mbase, MUSB_POWER) - | MUSB_POWER_HSENAB; - musb_writeb(mbase, MUSB_POWER, reg); - } - break; - - case 'i': - if (mbase) { - reg = musb_readb(mbase, MUSB_POWER) - & ~MUSB_POWER_HSENAB; - musb_writeb(mbase, MUSB_POWER, reg); - } - break; - - case 'F': - reg = musb_readb(mbase, MUSB_DEVCTL); - reg |= MUSB_DEVCTL_SESSION; - musb_writeb(mbase, MUSB_DEVCTL, reg); - break; - - case 'H': - if (mbase) { - reg = musb_readb(mbase, MUSB_DEVCTL); - reg |= MUSB_DEVCTL_HR; - musb_writeb(mbase, MUSB_DEVCTL, reg); - /* MUSB_HST_MODE( ((struct musb*)data) ); */ - /* WARNING("Host Mode\n"); */ - } - break; - - case 'h': - if (mbase) { - reg = musb_readb(mbase, MUSB_DEVCTL); - reg &= ~MUSB_DEVCTL_HR; - musb_writeb(mbase, MUSB_DEVCTL, reg); - } - break; - - case 'T': - if (mbase) { - musb_load_testpacket(musb); - musb_writeb(mbase, MUSB_TESTMODE, - MUSB_TEST_PACKET); - } - break; - -#if (MUSB_DEBUG > 0) - /* set/read debug level */ - case 'D':{ - if (count > 1) { - char digits[8], *p = digits; - int i = 0, level = 0, sign = 1; - int len = min(count - 1, (unsigned long)8); - - if (copy_from_user(&digits, &buffer[1], len)) - return -EFAULT; - - /* optional sign */ - if (*p == '-') { - len -= 1; - sign = -sign; - p++; - } - - /* read it */ - while (i++ < len && *p > '0' && *p < '9') { - level = level * 10 + (*p - '0'); - p++; - } - - level *= sign; - DBG(1, "debug level %d\n", level); - debug = level; - } - } - break; - - - case '?': - INFO("?: you are seeing it\n"); - INFO("C/c: soft connect enable/disable\n"); - INFO("I/i: hispeed enable/disable\n"); - INFO("F: force session start\n"); - INFO("H: host mode\n"); - INFO("T: start sending TEST_PACKET\n"); - INFO("D: set/read dbug level\n"); - break; -#endif - - default: - ERR("Command %c not implemented\n", cmd); - break; - } - - musb_platform_try_idle(musb, 0); - - return count; -} - -static int musb_proc_read(char *page, char **start, - off_t off, int count, int *eof, void *data) -{ - char *buffer = page; - int code = 0; - unsigned long flags; - struct musb *musb = data; - unsigned epnum; - - count -= off; - count -= 1; /* for NUL at end */ - if (count <= 0) - return -EINVAL; - - spin_lock_irqsave(&musb->lock, flags); - - code = dump_header_stats(musb, buffer); - if (code > 0) { - buffer += code; - count -= code; - } - - /* generate the report for the end points */ - /* REVISIT ... not unless something's connected! */ - for (epnum = 0; count >= 0 && epnum < musb->nr_endpoints; - epnum++) { - code = dump_end_info(musb, epnum, buffer, count); - if (code > 0) { - buffer += code; - count -= code; - } - } - - musb_platform_try_idle(musb, 0); - - spin_unlock_irqrestore(&musb->lock, flags); - *eof = 1; - - return buffer - page; -} - -void __devexit musb_debug_delete(char *name, struct musb *musb) -{ - if (musb->proc_entry) - remove_proc_entry(name, NULL); -} - -struct proc_dir_entry *__init -musb_debug_create(char *name, struct musb *data) -{ - struct proc_dir_entry *pde; - - /* FIXME convert everything to seq_file; then later, debugfs */ - - if (!name) - return NULL; - - pde = create_proc_entry(name, S_IFREG | S_IRUGO | S_IWUSR, NULL); - data->proc_entry = pde; - if (pde) { - pde->data = data; - /* pde->owner = THIS_MODULE; */ - - pde->read_proc = musb_proc_read; - pde->write_proc = musb_proc_write; - - pde->size = 0; - - pr_debug("Registered /proc/%s\n", name); - } else { - pr_debug("Cannot create a valid proc file entry"); - } - - return pde; -} -- cgit v1.1 From e8164f64caff68d4e878e1719d88d145faa75f1d Mon Sep 17 00:00:00 2001 From: Felipe Balbi Date: Sun, 10 Aug 2008 21:22:35 +0300 Subject: usb: musb: get rid of MUSB_LOGLEVEL and use parameter We can change debugging level on the fly via /sys/module/musb_hdrc/parameters/debug. We can also get rid of the LOGLEVEL facility in Kconfig and rely only in module parameter. Cc: Anand Gadiyar Cc: Bryan Wu Cc: David Brownell Signed-off-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/Kconfig | 13 ++++++------- drivers/usb/musb/Makefile | 16 ++-------------- drivers/usb/musb/musb_core.c | 17 ++++------------- drivers/usb/musb/musb_debug.h | 4 ---- 4 files changed, 12 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index faca433..a001748 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -165,12 +165,11 @@ config USB_TUSB_OMAP_DMA help Enable DMA transfers on TUSB 6010 when OMAP DMA is available. -config USB_MUSB_LOGLEVEL +config USB_MUSB_DEBUG depends on USB_MUSB_HDRC - int 'Logging Level (0 - none / 3 - annoying / ... )' - default 0 + bool "Enable debugging messages" + default n help - Set the logging level. 0 disables the debugging altogether, - although when USB_DEBUG is set the value is at least 1. - Starting at level 3, per-transfer (urb, usb_request, packet, - or dma transfer) tracing may kick in. + This enables musb debugging. To set the logging level use the debug + module parameter. Starting at level 3, per-transfer (urb, usb_request, + packet, or dma transfer) tracing may kick in. diff --git a/drivers/usb/musb/Makefile b/drivers/usb/musb/Makefile index 860369c..b6af0d6 100644 --- a/drivers/usb/musb/Makefile +++ b/drivers/usb/musb/Makefile @@ -64,18 +64,6 @@ endif # Debugging -MUSB_DEBUG:=$(CONFIG_USB_MUSB_LOGLEVEL) - -ifeq ("$(strip $(MUSB_DEBUG))","") - ifdef CONFIG_USB_DEBUG - MUSB_DEBUG:=1 - else - MUSB_DEBUG:=0 - endif +ifeq ($(CONFIG_USB_MUSB_DEBUG),y) + EXTRA_CFLAGS += -DDEBUG endif - -ifneq ($(MUSB_DEBUG),0) - EXTRA_CFLAGS += -DDEBUG -endif - -EXTRA_CFLAGS += -DMUSB_DEBUG=$(MUSB_DEBUG) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 99690ba..c5b8f02 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -114,23 +114,14 @@ -#if MUSB_DEBUG > 0 -unsigned debug = MUSB_DEBUG; -module_param(debug, uint, 0); -MODULE_PARM_DESC(debug, "initial debug message level"); - -#define MUSB_VERSION_SUFFIX "/dbg" -#endif +unsigned debug; +module_param(debug, uint, S_IRUGO | S_IWUSR); +MODULE_PARM_DESC(debug, "Debug message level. Default = 0"); #define DRIVER_AUTHOR "Mentor Graphics, Texas Instruments, Nokia" #define DRIVER_DESC "Inventra Dual-Role USB Controller Driver" -#define MUSB_VERSION_BASE "6.0" - -#ifndef MUSB_VERSION_SUFFIX -#define MUSB_VERSION_SUFFIX "" -#endif -#define MUSB_VERSION MUSB_VERSION_BASE MUSB_VERSION_SUFFIX +#define MUSB_VERSION "6.0" #define DRIVER_INFO DRIVER_DESC ", v" MUSB_VERSION diff --git a/drivers/usb/musb/musb_debug.h b/drivers/usb/musb/musb_debug.h index 3bdb311..4d27944 100644 --- a/drivers/usb/musb/musb_debug.h +++ b/drivers/usb/musb/musb_debug.h @@ -48,11 +48,7 @@ __func__, __LINE__ , ## args); \ } } while (0) -#if MUSB_DEBUG > 0 extern unsigned debug; -#else -#define debug 0 -#endif static inline int _dbg_level(unsigned l) { -- cgit v1.1 From fb85d991616046f1b640ed9c4eab9b44908dab74 Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Thu, 21 Aug 2008 20:21:00 +0530 Subject: MUSB: Fix index register corruption seen with g_ether and Windows host If Indexed Mode register accesses are enabled, the ep0_rxstate() function calls musb_g_ep0_giveback() before writing to the CSR register. When control returns to this ep0_rxstate, the index register contents are over-written. This causes the CSR register write to fail. Fixed by writing the correct value into the index register before writing to the CSR. This was observed only in ep0_rxstate() with g_ether loaded and the device connected to a MS Windows host PC. Anticipatively fixed ep0_txstate() as well. Signed-off-by: Anand Gadiyar Acked-by: Felipe Balbi Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_gadget_ep0.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c index 48d7d3c..a57652f 100644 --- a/drivers/usb/musb/musb_gadget_ep0.c +++ b/drivers/usb/musb/musb_gadget_ep0.c @@ -476,6 +476,7 @@ static void ep0_rxstate(struct musb *musb) return; musb->ackpend = 0; } + musb_ep_select(musb->mregs, 0); musb_writew(regs, MUSB_CSR0, tmp); } @@ -528,6 +529,7 @@ static void ep0_txstate(struct musb *musb) } /* send it out, triggering a "txpktrdy cleared" irq */ + musb_ep_select(musb->mregs, 0); musb_writew(regs, MUSB_CSR0, csr); } -- cgit v1.1 From 74573ee7096a4ffc2f098108d21c85801b9c7434 Mon Sep 17 00:00:00 2001 From: Alexey Dobriyan Date: Wed, 20 Aug 2008 16:56:04 -0700 Subject: USB: cdc-acm: don't unlock acm->mutex on error path On Wed, Jul 23, 2008 at 03:52:36PM +0300, Andrei Popa wrote: > I installed gnokii-0.6.22-r2 and gave the command "gnokii --identify" > and the kernel oopsed: > > BUG: unable to handle kernel NULL pointer dereference at 00000458 > IP: [] mutex_unlock+0x0/0xb > [] acm_tty_open+0x4c/0x214 Signed-off-by: Alexey Dobriyan Tested-by: Andrei Popa Cc: stable [2.6.25.x, 2.6.26.x] Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 382522e..c257453 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -589,8 +589,8 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) tasklet_schedule(&acm->urb_task); done: -err_out: mutex_unlock(&acm->mutex); +err_out: mutex_unlock(&open_mutex); return rv; -- cgit v1.1 From 65605ae8e587d714f73e674369bc4cd5a1e53a9b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 12 Aug 2008 14:33:27 -0400 Subject: USB: Add udev argument to interface suspend/resume functions This patch (as1127) makes a minor change to the prototypes of the usb_suspend_interface() and usb_resume_interface() routines. Now the usb_device structure is passed as an argument, instead of being computed on-the-fly from the usb_interface argument. It makes the code look simpler, even if it really isn't much different from before. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 2be37fe..ed1cc85 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -926,14 +926,14 @@ static int usb_resume_device(struct usb_device *udev) } /* Caller has locked intf's usb_device's pm mutex */ -static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) +static int usb_suspend_interface(struct usb_device *udev, + struct usb_interface *intf, pm_message_t msg) { struct usb_driver *driver; int status = 0; /* with no hardware, USB interfaces only use FREEZE and ON states */ - if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED || - !is_active(intf)) + if (udev->state == USB_STATE_NOTATTACHED || !is_active(intf)) goto done; if (intf->condition == USB_INTERFACE_UNBOUND) /* This can't happen */ @@ -944,7 +944,7 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) status = driver->suspend(intf, msg); if (status == 0) mark_quiesced(intf); - else if (!interface_to_usbdev(intf)->auto_pm) + else if (!udev->auto_pm) dev_err(&intf->dev, "%s error %d\n", "suspend", status); } else { @@ -961,13 +961,13 @@ static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg) } /* Caller has locked intf's usb_device's pm_mutex */ -static int usb_resume_interface(struct usb_interface *intf, int reset_resume) +static int usb_resume_interface(struct usb_device *udev, + struct usb_interface *intf, int reset_resume) { struct usb_driver *driver; int status = 0; - if (interface_to_usbdev(intf)->state == USB_STATE_NOTATTACHED || - is_active(intf)) + if (udev->state == USB_STATE_NOTATTACHED || is_active(intf)) goto done; /* Don't let autoresume interfere with unbinding */ @@ -1151,7 +1151,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) if (udev->actconfig) { for (; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; - status = usb_suspend_interface(intf, msg); + status = usb_suspend_interface(udev, intf, msg); if (status != 0) break; } @@ -1163,7 +1163,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg) if (status != 0) { while (--i >= 0) { intf = udev->actconfig->interface[i]; - usb_resume_interface(intf, 0); + usb_resume_interface(udev, intf, 0); } /* Try another autosuspend when the interfaces aren't busy */ @@ -1276,7 +1276,7 @@ static int usb_resume_both(struct usb_device *udev) if (status == 0 && udev->actconfig) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { intf = udev->actconfig->interface[i]; - usb_resume_interface(intf, udev->reset_resume); + usb_resume_interface(udev, intf, udev->reset_resume); } } -- cgit v1.1 From 55151d7daba185f94e9dc561a5a2ba36b5f647dd Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 12 Aug 2008 14:33:59 -0400 Subject: USB: Defer Set-Interface for suspended devices This patch (as1128) fixes one of the problems related to the new PM infrastructure. We are not allowed to register new child devices during the middle of a system sleep transition, but unbinding a USB driver causes the core to automatically install altsetting 0 and thereby create new endpoint pseudo-devices. The patch fixes this problem (and the related problem that installing altsetting 0 will fail if the device is suspended) by deferring the Set-Interface call until some later time when it is legal and can succeed. Possible later times are: when a new driver is being probed for the interface, and when the interface is being resumed. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index ed1cc85..637b2be 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -230,6 +230,13 @@ static int usb_probe_interface(struct device *dev) */ intf->pm_usage_cnt = !(driver->supports_autosuspend); + /* Carry out a deferred switch to altsetting 0 */ + if (intf->needs_altsetting0) { + usb_set_interface(udev, intf->altsetting[0]. + desc.bInterfaceNumber, 0); + intf->needs_altsetting0 = 0; + } + error = driver->probe(intf, id); if (error) { mark_quiesced(intf); @@ -266,8 +273,17 @@ static int usb_unbind_interface(struct device *dev) driver->disconnect(intf); - /* reset other interface state */ - usb_set_interface(udev, intf->altsetting[0].desc.bInterfaceNumber, 0); + /* Reset other interface state. + * We cannot do a Set-Interface if the device is suspended or + * if it is prepared for a system sleep (since installing a new + * altsetting means creating new endpoint device entries). + * When either of these happens, defer the Set-Interface. + */ + if (!error && intf->dev.power.status == DPM_ON) + usb_set_interface(udev, intf->altsetting[0]. + desc.bInterfaceNumber, 0); + else + intf->needs_altsetting0 = 1; usb_set_intfdata(intf, NULL); intf->condition = USB_INTERFACE_UNBOUND; @@ -975,8 +991,17 @@ static int usb_resume_interface(struct usb_device *udev, goto done; /* Can't resume it if it doesn't have a driver. */ - if (intf->condition == USB_INTERFACE_UNBOUND) + if (intf->condition == USB_INTERFACE_UNBOUND) { + + /* Carry out a deferred switch to altsetting 0 */ + if (intf->needs_altsetting0 && + intf->dev.power.status == DPM_ON) { + usb_set_interface(udev, intf->altsetting[0]. + desc.bInterfaceNumber, 0); + intf->needs_altsetting0 = 0; + } goto done; + } /* Don't resume if the interface is marked for rebinding */ if (intf->needs_binding) -- cgit v1.1 From f2189c477c986db47ac7f9cc32d05f6df18bfe9e Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 12 Aug 2008 14:34:10 -0400 Subject: USB: Add new PM callback methods for USB This patch (as1129) adds support for the new PM callbacks to usbcore. The new callbacks merely invoke the same old USB power management routines as the old ones did. A minor improvement is that the callbacks are present only in the "USB-device" device_type structure, rather than in the bus_type structure. This way they will be invoked only for USB devices, not for USB interfaces. The core USB PM routines automatically handle suspending and resuming interfaces along with their devices. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 15 ++-------- drivers/usb/core/usb.c | 73 +++++++++++++++++++++++++++++++++++++++++++---- drivers/usb/core/usb.h | 3 ++ 3 files changed, 72 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 637b2be..2da70b4 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -1630,12 +1630,10 @@ int usb_external_resume_device(struct usb_device *udev) return status; } -static int usb_suspend(struct device *dev, pm_message_t message) +int usb_suspend(struct device *dev, pm_message_t message) { struct usb_device *udev; - if (!is_usb_device(dev)) /* Ignore PM for interfaces */ - return 0; udev = to_usb_device(dev); /* If udev is already suspended, we can skip this suspend and @@ -1654,12 +1652,10 @@ static int usb_suspend(struct device *dev, pm_message_t message) return usb_external_suspend_device(udev, message); } -static int usb_resume(struct device *dev) +int usb_resume(struct device *dev) { struct usb_device *udev; - if (!is_usb_device(dev)) /* Ignore PM for interfaces */ - return 0; udev = to_usb_device(dev); /* If udev->skip_sys_resume is set then udev was already suspended @@ -1671,17 +1667,10 @@ static int usb_resume(struct device *dev) return usb_external_resume_device(udev); } -#else - -#define usb_suspend NULL -#define usb_resume NULL - #endif /* CONFIG_PM */ struct bus_type usb_bus_type = { .name = "usb", .match = usb_device_match, .uevent = usb_uevent, - .suspend = usb_suspend, - .resume = usb_resume, }; diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c index 84fcaa6..be1fa07 100644 --- a/drivers/usb/core/usb.c +++ b/drivers/usb/core/usb.c @@ -219,12 +219,6 @@ static int usb_dev_uevent(struct device *dev, struct kobj_uevent_env *env) } #endif /* CONFIG_HOTPLUG */ -struct device_type usb_device_type = { - .name = "usb_device", - .release = usb_release_dev, - .uevent = usb_dev_uevent, -}; - #ifdef CONFIG_PM static int ksuspend_usb_init(void) @@ -244,13 +238,80 @@ static void ksuspend_usb_cleanup(void) destroy_workqueue(ksuspend_usb_wq); } +/* USB device Power-Management thunks. + * There's no need to distinguish here between quiescing a USB device + * and powering it down; the generic_suspend() routine takes care of + * it by skipping the usb_port_suspend() call for a quiesce. And for + * USB interfaces there's no difference at all. + */ + +static int usb_dev_prepare(struct device *dev) +{ + return 0; /* Implement eventually? */ +} + +static void usb_dev_complete(struct device *dev) +{ + /* Currently used only for rebinding interfaces */ + usb_resume(dev); /* Implement eventually? */ +} + +static int usb_dev_suspend(struct device *dev) +{ + return usb_suspend(dev, PMSG_SUSPEND); +} + +static int usb_dev_resume(struct device *dev) +{ + return usb_resume(dev); +} + +static int usb_dev_freeze(struct device *dev) +{ + return usb_suspend(dev, PMSG_FREEZE); +} + +static int usb_dev_thaw(struct device *dev) +{ + return usb_resume(dev); +} + +static int usb_dev_poweroff(struct device *dev) +{ + return usb_suspend(dev, PMSG_HIBERNATE); +} + +static int usb_dev_restore(struct device *dev) +{ + return usb_resume(dev); +} + +static struct pm_ops usb_device_pm_ops = { + .prepare = usb_dev_prepare, + .complete = usb_dev_complete, + .suspend = usb_dev_suspend, + .resume = usb_dev_resume, + .freeze = usb_dev_freeze, + .thaw = usb_dev_thaw, + .poweroff = usb_dev_poweroff, + .restore = usb_dev_restore, +}; + #else #define ksuspend_usb_init() 0 #define ksuspend_usb_cleanup() do {} while (0) +#define usb_device_pm_ops (*(struct pm_ops *)0) #endif /* CONFIG_PM */ +struct device_type usb_device_type = { + .name = "usb_device", + .release = usb_release_dev, + .uevent = usb_dev_uevent, + .pm = &usb_device_pm_ops, +}; + /* Returns 1 if @usb_bus is WUSB, 0 otherwise */ static unsigned usb_bus_is_wusb(struct usb_bus *bus) diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h index d9a6e16..9a1a45a 100644 --- a/drivers/usb/core/usb.h +++ b/drivers/usb/core/usb.h @@ -41,6 +41,9 @@ extern void usb_host_cleanup(void); #ifdef CONFIG_PM +extern int usb_suspend(struct device *dev, pm_message_t msg); +extern int usb_resume(struct device *dev); + extern void usb_autosuspend_work(struct work_struct *work); extern int usb_port_suspend(struct usb_device *dev); extern int usb_port_resume(struct usb_device *dev); -- cgit v1.1 From 5096aedcd2eb70fbea83f09281f97f9ec973d9de Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Tue, 12 Aug 2008 14:34:14 -0400 Subject: USB: Don't rebind before "complete" callback This patch (as1130) fixes an incompatibility between the new PM infrastructure and USB power management. We are not allowed to call drivers' probe routines during a system sleep transition between the "prepare" and "complete" callbacks, but that's exactly what we do when a driver doesn't have full suspend/resume support. Such drivers are unbound during the "suspend" call and reprobed during the "resume" call. The patch causes the reprobe step to be skipped if the "complete" callback hasn't been issued yet, i.e., if the interface's dev.power.status field is not equal to DPM_ON. Thus during the "resume" callback nothing bad will happen, and during the final "complete" callback the reprobing will occur as desired. This fixes the problem reported in Bugzilla #11263. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/driver.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c index 2da70b4..5a7fa6f 100644 --- a/drivers/usb/core/driver.c +++ b/drivers/usb/core/driver.c @@ -814,7 +814,8 @@ void usb_forced_unbind_intf(struct usb_interface *intf) * The caller must hold @intf's device's lock, but not its pm_mutex * and not @intf->dev.sem. * - * FIXME: The caller must block system sleep transitions. + * Note: Rebinds will be skipped if a system sleep transition is in + * progress and the PM "complete" callback hasn't occurred yet. */ void usb_rebind_intf(struct usb_interface *intf) { @@ -830,10 +831,12 @@ void usb_rebind_intf(struct usb_interface *intf) } /* Try to rebind the interface */ - intf->needs_binding = 0; - rc = device_attach(&intf->dev); - if (rc < 0) - dev_warn(&intf->dev, "rebind failed: %d\n", rc); + if (intf->dev.power.status == DPM_ON) { + intf->needs_binding = 0; + rc = device_attach(&intf->dev); + if (rc < 0) + dev_warn(&intf->dev, "rebind failed: %d\n", rc); + } } #ifdef CONFIG_PM @@ -845,7 +848,6 @@ void usb_rebind_intf(struct usb_interface *intf) * or rebind interfaces that have been unbound, according to @action. * * The caller must hold @udev's device lock. - * FIXME: For rebinds, the caller must block system sleep transitions. */ static void do_unbind_rebind(struct usb_device *udev, int action) { @@ -867,22 +869,8 @@ static void do_unbind_rebind(struct usb_device *udev, int action) } break; case DO_REBIND: - if (intf->needs_binding) { - - /* FIXME: The next line is needed because we are going to probe - * the interface, but as far as the PM core is concerned the - * interface is still suspended. The problem wouldn't exist - * if we could rebind the interface during the interface's own - * resume() call, but at the time the usb_device isn't locked! - * - * The real solution will be to carry this out during the device's - * complete() callback. Until that is implemented, we have to - * use this hack. - */ -// intf->dev.power.sleeping = 0; - + if (intf->needs_binding) usb_rebind_intf(intf); - } break; } } -- cgit v1.1 From b5fb454f69642f9d933b327b185a2ba06dd0945c Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 20 Aug 2008 17:22:05 -0400 Subject: USB: automatically enable RHSC interrupts This patch (as1069c) changes the way OHCI root-hub status-change interrupts are enabled. Currently a special HCD method, hub_irq_enable(), is called when the hub driver is finished using a root hub. This approach turns out to be subject to races, resulting in unnecessary polling. The patch does away with the method entirely. Instead, the driver automatically enables the RHSC interrupt when no more status changes are present. This scheme is safe with controllers using level-triggered semantics for their interrupt flags. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/hcd.c | 9 ------- drivers/usb/core/hcd.h | 4 ---- drivers/usb/core/hub.c | 9 ------- drivers/usb/host/ohci-at91.c | 1 - drivers/usb/host/ohci-au1xxx.c | 1 - drivers/usb/host/ohci-ep93xx.c | 1 - drivers/usb/host/ohci-hub.c | 53 ++++++++++++++++++++++++----------------- drivers/usb/host/ohci-lh7a404.c | 1 - drivers/usb/host/ohci-omap.c | 1 - drivers/usb/host/ohci-pci.c | 1 - drivers/usb/host/ohci-pnx4008.c | 1 - drivers/usb/host/ohci-pnx8550.c | 1 - drivers/usb/host/ohci-ppc-of.c | 1 - drivers/usb/host/ohci-ppc-soc.c | 1 - drivers/usb/host/ohci-ps3.c | 1 - drivers/usb/host/ohci-pxa27x.c | 1 - drivers/usb/host/ohci-s3c2410.c | 1 - drivers/usb/host/ohci-sa1111.c | 1 - drivers/usb/host/ohci-sh.c | 1 - drivers/usb/host/ohci-sm501.c | 1 - drivers/usb/host/ohci-ssb.c | 1 - drivers/usb/host/u132-hcd.c | 11 --------- 22 files changed, 31 insertions(+), 72 deletions(-) (limited to 'drivers') diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index f7bfd72..8abd4e5 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -924,15 +924,6 @@ static int register_root_hub(struct usb_hcd *hcd) return retval; } -void usb_enable_root_hub_irq (struct usb_bus *bus) -{ - struct usb_hcd *hcd; - - hcd = container_of (bus, struct usb_hcd, self); - if (hcd->driver->hub_irq_enable && hcd->state != HC_STATE_HALT) - hcd->driver->hub_irq_enable (hcd); -} - /*-------------------------------------------------------------------------*/ diff --git a/drivers/usb/core/hcd.h b/drivers/usb/core/hcd.h index 5b0b59b..e710ce0 100644 --- a/drivers/usb/core/hcd.h +++ b/drivers/usb/core/hcd.h @@ -212,8 +212,6 @@ struct hc_driver { int (*bus_suspend)(struct usb_hcd *); int (*bus_resume)(struct usb_hcd *); int (*start_port_reset)(struct usb_hcd *, unsigned port_num); - void (*hub_irq_enable)(struct usb_hcd *); - /* Needed only if port-change IRQs are level-triggered */ /* force handover of high-speed port to full-speed companion */ void (*relinquish_port)(struct usb_hcd *, int); @@ -379,8 +377,6 @@ extern struct list_head usb_bus_list; extern struct mutex usb_bus_list_lock; extern wait_queue_head_t usb_kill_urb_queue; -extern void usb_enable_root_hub_irq(struct usb_bus *bus); - extern int usb_find_interface_driver(struct usb_device *dev, struct usb_interface *interface); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 107e1d2..6a5cb01 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -2102,8 +2102,6 @@ int usb_port_resume(struct usb_device *udev) } clear_bit(port1, hub->busy_bits); - if (!hub->hdev->parent && !hub->busy_bits[0]) - usb_enable_root_hub_irq(hub->hdev->bus); status = check_port_resume_type(udev, hub, port1, status, portchange, portstatus); @@ -3081,11 +3079,6 @@ static void hub_events(void) } } - /* If this is a root hub, tell the HCD it's okay to - * re-enable port-change interrupts now. */ - if (!hdev->parent && !hub->busy_bits[0]) - usb_enable_root_hub_irq(hdev->bus); - loop_autopm: /* Allow autosuspend if we're not going to run again */ if (list_empty(&hub->event_list)) @@ -3311,8 +3304,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev) break; } clear_bit(port1, parent_hub->busy_bits); - if (!parent_hdev->parent && !parent_hub->busy_bits[0]) - usb_enable_root_hub_irq(parent_hdev->bus); if (ret < 0) goto re_enumerate; diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c index 6db7a28..4ed228a 100644 --- a/drivers/usb/host/ohci-at91.c +++ b/drivers/usb/host/ohci-at91.c @@ -260,7 +260,6 @@ static const struct hc_driver ohci_at91_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-au1xxx.c b/drivers/usb/host/ohci-au1xxx.c index c094800..2ac4e02 100644 --- a/drivers/usb/host/ohci-au1xxx.c +++ b/drivers/usb/host/ohci-au1xxx.c @@ -163,7 +163,6 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ep93xx.c b/drivers/usb/host/ohci-ep93xx.c index cb0b506..fb3055f 100644 --- a/drivers/usb/host/ohci-ep93xx.c +++ b/drivers/usb/host/ohci-ep93xx.c @@ -134,7 +134,6 @@ static struct hc_driver ohci_ep93xx_hc_driver = { .get_frame_number = ohci_get_frame, .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-hub.c b/drivers/usb/host/ohci-hub.c index 439beb7..7ea9a7b 100644 --- a/drivers/usb/host/ohci-hub.c +++ b/drivers/usb/host/ohci-hub.c @@ -36,18 +36,6 @@ /*-------------------------------------------------------------------------*/ -/* hcd->hub_irq_enable() */ -static void ohci_rhsc_enable (struct usb_hcd *hcd) -{ - struct ohci_hcd *ohci = hcd_to_ohci (hcd); - - spin_lock_irq(&ohci->lock); - if (!ohci->autostop) - del_timer(&hcd->rh_timer); /* Prevent next poll */ - ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); - spin_unlock_irq(&ohci->lock); -} - #define OHCI_SCHED_ENABLES \ (OHCI_CTRL_CLE|OHCI_CTRL_BLE|OHCI_CTRL_PLE|OHCI_CTRL_IE) @@ -374,18 +362,28 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) { int poll_rh = 1; + int rhsc; + rhsc = ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC; switch (ohci->hc_control & OHCI_CTRL_HCFS) { case OHCI_USB_OPER: - /* keep on polling until we know a device is connected - * and RHSC is enabled */ + /* If no status changes are pending, enable status-change + * interrupts. + */ + if (!rhsc && !changed) { + rhsc = OHCI_INTR_RHSC; + ohci_writel(ohci, rhsc, &ohci->regs->intrenable); + } + + /* Keep on polling until we know a device is connected + * and RHSC is enabled, or until we autostop. + */ if (!ohci->autostop) { if (any_connected || !device_may_wakeup(&ohci_to_hcd(ohci) ->self.root_hub->dev)) { - if (ohci_readl(ohci, &ohci->regs->intrenable) & - OHCI_INTR_RHSC) + if (rhsc) poll_rh = 0; } else { ohci->autostop = 1; @@ -398,12 +396,13 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, ohci->autostop = 0; ohci->next_statechange = jiffies + STATECHANGE_DELAY; - } else if (time_after_eq(jiffies, + } else if (rhsc && time_after_eq(jiffies, ohci->next_statechange) && !ohci->ed_rm_list && !(ohci->hc_control & OHCI_SCHED_ENABLES)) { ohci_rh_suspend(ohci, 1); + poll_rh = 0; } } break; @@ -417,6 +416,12 @@ static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, else usb_hcd_resume_root_hub(ohci_to_hcd(ohci)); } else { + if (!rhsc && (ohci->autostop || + ohci_to_hcd(ohci)->self.root_hub-> + do_remote_wakeup)) + ohci_writel(ohci, OHCI_INTR_RHSC, + &ohci->regs->intrenable); + /* everything is idle, no need for polling */ poll_rh = 0; } @@ -438,12 +443,16 @@ static inline int ohci_rh_resume(struct ohci_hcd *ohci) static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed, int any_connected) { - int poll_rh = 1; - - /* keep on polling until RHSC is enabled */ + /* If RHSC is enabled, don't poll */ if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC) - poll_rh = 0; - return poll_rh; + return 0; + + /* If no status changes are pending, enable status-change interrupts */ + if (!changed) { + ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); + return 0; + } + return 1; } #endif /* CONFIG_PM */ diff --git a/drivers/usb/host/ohci-lh7a404.c b/drivers/usb/host/ohci-lh7a404.c index 9e31d44..de42283 100644 --- a/drivers/usb/host/ohci-lh7a404.c +++ b/drivers/usb/host/ohci-lh7a404.c @@ -193,7 +193,6 @@ static const struct hc_driver ohci_lh7a404_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c index 3d532b7..1eb64d0 100644 --- a/drivers/usb/host/ohci-omap.c +++ b/drivers/usb/host/ohci-omap.c @@ -470,7 +470,6 @@ static const struct hc_driver ohci_omap_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 083e8df..a9c2ae3 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c @@ -459,7 +459,6 @@ static const struct hc_driver ohci_pci_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pnx4008.c b/drivers/usb/host/ohci-pnx4008.c index b02cd07..658a2a9 100644 --- a/drivers/usb/host/ohci-pnx4008.c +++ b/drivers/usb/host/ohci-pnx4008.c @@ -277,7 +277,6 @@ static const struct hc_driver ohci_pnx4008_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-pnx8550.c b/drivers/usb/host/ohci-pnx8550.c index 605d59c..28467e2 100644 --- a/drivers/usb/host/ohci-pnx8550.c +++ b/drivers/usb/host/ohci-pnx8550.c @@ -201,7 +201,6 @@ static const struct hc_driver ohci_pnx8550_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c index 91e6e10..7ac5326 100644 --- a/drivers/usb/host/ohci-ppc-of.c +++ b/drivers/usb/host/ohci-ppc-of.c @@ -72,7 +72,6 @@ static const struct hc_driver ohci_ppc_of_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ppc-soc.c b/drivers/usb/host/ohci-ppc-soc.c index 523c301..cd3398b 100644 --- a/drivers/usb/host/ohci-ppc-soc.c +++ b/drivers/usb/host/ohci-ppc-soc.c @@ -172,7 +172,6 @@ static const struct hc_driver ohci_ppc_soc_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ps3.c b/drivers/usb/host/ohci-ps3.c index 55c9564..2089d8a 100644 --- a/drivers/usb/host/ohci-ps3.c +++ b/drivers/usb/host/ohci-ps3.c @@ -68,7 +68,6 @@ static const struct hc_driver ps3_ohci_hc_driver = { .get_frame_number = ohci_get_frame, .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, .start_port_reset = ohci_start_port_reset, #if defined(CONFIG_PM) .bus_suspend = ohci_bus_suspend, diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c index 8c9c484..7f0f35c 100644 --- a/drivers/usb/host/ohci-pxa27x.c +++ b/drivers/usb/host/ohci-pxa27x.c @@ -298,7 +298,6 @@ static const struct hc_driver ohci_pxa27x_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c index 9e3dc40..f46af7a 100644 --- a/drivers/usb/host/ohci-s3c2410.c +++ b/drivers/usb/host/ohci-s3c2410.c @@ -466,7 +466,6 @@ static const struct hc_driver ohci_s3c2410_hc_driver = { */ .hub_status_data = ohci_s3c2410_hub_status_data, .hub_control = ohci_s3c2410_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c index 4626b00..e4bbe8e 100644 --- a/drivers/usb/host/ohci-sa1111.c +++ b/drivers/usb/host/ohci-sa1111.c @@ -231,7 +231,6 @@ static const struct hc_driver ohci_sa1111_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sh.c b/drivers/usb/host/ohci-sh.c index e7ee607..60f03cc 100644 --- a/drivers/usb/host/ohci-sh.c +++ b/drivers/usb/host/ohci-sh.c @@ -68,7 +68,6 @@ static const struct hc_driver ohci_sh_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c index 21b164e..cff2363 100644 --- a/drivers/usb/host/ohci-sm501.c +++ b/drivers/usb/host/ohci-sm501.c @@ -75,7 +75,6 @@ static const struct hc_driver ohci_sm501_hc_driver = { */ .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/ohci-ssb.c b/drivers/usb/host/ohci-ssb.c index 3660c83..23fd6a8 100644 --- a/drivers/usb/host/ohci-ssb.c +++ b/drivers/usb/host/ohci-ssb.c @@ -81,7 +81,6 @@ static const struct hc_driver ssb_ohci_hc_driver = { .hub_status_data = ohci_hub_status_data, .hub_control = ohci_hub_control, - .hub_irq_enable = ohci_rhsc_enable, #ifdef CONFIG_PM .bus_suspend = ohci_bus_suspend, .bus_resume = ohci_bus_resume, diff --git a/drivers/usb/host/u132-hcd.c b/drivers/usb/host/u132-hcd.c index 20ad3c4..228f2b0 100644 --- a/drivers/usb/host/u132-hcd.c +++ b/drivers/usb/host/u132-hcd.c @@ -2934,16 +2934,6 @@ static int u132_start_port_reset(struct usb_hcd *hcd, unsigned port_num) return 0; } -static void u132_hub_irq_enable(struct usb_hcd *hcd) -{ - struct u132 *u132 = hcd_to_u132(hcd); - if (u132->going > 1) { - dev_err(&u132->platform_dev->dev, "device has been removed %d\n" - , u132->going); - } else if (u132->going > 0) - dev_err(&u132->platform_dev->dev, "device is being removed\n"); -} - #ifdef CONFIG_PM static int u132_bus_suspend(struct usb_hcd *hcd) @@ -2995,7 +2985,6 @@ static struct hc_driver u132_hc_driver = { .bus_suspend = u132_bus_suspend, .bus_resume = u132_bus_resume, .start_port_reset = u132_start_port_reset, - .hub_irq_enable = u132_hub_irq_enable, }; /* -- cgit v1.1 From eaea04353e0114a9805fc2cf1ff832cb0ac2570b Mon Sep 17 00:00:00 2001 From: Stefan Lippers-Hollmann Date: Thu, 21 Aug 2008 13:46:11 +0200 Subject: USB: sisusbvga: add USB ID for 0711:0918 Magic Control Technology Corp. sisusbvga: add USB ID for 0711:0918 Magic Control Technology Corp. usb 1-2: new high speed USB device using ehci_hcd and address 4 usb 1-2: configuration #1 chosen from 1 choice usb 1-2: USB2VGA dongle found at address 4 usb 1-2: Allocated 8 output buffers usb 1-2: 8MB 1 ch/1 r SDR SDRAM, bus width 32 usb 1-2: New USB device found, idVendor=0711, idProduct=0918 usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0 Signed-off-by: Stefan Lippers-Hollmann Signed-off-by: Greg Kroah-Hartman --- drivers/usb/misc/sisusbvga/sisusb.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/usb/misc/sisusbvga/sisusb.c b/drivers/usb/misc/sisusbvga/sisusb.c index fbace41..69c34a5 100644 --- a/drivers/usb/misc/sisusbvga/sisusb.c +++ b/drivers/usb/misc/sisusbvga/sisusb.c @@ -3270,6 +3270,7 @@ static struct usb_device_id sisusb_table [] = { { USB_DEVICE(0x0711, 0x0900) }, { USB_DEVICE(0x0711, 0x0901) }, { USB_DEVICE(0x0711, 0x0902) }, + { USB_DEVICE(0x0711, 0x0918) }, { USB_DEVICE(0x182d, 0x021c) }, { USB_DEVICE(0x182d, 0x0269) }, { } -- cgit v1.1 From 0983e56835cbf4796e8f5780c549c32ac1c3afac Mon Sep 17 00:00:00 2001 From: Julien Brunel Date: Thu, 21 Aug 2008 19:46:30 +0200 Subject: [S390] drivers/s390: Use an IS_ERR test rather than a NULL test In case of error, functions dasd_kmalloc_request and idal_buffer_alloc return an ERR pointer, but never return the NULL pointer. So after a call to one of these functions, a NULL test should be replaced by an IS_ERR test. A simplified version of the semantic patch that makes this change is as follows: (http://www.emn.fr/x-info/coccinelle/) // @correct_null_test@ expression x,E; statement S1, S2; @@ x = ( dasd_kmalloc_request(...) | idal_buffer_alloc(...) ) <... when != x = E if ( ( - x@p2 != NULL + ! IS_ERR ( x ) | - x@p2 == NULL + IS_ERR( x ) ) ) S1 else S2 ...> ? x = E; // Signed-off-by: Julien Brunel Signed-off-by: Julia Lawall Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd_eer.c | 3 ++- drivers/s390/char/tape_char.c | 2 +- drivers/s390/char/tape_std.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_eer.c b/drivers/s390/block/dasd_eer.c index 29da441..bf512ac 100644 --- a/drivers/s390/block/dasd_eer.c +++ b/drivers/s390/block/dasd_eer.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -457,7 +458,7 @@ int dasd_eer_enable(struct dasd_device *device) cqr = dasd_kmalloc_request("ECKD", 1 /* SNSS */, SNSS_DATA_SIZE, device); - if (!cqr) + if (IS_ERR(cqr)) return -ENOMEM; cqr->startdev = device; diff --git a/drivers/s390/char/tape_char.c b/drivers/s390/char/tape_char.c index 687720b..be0ce22 100644 --- a/drivers/s390/char/tape_char.c +++ b/drivers/s390/char/tape_char.c @@ -109,7 +109,7 @@ tapechar_check_idalbuffer(struct tape_device *device, size_t block_size) /* The current idal buffer is not correct. Allocate a new one. */ new = idal_buffer_alloc(block_size, 0); - if (new == NULL) + if (IS_ERR(new)) return -ENOMEM; if (device->char_data.idal_buf != NULL) diff --git a/drivers/s390/char/tape_std.c b/drivers/s390/char/tape_std.c index 2a1af4e..cc8fd781 100644 --- a/drivers/s390/char/tape_std.c +++ b/drivers/s390/char/tape_std.c @@ -248,7 +248,7 @@ tape_std_mtsetblk(struct tape_device *device, int count) /* Allocate a new idal buffer. */ new = idal_buffer_alloc(count, 0); - if (new == NULL) + if (IS_ERR(new)) return -ENOMEM; if (device->char_data.idal_buf != NULL) idal_buffer_free(device->char_data.idal_buf); -- cgit v1.1 From 53b41ba7ce4563c33a0449fbcbbd70665477d654 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 21 Aug 2008 19:46:33 +0200 Subject: [S390] qdio: prevent oopsing if qdio_establish fails If qdio_establish fails we call qdio_shutdown to cleanup the qdio subchannel. The tiq_list entry may not be valid at that time, therefore we must ignore queues with an invalid list entry in tiqdio_remove_input_queues. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_thinint.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index 9291a77..ea7f614 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c @@ -113,7 +113,11 @@ void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) struct qdio_q *q; int i; - for_each_input_queue(irq_ptr, q, i) { + for (i = 0; i < irq_ptr->nr_input_qs; i++) { + q = irq_ptr->input_qs[i]; + /* if establish triggered an error */ + if (!q || !q->entry.prev || !q->entry.next) + continue; list_del_rcu(&q->entry); synchronize_rcu(); } -- cgit v1.1 From 58eb27cd7f4f1de2932b3e0e39ea54a27e9fef43 Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 21 Aug 2008 19:46:34 +0200 Subject: [S390] qdio: improve s390 debug feature usage Improve s390 debug feature usage: - log busy bit in dbf - increase size of dbf views - consistent logging of qdio api calls to setup view - print subchannel number so one can associate the interface with the dbf data - only log events to one view Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_debug.h | 6 ++-- drivers/s390/cio/qdio_main.c | 70 +++++++++++++++++++++---------------------- drivers/s390/cio/qdio_setup.c | 6 ++-- 3 files changed, 40 insertions(+), 42 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/qdio_debug.h b/drivers/s390/cio/qdio_debug.h index 8484b83..5a4d85b 100644 --- a/drivers/s390/cio/qdio_debug.h +++ b/drivers/s390/cio/qdio_debug.h @@ -61,18 +61,18 @@ /* s390dbf views */ #define QDIO_DBF_SETUP_LEN 8 -#define QDIO_DBF_SETUP_PAGES 4 +#define QDIO_DBF_SETUP_PAGES 8 #define QDIO_DBF_SETUP_NR_AREAS 1 #define QDIO_DBF_TRACE_LEN 8 #define QDIO_DBF_TRACE_NR_AREAS 2 #ifdef CONFIG_QDIO_DEBUG -#define QDIO_DBF_TRACE_PAGES 16 +#define QDIO_DBF_TRACE_PAGES 32 #define QDIO_DBF_SETUP_LEVEL 6 #define QDIO_DBF_TRACE_LEVEL 4 #else /* !CONFIG_QDIO_DEBUG */ -#define QDIO_DBF_TRACE_PAGES 4 +#define QDIO_DBF_TRACE_PAGES 8 #define QDIO_DBF_SETUP_LEVEL 2 #define QDIO_DBF_TRACE_LEVEL 2 #endif /* CONFIG_QDIO_DEBUG */ diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index d156485..444fc7e 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -330,6 +330,7 @@ static int qdio_siga_output(struct qdio_q *q) int cc; u32 busy_bit; u64 start_time = 0; + char dbf_text[15]; QDIO_DBF_TEXT5(0, trace, "sigaout"); QDIO_DBF_HEX5(0, trace, &q, sizeof(void *)); @@ -338,6 +339,9 @@ static int qdio_siga_output(struct qdio_q *q) again: cc = qdio_do_siga_output(q, &busy_bit); if (queue_type(q) == QDIO_IQDIO_QFMT && cc == 2 && busy_bit) { + sprintf(dbf_text, "bb%4x%2x", q->irq_ptr->schid.sch_no, q->nr); + QDIO_DBF_TEXT3(0, trace, dbf_text); + if (!start_time) start_time = get_usecs(); else if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) @@ -748,16 +752,18 @@ static void qdio_kick_outbound_q(struct qdio_q *q) rc = qdio_siga_output(q); switch (rc) { case 0: - /* went smooth this time, reset timestamp */ - q->u.out.timestamp = 0; - /* TODO: improve error handling for CC=0 case */ #ifdef CONFIG_QDIO_DEBUG - QDIO_DBF_TEXT3(0, trace, "cc2reslv"); - sprintf(dbf_text, "%4x%2x%2x", q->irq_ptr->schid.sch_no, q->nr, - atomic_read(&q->u.out.busy_siga_counter)); - QDIO_DBF_TEXT3(0, trace, dbf_text); + if (q->u.out.timestamp) { + QDIO_DBF_TEXT3(0, trace, "cc2reslv"); + sprintf(dbf_text, "%4x%2x%2x", q->irq_ptr->schid.sch_no, + q->nr, + atomic_read(&q->u.out.busy_siga_counter)); + QDIO_DBF_TEXT3(0, trace, dbf_text); + } #endif /* CONFIG_QDIO_DEBUG */ + /* went smooth this time, reset timestamp */ + q->u.out.timestamp = 0; break; /* cc=2 and busy bit */ case (2 | QDIO_ERROR_SIGA_BUSY): @@ -1066,14 +1072,12 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, if (IS_ERR(irb)) { switch (PTR_ERR(irb)) { case -EIO: - sprintf(dbf_text, "ierr%4x", - cdev->private->schid.sch_no); + sprintf(dbf_text, "ierr%4x", irq_ptr->schid.sch_no); QDIO_DBF_TEXT2(1, setup, dbf_text); qdio_int_error(cdev); return; case -ETIMEDOUT: - sprintf(dbf_text, "qtoh%4x", - cdev->private->schid.sch_no); + sprintf(dbf_text, "qtoh%4x", irq_ptr->schid.sch_no); QDIO_DBF_TEXT2(1, setup, dbf_text); qdio_int_error(cdev); return; @@ -1124,8 +1128,10 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, struct qdio_ssqd_desc *qdio_get_ssqd_desc(struct ccw_device *cdev) { struct qdio_irq *irq_ptr; + char dbf_text[15]; - QDIO_DBF_TEXT0(0, setup, "getssqd"); + sprintf(dbf_text, "qssq%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); irq_ptr = cdev->private->qdio_data; if (!irq_ptr) @@ -1149,14 +1155,13 @@ int qdio_cleanup(struct ccw_device *cdev, int how) char dbf_text[15]; int rc; + sprintf(dbf_text, "qcln%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; - sprintf(dbf_text, "qcln%4x", irq_ptr->schid.sch_no); - QDIO_DBF_TEXT1(0, trace, dbf_text); - QDIO_DBF_TEXT0(0, setup, dbf_text); - rc = qdio_shutdown(cdev, how); if (rc == 0) rc = qdio_free(cdev); @@ -1191,6 +1196,9 @@ int qdio_shutdown(struct ccw_device *cdev, int how) unsigned long flags; char dbf_text[15]; + sprintf(dbf_text, "qshu%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; @@ -1205,10 +1213,6 @@ int qdio_shutdown(struct ccw_device *cdev, int how) return 0; } - sprintf(dbf_text, "qsqs%4x", irq_ptr->schid.sch_no); - QDIO_DBF_TEXT1(0, trace, dbf_text); - QDIO_DBF_TEXT0(0, setup, dbf_text); - tiqdio_remove_input_queues(irq_ptr); qdio_shutdown_queues(cdev); qdio_shutdown_debug_entries(irq_ptr, cdev); @@ -1263,16 +1267,14 @@ int qdio_free(struct ccw_device *cdev) struct qdio_irq *irq_ptr; char dbf_text[15]; + sprintf(dbf_text, "qfre%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; mutex_lock(&irq_ptr->setup_mutex); - - sprintf(dbf_text, "qfqs%4x", irq_ptr->schid.sch_no); - QDIO_DBF_TEXT1(0, trace, dbf_text); - QDIO_DBF_TEXT0(0, setup, dbf_text); - cdev->private->qdio_data = NULL; mutex_unlock(&irq_ptr->setup_mutex); @@ -1295,7 +1297,6 @@ int qdio_initialize(struct qdio_initialize *init_data) sprintf(dbf_text, "qini%4x", init_data->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0, setup, dbf_text); - QDIO_DBF_TEXT0(0, trace, dbf_text); rc = qdio_allocate(init_data); if (rc) @@ -1319,7 +1320,6 @@ int qdio_allocate(struct qdio_initialize *init_data) sprintf(dbf_text, "qalc%4x", init_data->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0, setup, dbf_text); - QDIO_DBF_TEXT0(0, trace, dbf_text); if ((init_data->no_input_qs && !init_data->input_handler) || (init_data->no_output_qs && !init_data->output_handler)) @@ -1389,6 +1389,9 @@ int qdio_establish(struct qdio_initialize *init_data) unsigned long saveflags; int rc; + sprintf(dbf_text, "qest%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; @@ -1399,10 +1402,6 @@ int qdio_establish(struct qdio_initialize *init_data) if (!try_module_get(THIS_MODULE)) return -EINVAL; - sprintf(dbf_text, "qest%4x", cdev->private->schid.sch_no); - QDIO_DBF_TEXT0(0, setup, dbf_text); - QDIO_DBF_TEXT0(0, trace, dbf_text); - mutex_lock(&irq_ptr->setup_mutex); qdio_setup_irq(init_data); @@ -1472,6 +1471,9 @@ int qdio_activate(struct ccw_device *cdev) unsigned long saveflags; char dbf_text[20]; + sprintf(dbf_text, "qact%4x", cdev->private->schid.sch_no); + QDIO_DBF_TEXT0(0, setup, dbf_text); + irq_ptr = cdev->private->qdio_data; if (!irq_ptr) return -ENODEV; @@ -1485,10 +1487,6 @@ int qdio_activate(struct ccw_device *cdev) goto out; } - sprintf(dbf_text, "qact%4x", irq_ptr->schid.sch_no); - QDIO_DBF_TEXT2(0, setup, dbf_text); - QDIO_DBF_TEXT2(0, trace, dbf_text); - irq_ptr->ccw.cmd_code = irq_ptr->aqueue.cmd; irq_ptr->ccw.flags = CCW_FLAG_SLI; irq_ptr->ccw.count = irq_ptr->aqueue.count; @@ -1663,7 +1661,7 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, #ifdef CONFIG_QDIO_DEBUG char dbf_text[20]; - sprintf(dbf_text, "doQD%04x", cdev->private->schid.sch_no); + sprintf(dbf_text, "doQD%4x", cdev->private->schid.sch_no); QDIO_DBF_TEXT3(0, trace, dbf_text); #endif /* CONFIG_QDIO_DEBUG */ diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 1bd2a20..1679e2f 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c @@ -165,7 +165,7 @@ static void setup_queues(struct qdio_irq *irq_ptr, void **output_sbal_array = qdio_init->output_sbal_addr_array; int i; - sprintf(dbf_text, "qfqs%4x", qdio_init->cdev->private->schid.sch_no); + sprintf(dbf_text, "qset%4x", qdio_init->cdev->private->schid.sch_no); QDIO_DBF_TEXT0(0, setup, dbf_text); for_each_input_queue(irq_ptr, q, i) { @@ -285,7 +285,7 @@ void qdio_setup_ssqd_info(struct qdio_irq *irq_ptr) rc = __get_ssqd_info(irq_ptr); if (rc) { QDIO_DBF_TEXT2(0, setup, "ssqdasig"); - sprintf(dbf_text, "schno%x", irq_ptr->schid.sch_no); + sprintf(dbf_text, "schn%4x", irq_ptr->schid.sch_no); QDIO_DBF_TEXT2(0, setup, dbf_text); sprintf(dbf_text, "rc:%d", rc); QDIO_DBF_TEXT2(0, setup, dbf_text); @@ -447,7 +447,7 @@ void qdio_print_subchannel_info(struct qdio_irq *irq_ptr, { char s[80]; - sprintf(s, "%s ", cdev->dev.bus_id); + sprintf(s, "%s sc:%x ", cdev->dev.bus_id, irq_ptr->schid.sch_no); switch (irq_ptr->qib.qfmt) { case QDIO_QETH_QFMT: -- cgit v1.1 From 0686e402c365c92396d4c7abfaa24810f9cb77cc Mon Sep 17 00:00:00 2001 From: Jan Glauber Date: Thu, 21 Aug 2008 19:46:35 +0200 Subject: [S390] qdio: remove the module_get & module_put pair Increasing the qdio reference count for every used subchannel is unnecessary since unloading qdio (if build as a module) is only possible if other modules that use qdio are unloaded. Unloading modules that use qdio in turn requires that these modules shut down all qdio subchannels. Therefore the additional module_get reference is not needed. Signed-off-by: Jan Glauber Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/qdio_main.c | 4 ---- 1 file changed, 4 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 444fc7e..e6eabc8 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c @@ -1251,7 +1251,6 @@ no_cleanup: qdio_set_state(irq_ptr, QDIO_IRQ_STATE_INACTIVE); mutex_unlock(&irq_ptr->setup_mutex); - module_put(THIS_MODULE); if (rc) return rc; return 0; @@ -1399,9 +1398,6 @@ int qdio_establish(struct qdio_initialize *init_data) if (cdev->private->state != DEV_STATE_ONLINE) return -EINVAL; - if (!try_module_get(THIS_MODULE)) - return -EINVAL; - mutex_lock(&irq_ptr->setup_mutex); qdio_setup_irq(init_data); -- cgit v1.1 From 16f7f9564c3ae190954f2ec55f385a268b93ac4d Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Thu, 21 Aug 2008 19:46:36 +0200 Subject: [S390] cio: fix ccw group device cleanup Fix ccw group device initialization: initialize device object before using reference counting during cleanup. Fixes the following message when group device initialization fails (e.g. because too few devices where specified): kobject: '' (..): is not initialized, yet kobject_put() is being called. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/cio/ccwgroup.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/cio/ccwgroup.c b/drivers/s390/cio/ccwgroup.c index 26a930e..e0ce65f 100644 --- a/drivers/s390/cio/ccwgroup.c +++ b/drivers/s390/cio/ccwgroup.c @@ -112,8 +112,10 @@ ccwgroup_release (struct device *dev) gdev = to_ccwgroupdev(dev); for (i = 0; i < gdev->count; i++) { - dev_set_drvdata(&gdev->cdev[i]->dev, NULL); - put_device(&gdev->cdev[i]->dev); + if (gdev->cdev[i]) { + dev_set_drvdata(&gdev->cdev[i]->dev, NULL); + put_device(&gdev->cdev[i]->dev); + } } kfree(gdev); } @@ -221,6 +223,13 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, atomic_set(&gdev->onoff, 0); mutex_init(&gdev->reg_mutex); mutex_lock(&gdev->reg_mutex); + gdev->creator_id = creator_id; + gdev->count = num_devices; + gdev->dev.bus = &ccwgroup_bus_type; + gdev->dev.parent = root; + gdev->dev.release = ccwgroup_release; + device_initialize(&gdev->dev); + curr_buf = buf; for (i = 0; i < num_devices && curr_buf; i++) { rc = __get_next_bus_id(&curr_buf, tmp_bus_id); @@ -258,16 +267,11 @@ int ccwgroup_create_from_string(struct device *root, unsigned int creator_id, rc = -EINVAL; goto error; } - gdev->creator_id = creator_id; - gdev->count = num_devices; - gdev->dev.bus = &ccwgroup_bus_type; - gdev->dev.parent = root; - gdev->dev.release = ccwgroup_release; snprintf (gdev->dev.bus_id, BUS_ID_SIZE, "%s", gdev->cdev[0]->dev.bus_id); - rc = device_register(&gdev->dev); + rc = device_add(&gdev->dev); if (rc) goto error; get_device(&gdev->dev); -- cgit v1.1 From 49fd38bdaa96f093fcad3176a781a4d0de8f8602 Mon Sep 17 00:00:00 2001 From: Stefan Weinhuber Date: Thu, 21 Aug 2008 19:46:38 +0200 Subject: [S390] dasd: fix data size for PSF/PRSSD command The Perform Subsystem Function/Prepare for Read Subsystem Data command requires 12 bytes of parameter data, but the respective data structure dasd_psf_prssd_data has a length of 16 bytes. Current storage servers ignore the obsolete bytes, but older models fail to execute the command and report an incorrect length error. This causes the device initilization for these devices to fail. To fix this problem we need to correct the dasd_psf_prssd_data structure and shorten it to the correct length. Reported-by: Ivan Warren Reviewed-by: Ivan Warren Tested-by: Ivan Warren CC: stable Signed-off-by: Stefan Weinhuber --- drivers/s390/block/dasd_eckd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 4bf0aa5..2476f87 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h @@ -308,7 +308,7 @@ struct dasd_psf_prssd_data { unsigned char flags; unsigned char reserved[4]; unsigned char suborder; - unsigned char varies[9]; + unsigned char varies[5]; } __attribute__ ((packed)); /* -- cgit v1.1 From 91c36919a456589f4f073671474a1f899e0d3c2b Mon Sep 17 00:00:00 2001 From: Peter Oberparleiter Date: Thu, 21 Aug 2008 19:46:39 +0200 Subject: [S390] cio: call ccw driver notify function with lock held Calling a ccw driver's notify function without the ccw device lock held opens up a race window between discovery and handling of a change in the device operational state. As a result, the device driver may encounter unexpected device malfunction, leading to out-of-retry situations or similar. Remove race by extending the ccw device lock from state change discovery to the calling of the notify function. Signed-off-by: Peter Oberparleiter Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dasd.c | 5 +---- drivers/s390/cio/css.c | 1 - drivers/s390/cio/device.c | 40 ++++++++++++++++++++-------------------- drivers/s390/cio/device.h | 2 +- drivers/s390/cio/device_fsm.c | 31 +++++++++++++++++++------------ 5 files changed, 41 insertions(+), 38 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index 1b6c52e..acb7801 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c @@ -2333,13 +2333,11 @@ int dasd_generic_notify(struct ccw_device *cdev, int event) { struct dasd_device *device; struct dasd_ccw_req *cqr; - unsigned long flags; int ret; - device = dasd_device_from_cdev(cdev); + device = dasd_device_from_cdev_locked(cdev); if (IS_ERR(device)) return 0; - spin_lock_irqsave(get_ccwdev_lock(cdev), flags); ret = 0; switch (event) { case CIO_GONE: @@ -2369,7 +2367,6 @@ int dasd_generic_notify(struct ccw_device *cdev, int event) ret = 1; break; } - spin_unlock_irqrestore(get_ccwdev_lock(cdev), flags); dasd_put_device(device); return ret; } diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 46c021d..51489ef 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c @@ -477,7 +477,6 @@ void css_schedule_eval_all(void) void css_wait_for_slow_path(void) { - flush_workqueue(ccw_device_notify_work); flush_workqueue(slow_path_wq); } diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index e818d0c..2822103 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c @@ -150,7 +150,6 @@ static struct css_driver io_subchannel_driver = { }; struct workqueue_struct *ccw_device_work; -struct workqueue_struct *ccw_device_notify_work; wait_queue_head_t ccw_device_init_wq; atomic_t ccw_device_init_count; @@ -168,11 +167,6 @@ init_ccw_bus_type (void) ccw_device_work = create_singlethread_workqueue("cio"); if (!ccw_device_work) return -ENOMEM; /* FIXME: better errno ? */ - ccw_device_notify_work = create_singlethread_workqueue("cio_notify"); - if (!ccw_device_notify_work) { - ret = -ENOMEM; /* FIXME: better errno ? */ - goto out_err; - } slow_path_wq = create_singlethread_workqueue("kslowcrw"); if (!slow_path_wq) { ret = -ENOMEM; /* FIXME: better errno ? */ @@ -192,8 +186,6 @@ init_ccw_bus_type (void) out_err: if (ccw_device_work) destroy_workqueue(ccw_device_work); - if (ccw_device_notify_work) - destroy_workqueue(ccw_device_notify_work); if (slow_path_wq) destroy_workqueue(slow_path_wq); return ret; @@ -204,7 +196,6 @@ cleanup_ccw_bus_type (void) { css_driver_unregister(&io_subchannel_driver); bus_unregister(&ccw_bus_type); - destroy_workqueue(ccw_device_notify_work); destroy_workqueue(ccw_device_work); } @@ -1496,11 +1487,22 @@ static void device_set_disconnected(struct ccw_device *cdev) ccw_device_schedule_recovery(); } +void ccw_device_set_notoper(struct ccw_device *cdev) +{ + struct subchannel *sch = to_subchannel(cdev->dev.parent); + + CIO_TRACE_EVENT(2, "notoper"); + CIO_TRACE_EVENT(2, sch->dev.bus_id); + ccw_device_set_timeout(cdev, 0); + cio_disable_subchannel(sch); + cdev->private->state = DEV_STATE_NOT_OPER; +} + static int io_subchannel_sch_event(struct subchannel *sch, int slow) { int event, ret, disc; unsigned long flags; - enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE } action; + enum { NONE, UNREGISTER, UNREGISTER_PROBE, REPROBE, DISC } action; struct ccw_device *cdev; spin_lock_irqsave(sch->lock, flags); @@ -1535,16 +1537,11 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) } /* fall through */ case CIO_GONE: - /* Prevent unwanted effects when opening lock. */ - cio_disable_subchannel(sch); - device_set_disconnected(cdev); /* Ask driver what to do with device. */ - action = UNREGISTER; - spin_unlock_irqrestore(sch->lock, flags); - ret = io_subchannel_notify(sch, event); - spin_lock_irqsave(sch->lock, flags); - if (ret) - action = NONE; + if (io_subchannel_notify(sch, event)) + action = DISC; + else + action = UNREGISTER; break; case CIO_REVALIDATE: /* Device will be removed, so no notify necessary. */ @@ -1565,6 +1562,7 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) switch (action) { case UNREGISTER: case UNREGISTER_PROBE: + ccw_device_set_notoper(cdev); /* Unregister device (will use subchannel lock). */ spin_unlock_irqrestore(sch->lock, flags); css_sch_device_unregister(sch); @@ -1577,6 +1575,9 @@ static int io_subchannel_sch_event(struct subchannel *sch, int slow) case REPROBE: ccw_device_trigger_reprobe(cdev); break; + case DISC: + device_set_disconnected(cdev); + break; default: break; } @@ -1828,5 +1829,4 @@ EXPORT_SYMBOL(ccw_driver_unregister); EXPORT_SYMBOL(get_ccwdev_by_busid); EXPORT_SYMBOL(ccw_bus_type); EXPORT_SYMBOL(ccw_device_work); -EXPORT_SYMBOL(ccw_device_notify_work); EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id); diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 9800a83..6f5c3f2 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h @@ -72,7 +72,6 @@ dev_fsm_final_state(struct ccw_device *cdev) } extern struct workqueue_struct *ccw_device_work; -extern struct workqueue_struct *ccw_device_notify_work; extern wait_queue_head_t ccw_device_init_wq; extern atomic_t ccw_device_init_count; @@ -120,6 +119,7 @@ int ccw_device_stlck(struct ccw_device *); void ccw_device_trigger_reprobe(struct ccw_device *); void ccw_device_kill_io(struct ccw_device *); int ccw_device_notify(struct ccw_device *, int); +void ccw_device_set_notoper(struct ccw_device *cdev); /* qdio needs this. */ void ccw_device_set_timeout(struct ccw_device *, int); diff --git a/drivers/s390/cio/device_fsm.c b/drivers/s390/cio/device_fsm.c index 8b5fe57..550508d 100644 --- a/drivers/s390/cio/device_fsm.c +++ b/drivers/s390/cio/device_fsm.c @@ -337,26 +337,34 @@ int ccw_device_notify(struct ccw_device *cdev, int event) return 0; if (!cdev->online) return 0; + CIO_MSG_EVENT(2, "notify called for 0.%x.%04x, event=%d\n", + cdev->private->dev_id.ssid, cdev->private->dev_id.devno, + event); return cdev->drv->notify ? cdev->drv->notify(cdev, event) : 0; } -static void -ccw_device_oper_notify(struct work_struct *work) +static void cmf_reenable_delayed(struct work_struct *work) { struct ccw_device_private *priv; struct ccw_device *cdev; - int ret; priv = container_of(work, struct ccw_device_private, kick_work); cdev = priv->cdev; - ret = ccw_device_notify(cdev, CIO_OPER); - if (ret) { + cmf_reenable(cdev); +} + +static void ccw_device_oper_notify(struct ccw_device *cdev) +{ + if (ccw_device_notify(cdev, CIO_OPER)) { /* Reenable channel measurements, if needed. */ - cmf_reenable(cdev); - wake_up(&cdev->private->wait_q); - } else - /* Driver doesn't want device back. */ - ccw_device_do_unreg_rereg(work); + PREPARE_WORK(&cdev->private->kick_work, cmf_reenable_delayed); + queue_work(ccw_device_work, &cdev->private->kick_work); + return; + } + /* Driver doesn't want device back. */ + ccw_device_set_notoper(cdev); + PREPARE_WORK(&cdev->private->kick_work, ccw_device_do_unreg_rereg); + queue_work(ccw_device_work, &cdev->private->kick_work); } /* @@ -386,8 +394,7 @@ ccw_device_done(struct ccw_device *cdev, int state) if (cdev->private->flags.donotify) { cdev->private->flags.donotify = 0; - PREPARE_WORK(&cdev->private->kick_work, ccw_device_oper_notify); - queue_work(ccw_device_notify_work, &cdev->private->kick_work); + ccw_device_oper_notify(cdev); } wake_up(&cdev->private->wait_q); -- cgit v1.1 From 04f64b5756872b474d9429e3b6987ada10bb8012 Mon Sep 17 00:00:00 2001 From: Gerald Schaefer Date: Thu, 21 Aug 2008 19:46:40 +0200 Subject: [S390] dcssblk: fix race in dcssblk_add_store() Concurrently adding the same segment may lead to duplicate device_register() calls, which will trigger an error in kobject code: "... don't try to register things with the same name in the same directory". This patch adds a check to avoid this. Signed-off-by: Gerald Schaefer Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dcssblk.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers') diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index 01fcdd9..db85f1f 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -384,6 +384,10 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char * get minor, add to list */ down_write(&dcssblk_devices_sem); + if (dcssblk_get_segment_by_name(local_buf)) { + rc = -EEXIST; + goto release_gd; + } rc = dcssblk_assign_free_minor(dev_info); if (rc) { up_write(&dcssblk_devices_sem); -- cgit v1.1 From 167e782e301188c7c7e31e486bbeea5f918324c1 Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Thu, 21 Aug 2008 15:13:29 -0600 Subject: PCI: pciehp: Rename duplicate slot name N as N-1, N-2, N-M... Commit 3800345f723fd130d50434d4717b99d4a9f383c8 (pciehp: fix slot name) introduces the pciehp_slot_with_bus module parameter, which was intended to help work around broken firmware that assigns the same name to multiple slots. Commit 9e4f2e8d4ddb04ad16a3828cd9a369a5a5287009 (pciehp: add message about pciehp_slot_with_bus option) tells the user to use the above parameter in the event of a name collision. This approach is sub-optimal because it requires too much work from the user. Instead, let's rename the slot on behalf of the user. If firmware assigns the name N to multiple slots, then: The first registered slot is assigned N The second registered slot is assigned N-1 The third registered slot is assigned N-2 The Mth registered slot becomes N-M In the event we overflow the slot->name parameter, we report an error to the user. This is a temporary fix until the entire PCI core can be reworked such that individual drivers no longer have to manage their own slot names. Tested-by: Kenji Kaneshige Acked-by: Kenji Kaneshige Signed-off-by: Alex Chiang Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/pciehp.h | 1 - drivers/pci/hotplug/pciehp_core.c | 21 ++++++++++++++------- drivers/pci/hotplug/pciehp_hpc.c | 11 +---------- 3 files changed, 15 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index e3a1e7e..9e6cec6 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h @@ -43,7 +43,6 @@ extern int pciehp_poll_mode; extern int pciehp_poll_time; extern int pciehp_debug; extern int pciehp_force; -extern int pciehp_slot_with_bus; extern struct workqueue_struct *pciehp_wq; #define dbg(format, arg...) \ diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 3677495..4fd5355 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c @@ -41,7 +41,6 @@ int pciehp_debug; int pciehp_poll_mode; int pciehp_poll_time; int pciehp_force; -int pciehp_slot_with_bus; struct workqueue_struct *pciehp_wq; #define DRIVER_VERSION "0.4" @@ -56,12 +55,10 @@ module_param(pciehp_debug, bool, 0644); module_param(pciehp_poll_mode, bool, 0644); module_param(pciehp_poll_time, int, 0644); module_param(pciehp_force, bool, 0644); -module_param(pciehp_slot_with_bus, bool, 0644); MODULE_PARM_DESC(pciehp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(pciehp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(pciehp_poll_time, "Polling mechanism frequency, in seconds"); MODULE_PARM_DESC(pciehp_force, "Force pciehp, even if _OSC and OSHP are missing"); -MODULE_PARM_DESC(pciehp_slot_with_bus, "Use bus number in the slot name"); #define PCIE_MODULE_NAME "pciehp" @@ -194,6 +191,7 @@ static int init_slots(struct controller *ctrl) struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; + int len, dup = 1; int retval = -ENOMEM; list_for_each_entry(slot, &ctrl->slot_list, slot_list) { @@ -220,15 +218,24 @@ static int init_slots(struct controller *ctrl) dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " "slot_device_offset=%x\n", slot->bus, slot->device, slot->hp_slot, slot->number, ctrl->slot_device_offset); +duplicate_name: retval = pci_hp_register(hotplug_slot, ctrl->pci_dev->subordinate, slot->device); if (retval) { + /* + * If slot N already exists, we'll try to create + * slot N-1, N-2 ... N-M, until we overflow. + */ + if (retval == -EEXIST) { + len = snprintf(slot->name, SLOT_NAME_SIZE, + "%d-%d", slot->number, dup++); + if (len < SLOT_NAME_SIZE) + goto duplicate_name; + else + err("duplicate slot name overflow\n"); + } err("pci_hp_register failed with error %d\n", retval); - if (retval == -EEXIST) - err("Failed to register slot because of name " - "collision. Try \'pciehp_slot_with_bus\' " - "module option.\n"); goto error_info; } /* create additional sysfs entries */ diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index ad27e9e..ab31f5b 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c @@ -1030,15 +1030,6 @@ static void pcie_shutdown_notification(struct controller *ctrl) pciehp_free_irq(ctrl); } -static void make_slot_name(struct slot *slot) -{ - if (pciehp_slot_with_bus) - snprintf(slot->name, SLOT_NAME_SIZE, "%04d_%04d", - slot->bus, slot->number); - else - snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); -} - static int pcie_init_slot(struct controller *ctrl) { struct slot *slot; @@ -1053,7 +1044,7 @@ static int pcie_init_slot(struct controller *ctrl) slot->device = ctrl->slot_device_offset + slot->hp_slot; slot->hpc_ops = ctrl->hpc_ops; slot->number = ctrl->first_slot; - make_slot_name(slot); + snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); mutex_init(&slot->lock); INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); list_add(&slot->slot_list, &ctrl->slot_list); -- cgit v1.1 From d6a9e9b40be7da84f82eb414c2ad98c5bb69986b Mon Sep 17 00:00:00 2001 From: Alex Chiang Date: Thu, 21 Aug 2008 15:13:47 -0600 Subject: PCI: shpchp: Rename duplicate slot name N as N-1, N-2, N-M... Commit ef0ff95f136f0f2d035667af5d18b824609de320 (shpchp: fix slot name) introduces the shpchp_slot_with_bus module parameter, which was intended to help work around broken firmware that assigns the same name to multiple slots. Commit b3bd307c628af2f0a581c42d5d7e4bcdbbf64b6a (shpchp: add message about shpchp_slot_with_bus option) tells the user to use the above parameter in the event of a name collision. This approach is sub-optimal because it requires too much work from the user. Instead, let's rename the slot on behalf of the user. If firmware assigns the name N to multiple slots, then: The first registered slot is assigned N The second registered slot is assigned N-1 The third registered slot is assigned N-2 The Mth registered slot becomes N-M In the event we overflow the slot->name parameter, we report an error to the user. This is a temporary fix until the entire PCI core can be reworked such that individual drivers no longer have to manage their own slot names. Tested-by: Kenji Kaneshige Acked-by: Kenji Kaneshige Signed-off-by: Alex Chiang Signed-off-by: Jesse Barnes --- drivers/pci/hotplug/shpchp_core.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index a8cbd03..cc38615 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c @@ -39,7 +39,6 @@ int shpchp_debug; int shpchp_poll_mode; int shpchp_poll_time; -static int shpchp_slot_with_bus; struct workqueue_struct *shpchp_wq; #define DRIVER_VERSION "0.4" @@ -53,11 +52,9 @@ MODULE_LICENSE("GPL"); module_param(shpchp_debug, bool, 0644); module_param(shpchp_poll_mode, bool, 0644); module_param(shpchp_poll_time, int, 0644); -module_param(shpchp_slot_with_bus, bool, 0644); MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not"); MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not"); MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds"); -MODULE_PARM_DESC(shpchp_slot_with_bus, "Use bus number in the slot name"); #define SHPC_MODULE_NAME "shpchp" @@ -99,23 +96,13 @@ static void release_slot(struct hotplug_slot *hotplug_slot) kfree(slot); } -static void make_slot_name(struct slot *slot) -{ - if (shpchp_slot_with_bus) - snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%04d_%04d", - slot->bus, slot->number); - else - snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", - slot->number); -} - static int init_slots(struct controller *ctrl) { struct slot *slot; struct hotplug_slot *hotplug_slot; struct hotplug_slot_info *info; int retval = -ENOMEM; - int i; + int i, len, dup = 1; for (i = 0; i < ctrl->num_slots; i++) { slot = kzalloc(sizeof(*slot), GFP_KERNEL); @@ -146,7 +133,7 @@ static int init_slots(struct controller *ctrl) /* register this slot with the hotplug pci core */ hotplug_slot->private = slot; hotplug_slot->release = &release_slot; - make_slot_name(slot); + snprintf(slot->name, SLOT_NAME_SIZE, "%d", slot->number); hotplug_slot->ops = &shpchp_hotplug_slot_ops; get_power_status(hotplug_slot, &info->power_status); @@ -157,14 +144,23 @@ static int init_slots(struct controller *ctrl) dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x " "slot_device_offset=%x\n", slot->bus, slot->device, slot->hp_slot, slot->number, ctrl->slot_device_offset); +duplicate_name: retval = pci_hp_register(slot->hotplug_slot, ctrl->pci_dev->subordinate, slot->device); if (retval) { + /* + * If slot N already exists, we'll try to create + * slot N-1, N-2 ... N-M, until we overflow. + */ + if (retval == -EEXIST) { + len = snprintf(slot->name, SLOT_NAME_SIZE, + "%d-%d", slot->number, dup++); + if (len < SLOT_NAME_SIZE) + goto duplicate_name; + else + err("duplicate slot name overflow\n"); + } err("pci_hp_register failed with error %d\n", retval); - if (retval == -EEXIST) - err("Failed to register slot because of name " - "collision. Try \'shpchp_slot_with_bus\' " - "module option.\n"); goto error_info; } -- cgit v1.1 From ebca4f1bce1eb7b91a63c515db66316db9391221 Mon Sep 17 00:00:00 2001 From: Greg KH Date: Thu, 21 Aug 2008 13:47:58 -0700 Subject: PCI: fix reference leak in pci_get_dev_by_id() Alex Chiang and Matthew Wilcox pointed out that pci_get_dev_by_id() does not properly decrement the reference on the from pointer if it is present, like the documentation for the function states it will. It fixes a pretty bad leak in the hotplug core (we were leaking an entire struct pci_dev for each function of each offlined card, the first time around; subsequent onlines/offlines were ok). Cc: Matthew Wilcox Cc: stable Tested-by: Alex Chiang Acked-by: Alex Chiang Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jesse Barnes --- drivers/pci/search.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/pci/search.c b/drivers/pci/search.c index 217814f..3b3b5f1 100644 --- a/drivers/pci/search.c +++ b/drivers/pci/search.c @@ -280,6 +280,8 @@ static struct pci_dev *pci_get_dev_by_id(const struct pci_device_id *id, match_pci_dev_by_id); if (dev) pdev = to_pci_dev(dev); + if (from) + pci_dev_put(from); return pdev; } -- cgit v1.1 From 05944bdf6fadb5394710269df6770dde447b23ca Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 13 Aug 2008 20:19:09 +0900 Subject: libata: implement no[hs]rst force params Implement force params nohrst, nosrst and norst. This is to work around reset related problems and ease debugging. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 46 ++++++++++++++++++++++++++++++---------------- drivers/ata/libata-eh.c | 4 ++++ 2 files changed, 34 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 5ba96c5..dddcb9f 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -104,6 +104,7 @@ struct ata_force_param { unsigned long xfer_mask; unsigned int horkage_on; unsigned int horkage_off; + unsigned int lflags; }; struct ata_force_ent { @@ -196,22 +197,23 @@ void ata_force_cbl(struct ata_port *ap) } /** - * ata_force_spd_limit - force SATA spd limit according to libata.force + * ata_force_link_limits - force link limits according to libata.force * @link: ATA link of interest * - * Force SATA spd limit according to libata.force and whine about - * it. When only the port part is specified (e.g. 1:), the limit - * applies to all links connected to both the host link and all - * fan-out ports connected via PMP. If the device part is - * specified as 0 (e.g. 1.00:), it specifies the first fan-out - * link not the host link. Device number 15 always points to the - * host link whether PMP is attached or not. + * Force link flags and SATA spd limit according to libata.force + * and whine about it. When only the port part is specified + * (e.g. 1:), the limit applies to all links connected to both + * the host link and all fan-out ports connected via PMP. If the + * device part is specified as 0 (e.g. 1.00:), it specifies the + * first fan-out link not the host link. Device number 15 always + * points to the host link whether PMP is attached or not. * * LOCKING: * EH context. */ -static void ata_force_spd_limit(struct ata_link *link) +static void ata_force_link_limits(struct ata_link *link) { + bool did_spd = false; int linkno, i; if (ata_is_host_link(link)) @@ -228,13 +230,22 @@ static void ata_force_spd_limit(struct ata_link *link) if (fe->device != -1 && fe->device != linkno) continue; - if (!fe->param.spd_limit) - continue; + /* only honor the first spd limit */ + if (!did_spd && fe->param.spd_limit) { + link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1; + ata_link_printk(link, KERN_NOTICE, + "FORCE: PHY spd limit set to %s\n", + fe->param.name); + did_spd = true; + } - link->hw_sata_spd_limit = (1 << fe->param.spd_limit) - 1; - ata_link_printk(link, KERN_NOTICE, - "FORCE: PHY spd limit set to %s\n", fe->param.name); - return; + /* let lflags stack */ + if (fe->param.lflags) { + link->flags |= fe->param.lflags; + ata_link_printk(link, KERN_NOTICE, + "FORCE: link flag 0x%x forced -> 0x%x\n", + fe->param.lflags, link->flags); + } } } @@ -5200,7 +5211,7 @@ int sata_link_init_spd(struct ata_link *link) if (spd) link->hw_sata_spd_limit &= (1 << spd) - 1; - ata_force_spd_limit(link); + ata_force_link_limits(link); link->sata_spd_limit = link->hw_sata_spd_limit; @@ -5991,6 +6002,9 @@ static int __init ata_parse_force_one(char **cur, { "udma133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, { "udma/133", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 6) }, { "udma7", .xfer_mask = 1 << (ATA_SHIFT_UDMA + 7) }, + { "nohrst", .lflags = ATA_LFLAG_NO_HRST }, + { "nosrst", .lflags = ATA_LFLAG_NO_SRST }, + { "norst", .lflags = ATA_LFLAG_NO_HRST | ATA_LFLAG_NO_SRST }, }; char *start = *cur, *p = *cur; char *id, *val, *endp; diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 58bdc53..a570ca4 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2210,6 +2210,10 @@ int ata_eh_reset(struct ata_link *link, int classify, */ while (ata_eh_reset_timeouts[max_tries] != ULONG_MAX) max_tries++; + if (link->flags & ATA_LFLAG_NO_HRST) + hardreset = NULL; + if (link->flags & ATA_LFLAG_NO_SRST) + softreset = NULL; now = jiffies; deadline = ata_deadline(ehc->last_reset, ATA_EH_RESET_COOL_DOWN); -- cgit v1.1 From 4bdee6c5103696a2729d3db2f235d202191788e4 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Wed, 13 Aug 2008 20:24:16 +0900 Subject: sata_mv: don't issue two DMA commands concurrently sata_mv allowed issuing two DMA commands concurrently which the hardware allows. Unfortunately, libata core layer isn't ready for this yet and spews ugly warning message and malfunctions on this. Don't allow concurrent DMA commands for now. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/sata_mv.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c index ad169ff..80c655f 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -1134,30 +1134,16 @@ static int mv_qc_defer(struct ata_queued_cmd *qc) if (ap->nr_active_links == 0) return 0; - if (pp->pp_flags & MV_PP_FLAG_EDMA_EN) { - /* - * The port is operating in host queuing mode (EDMA). - * It can accomodate a new qc if the qc protocol - * is compatible with the current host queue mode. - */ - if (pp->pp_flags & MV_PP_FLAG_NCQ_EN) { - /* - * The host queue (EDMA) is in NCQ mode. - * If the new qc is also an NCQ command, - * then allow the new qc. - */ - if (qc->tf.protocol == ATA_PROT_NCQ) - return 0; - } else { - /* - * The host queue (EDMA) is in non-NCQ, DMA mode. - * If the new qc is also a non-NCQ, DMA command, - * then allow the new qc. - */ - if (qc->tf.protocol == ATA_PROT_DMA) - return 0; - } - } + /* + * The port is operating in host queuing mode (EDMA) with NCQ + * enabled, allow multiple NCQ commands. EDMA also allows + * queueing multiple DMA commands but libata core currently + * doesn't allow it. + */ + if ((pp->pp_flags & MV_PP_FLAG_EDMA_EN) && + (pp->pp_flags & MV_PP_FLAG_NCQ_EN) && ata_is_ncq(qc->tf.protocol)) + return 0; + return ATA_DEFER_PORT; } -- cgit v1.1 From adcb5308dda3d2749342685f23953e13ba74ff68 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Mon, 11 Aug 2008 17:03:09 -0700 Subject: ahci: RAID mode SATA patch for Intel Ibex Peak DeviceIDs Resend with proper whitespace. This patch adds the Intel Ibex Peak (PCH) SATA RAID Controller DeviceIDs. Signed-off-by: Seth Heasley Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index ef3e552..a0e85a7 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -486,6 +486,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(INTEL, 0x502b), board_ahci }, /* Tolapai */ { PCI_VDEVICE(INTEL, 0x3a05), board_ahci }, /* ICH10 */ { PCI_VDEVICE(INTEL, 0x3a25), board_ahci }, /* ICH10 */ + { PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */ + { PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */ /* JMicron 360/1/3/5/6, match class to avoid IDE function */ { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, -- cgit v1.1 From c6c6a1afefe51d488c050464f261d4711bea9a37 Mon Sep 17 00:00:00 2001 From: Seth Heasley Date: Mon, 11 Aug 2008 17:03:18 -0700 Subject: ata_piix: IDE Mode SATA patch for Intel Ibex Peak DeviceIDs This patch adds the Intel Ibex Peak (PCH) IDE mode SATA Controller DeviceIDs. Signed-off-by: Seth Heasley Signed-off-by: Jeff Garzik --- drivers/ata/ata_piix.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index c294121..b1d08a8 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c @@ -275,6 +275,14 @@ static const struct pci_device_id piix_pci_tbl[] = { { 0x8086, 0x3a20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, /* SATA Controller IDE (ICH10) */ { 0x8086, 0x3a26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b20, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, + /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b26, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b2d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata }, + /* SATA Controller IDE (PCH) */ + { 0x8086, 0x3b2e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata }, { } /* terminate list */ }; -- cgit v1.1 From eb3a55a9f43f0f8e770c2abf70e65bdda2d5ff1e Mon Sep 17 00:00:00 2001 From: Saeed Bishara Date: Mon, 4 Aug 2008 00:52:55 -1100 Subject: sata_mv: add the Gen IIE flag to the SoC devices. The SoC sata port is based on the 7042/6042 devices (Gen IIE). This patch will fix various issues when working with PMP and/or NCQ. Signed-off-by: Saeed Bishara 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 80c655f..13c1d2a 100644 --- a/drivers/ata/sata_mv.c +++ b/drivers/ata/sata_mv.c @@ -3022,7 +3022,8 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx) break; case chip_soc: hpriv->ops = &mv_soc_ops; - hp_flags |= MV_HP_FLAG_SOC | MV_HP_ERRATA_60X1C0; + hp_flags |= MV_HP_FLAG_SOC | MV_HP_GEN_IIE | + MV_HP_ERRATA_60X1C0; break; default: -- cgit v1.1 From a674050e068a2919908730279f0b731ae6d2e005 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 31 Jul 2008 16:07:04 +0900 Subject: libata: fix EH action overwriting in ata_eh_reset() ehc->i.action got accidentally overwritten to ATA_EH_HARD/SOFTRESET in ata_eh_reset(). The original intention was to clear reset action which wasn't selected. This can cause unexpected behavior when other EH actions are scheduled together with reset. Fix it. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index a570ca4..c98909b 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2251,10 +2251,10 @@ int ata_eh_reset(struct ata_link *link, int classify, ehc->i.action &= ~ATA_EH_RESET; if (hardreset) { reset = hardreset; - ehc->i.action = ATA_EH_HARDRESET; + ehc->i.action |= ATA_EH_HARDRESET; } else if (softreset) { reset = softreset; - ehc->i.action = ATA_EH_SOFTRESET; + ehc->i.action |= ATA_EH_SOFTRESET; } if (prereset) { -- cgit v1.1 From 5dbfc9cb59d4ad75199949d7dd8a8c6d7bc518df Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 31 Jul 2008 16:08:02 +0900 Subject: libata: always do follow-up SRST if hardreset returned -EAGAIN As an optimization, follow-up SRST used to be skipped if classification wasn't requested even when hardreset requested it via -EAGAIN. However, some hardresets can't wait for device readiness and skipping SRST can cause timeout or other failures during revalidation. Always perform follow-up SRST if hardreset returns -EAGAIN. This makes reset paths more predictable and thus less error-prone. While at it, move hardreset error checking such that it's done right after hardreset is finished. This simplifies followup SRST condition check a bit and makes the reset path easier to modify. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-eh.c | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index c98909b..d4dad47 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2171,18 +2171,12 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset, } static int ata_eh_followup_srst_needed(struct ata_link *link, - int rc, int classify, - const unsigned int *classes) + int rc, const unsigned int *classes) { if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link)) return 0; - if (rc == -EAGAIN) { - if (classify) - return 1; - rc = 0; - } - if (rc != 0) - return 0; + if (rc == -EAGAIN) + return 1; if (sata_pmp_supported(link->ap) && ata_is_host_link(link)) return 1; return 0; @@ -2309,9 +2303,11 @@ int ata_eh_reset(struct ata_link *link, int classify, ehc->i.flags |= ATA_EHI_DID_SOFTRESET; rc = ata_do_reset(link, reset, classes, deadline); + if (rc && rc != -EAGAIN) + goto fail; if (reset == hardreset && - ata_eh_followup_srst_needed(link, rc, classify, classes)) { + ata_eh_followup_srst_needed(link, rc, classes)) { /* okay, let's do follow-up softreset */ reset = softreset; @@ -2326,10 +2322,6 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_about_to_do(link, NULL, ATA_EH_RESET); rc = ata_do_reset(link, reset, classes, deadline); } - - /* -EAGAIN can happen if we skipped followup SRST */ - if (rc && rc != -EAGAIN) - goto fail; } else { if (verbose) ata_link_printk(link, KERN_INFO, "no reset method " -- cgit v1.1 From da0e21d3fa2340114fe24821718a1b57123e4664 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 31 Jul 2008 16:08:38 +0900 Subject: libata: use ata_link_printk() when printing SError SError belongs to link not port. Use ata_link_printk() to print it. Signed-off-by: Tejun Heo 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 d4dad47..c1db2f2 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2040,7 +2040,7 @@ static void ata_eh_link_report(struct ata_link *link) } if (ehc->i.serror) - ata_port_printk(ap, KERN_ERR, + ata_link_printk(link, KERN_ERR, "SError: { %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n", ehc->i.serror & SERR_DATA_RECOVERED ? "RecovData " : "", ehc->i.serror & SERR_COMM_RECOVERED ? "RecovComm " : "", -- cgit v1.1 From d127ea7b8643a93d14d1f3c542974407f14d3663 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 31 Jul 2008 16:09:34 +0900 Subject: libata: restore SControl on detach Save SControl during probing and restore it on detach. This prevents adjustments made by libata drivers to seep into the next driver which gets attached (be it a libata one or not). It's not clear whether SControl also needs to be restored on suspend. The next system to have control (ACPI or kexec'd kernel) would probably like to see the original SControl value but there's no guarantee that a link is gonna keep working after SControl is adjusted without a reset and adding a reset and modified recovery cycle soley for this is an overkill. For now, do it only for detach. Signed-off-by: Tejun Heo Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index dddcb9f..5f8f57a 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -5199,15 +5199,14 @@ void ata_link_init(struct ata_port *ap, struct ata_link *link, int pmp) */ int sata_link_init_spd(struct ata_link *link) { - u32 scontrol; u8 spd; int rc; - rc = sata_scr_read(link, SCR_CONTROL, &scontrol); + rc = sata_scr_read(link, SCR_CONTROL, &link->saved_scontrol); if (rc) return rc; - spd = (scontrol >> 4) & 0xf; + spd = (link->saved_scontrol >> 4) & 0xf; if (spd) link->hw_sata_spd_limit &= (1 << spd) - 1; @@ -5794,9 +5793,10 @@ static void ata_port_detach(struct ata_port *ap) ata_port_wait_eh(ap); /* EH is now guaranteed to see UNLOADING - EH context belongs - * to us. Disable all existing devices. + * to us. Restore SControl and disable all existing devices. */ - ata_port_for_each_link(link, ap) { + __ata_port_for_each_link(link, ap) { + sata_scr_write(link, SCR_CONTROL, link->saved_scontrol); ata_link_for_each_dev(dev, link) ata_dev_disable(dev); } -- cgit v1.1 From ff04715bd5171d6d5c4ddff40c7bdc8d2dc90f7d Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Thu, 31 Jul 2008 18:02:35 +0900 Subject: pata_via: clean up recent tf_load changes Commit bfce5e0179ad059035df28558724ff60af708e09 implemented custom tf_load for pata_via. This patch cleans it up a bit. * Instead of duplicating whole body, copy tf and set ATA_TFLAG_DEVICE when necessary. * Rename via_ata_tf_load() to via_tf_load(). * No need to set .tf_load in via_port_ops_noirq as it inherits from via_port_ops. * Clean up indentation. Signed-off-by: Tejun Heo Cc: Joseph Chan Signed-off-by: Jeff Garzik --- drivers/ata/pata_via.c | 59 ++++++++++---------------------------------------- 1 file changed, 11 insertions(+), 48 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c index 57d951b..8fdb2ce 100644 --- a/drivers/ata/pata_via.c +++ b/drivers/ata/pata_via.c @@ -324,62 +324,26 @@ static void via_set_dmamode(struct ata_port *ap, struct ata_device *adev) } /** - * via_ata_sff_tf_load - send taskfile registers to host controller + * via_tf_load - send taskfile registers to host controller * @ap: Port to which output is sent * @tf: ATA taskfile register set * * Outputs ATA taskfile to standard ATA host controller. * * Note: This is to fix the internal bug of via chipsets, which - * will reset the device register after changing the IEN bit on - * ctl register + * will reset the device register after changing the IEN bit on + * ctl register */ -static void via_ata_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) +static void via_tf_load(struct ata_port *ap, const struct ata_taskfile *tf) { - struct ata_ioports *ioaddr = &ap->ioaddr; - unsigned int is_addr = tf->flags & ATA_TFLAG_ISADDR; - - if (tf->ctl != ap->last_ctl) { - iowrite8(tf->ctl, ioaddr->ctl_addr); - iowrite8(tf->device, ioaddr->device_addr); - ap->last_ctl = tf->ctl; - ata_wait_idle(ap); - } - - if (is_addr && (tf->flags & ATA_TFLAG_LBA48)) { - iowrite8(tf->hob_feature, ioaddr->feature_addr); - iowrite8(tf->hob_nsect, ioaddr->nsect_addr); - iowrite8(tf->hob_lbal, ioaddr->lbal_addr); - iowrite8(tf->hob_lbam, ioaddr->lbam_addr); - iowrite8(tf->hob_lbah, ioaddr->lbah_addr); - VPRINTK("hob: feat 0x%X nsect 0x%X, lba 0x%X 0x%X 0x%X\n", - tf->hob_feature, - tf->hob_nsect, - tf->hob_lbal, - tf->hob_lbam, - tf->hob_lbah); - } + struct ata_taskfile tmp_tf; - if (is_addr) { - iowrite8(tf->feature, ioaddr->feature_addr); - iowrite8(tf->nsect, ioaddr->nsect_addr); - iowrite8(tf->lbal, ioaddr->lbal_addr); - iowrite8(tf->lbam, ioaddr->lbam_addr); - iowrite8(tf->lbah, ioaddr->lbah_addr); - VPRINTK("feat 0x%X nsect 0x%X lba 0x%X 0x%X 0x%X\n", - tf->feature, - tf->nsect, - tf->lbal, - tf->lbam, - tf->lbah); + if (ap->ctl != ap->last_ctl && !(tf->flags & ATA_TFLAG_DEVICE)) { + tmp_tf = *tf; + tmp_tf.flags |= ATA_TFLAG_DEVICE; + tf = &tmp_tf; } - - if (tf->flags & ATA_TFLAG_DEVICE) { - iowrite8(tf->device, ioaddr->device_addr); - VPRINTK("device 0x%X\n", tf->device); - } - - ata_wait_idle(ap); + ata_sff_tf_load(ap, tf); } static struct scsi_host_template via_sht = { @@ -392,13 +356,12 @@ static struct ata_port_operations via_port_ops = { .set_piomode = via_set_piomode, .set_dmamode = via_set_dmamode, .prereset = via_pre_reset, - .sff_tf_load = via_ata_tf_load, + .sff_tf_load = via_tf_load, }; static struct ata_port_operations via_port_ops_noirq = { .inherits = &via_port_ops, .sff_data_xfer = ata_sff_data_xfer_noirq, - .sff_tf_load = via_ata_tf_load, }; /** -- cgit v1.1 From 20e2de4a505aa02131a95665e8920eb053fce686 Mon Sep 17 00:00:00 2001 From: Tejun Heo Date: Fri, 1 Aug 2008 12:51:43 +0900 Subject: ahci: sis controllers actually can do PMP SIS controllers were blacklisted for PMP as enabling it made device detection fail whether the device was PMP or not - the natural conclusion was the controller chokes on SRST w/ pmp==15. However, it turned out that the controller just didn't like issuing SRST after hardreset w/o clearing SError first. Interestingly, the SRST itself succeeds but the following commands fail. If SError is cleared between hardreset and SRST, which is the default behavior now, everything works fine and SIS controllers work with PMPs happily. Remove PMP blacklisting for SIS AHCIs. Signed-off-by: Tejun Heo Cc: Piter PUNK Signed-off-by: Jeff Garzik --- drivers/ata/ahci.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a0e85a7..c729e69 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c @@ -577,9 +577,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { { PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */ /* SiS */ - { PCI_VDEVICE(SI, 0x1184), board_ahci_nopmp }, /* SiS 966 */ - { PCI_VDEVICE(SI, 0x1185), board_ahci_nopmp }, /* SiS 968 */ - { PCI_VDEVICE(SI, 0x0186), board_ahci_nopmp }, /* SiS 968 */ + { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ + { PCI_VDEVICE(SI, 0x1185), board_ahci }, /* SiS 968 */ + { PCI_VDEVICE(SI, 0x0186), board_ahci }, /* SiS 968 */ /* Marvell */ { PCI_VDEVICE(MARVELL, 0x6145), board_ahci_mv }, /* 6145 */ -- cgit v1.1 From b15b3ebae102f89c25ccbcae0b2099af312f2e82 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 1 Aug 2008 09:18:34 +0100 Subject: libata: Fix a large collection of DMA mode mismatches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dave Müller sent a diff for the pata_oldpiix that highlighted a problem where a lot of the ATA drivers assume dma_mode == 0 means "no DMA" while the core code uses 0xFF. This turns out to have other consequences such as code doing >= XFER_UDMA_0 also catching 0xFF as UDMAlots. Fortunately it doesn't generally affect set_dma_mode, although some drivers call back into their own set mode code from other points. Having been through the drivers I've added helpers for using_udma/using_mwdma dma_enabled so that people don't open code ranges that may change (eg if UDMA8 appears somewhere) Thanks to David for the initial bits [and added fix for pata_oldpiix from and signed-off-by Dave Mueller -jg] Signed-off-by: Alan Cox Signed-off-by: Jeff Garzik --- drivers/ata/libata-core.c | 4 ++-- drivers/ata/pata_acpi.c | 2 +- drivers/ata/pata_atiixp.c | 2 +- drivers/ata/pata_cs5530.c | 6 +++--- drivers/ata/pata_oldpiix.c | 2 +- drivers/ata/pata_sc1200.c | 6 +++--- 6 files changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 5f8f57a..79e3a8e 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3288,7 +3288,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) dev->dma_mode = ata_xfer_mask2mode(dma_mask); found = 1; - if (dev->dma_mode != 0xff) + if (ata_dma_enabled(dev)) used_dma = 1; } if (!found) @@ -3313,7 +3313,7 @@ int ata_do_set_mode(struct ata_link *link, struct ata_device **r_failed_dev) /* step 3: set host DMA timings */ ata_link_for_each_dev(dev, link) { - if (!ata_dev_enabled(dev) || dev->dma_mode == 0xff) + if (!ata_dev_enabled(dev) || !ata_dma_enabled(dev)) continue; dev->xfer_mode = dev->dma_mode; diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c index fbe6057..eb919c1 100644 --- a/drivers/ata/pata_acpi.c +++ b/drivers/ata/pata_acpi.c @@ -181,7 +181,7 @@ static unsigned int pacpi_qc_issue(struct ata_queued_cmd *qc) if (adev != acpi->last) { pacpi_set_piomode(ap, adev); - if (adev->dma_mode) + if (ata_dma_enabled(adev)) pacpi_set_dmamode(ap, adev); acpi->last = adev; } diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c index d7de7ba..e8a0d99 100644 --- a/drivers/ata/pata_atiixp.c +++ b/drivers/ata/pata_atiixp.c @@ -183,7 +183,7 @@ static void atiixp_bmdma_start(struct ata_queued_cmd *qc) u16 tmp16; pci_read_config_word(pdev, ATIIXP_IDE_UDMA_CONTROL, &tmp16); - if (adev->dma_mode >= XFER_UDMA_0) + if (ata_using_udma(adev)) tmp16 |= (1 << dn); else tmp16 &= ~(1 << dn); diff --git a/drivers/ata/pata_cs5530.c b/drivers/ata/pata_cs5530.c index 744beeb..0c4b271 100644 --- a/drivers/ata/pata_cs5530.c +++ b/drivers/ata/pata_cs5530.c @@ -149,10 +149,10 @@ static unsigned int cs5530_qc_issue(struct ata_queued_cmd *qc) struct ata_device *prev = ap->private_data; /* See if the DMA settings could be wrong */ - if (adev->dma_mode != 0 && adev != prev && prev != NULL) { + if (ata_dma_enabled(adev) && adev != prev && prev != NULL) { /* Maybe, but do the channels match MWDMA/UDMA ? */ - if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) || - (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0)) + if ((ata_using_udma(adev) && !ata_using_udma(prev)) || + (ata_using_udma(prev) && !ata_using_udma(adev))) /* Switch the mode bits */ cs5530_set_dmamode(ap, adev); } diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c index e678af3..df64f24 100644 --- a/drivers/ata/pata_oldpiix.c +++ b/drivers/ata/pata_oldpiix.c @@ -198,7 +198,7 @@ static unsigned int oldpiix_qc_issue(struct ata_queued_cmd *qc) if (adev != ap->private_data) { oldpiix_set_piomode(ap, adev); - if (adev->dma_mode) + if (ata_dma_enabled(adev)) oldpiix_set_dmamode(ap, adev); } return ata_sff_qc_issue(qc); diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c index cbab397..0278fd2 100644 --- a/drivers/ata/pata_sc1200.c +++ b/drivers/ata/pata_sc1200.c @@ -167,10 +167,10 @@ static unsigned int sc1200_qc_issue(struct ata_queued_cmd *qc) struct ata_device *prev = ap->private_data; /* See if the DMA settings could be wrong */ - if (adev->dma_mode != 0 && adev != prev && prev != NULL) { + if (ata_dma_enabled(adev) && adev != prev && prev != NULL) { /* Maybe, but do the channels match MWDMA/UDMA ? */ - if ((adev->dma_mode >= XFER_UDMA_0 && prev->dma_mode < XFER_UDMA_0) || - (adev->dma_mode < XFER_UDMA_0 && prev->dma_mode >= XFER_UDMA_0)) + if ((ata_using_udma(adev) && !ata_using_udma(prev)) || + (ata_using_udma(prev) && !ata_using_udma(adev))) /* Switch the mode bits */ sc1200_set_dmamode(ap, adev); } -- cgit v1.1 From 4ef281853474389fea952e9e59650e599ecf2d62 Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Fri, 22 Aug 2008 02:33:23 -0400 Subject: [libata] pata_it821x: fix warning Reported by Andrew Morton: drivers/ata/pata_it821x.c: In function 'it821x_port_start': drivers/ata/pata_it821x.c:609: warning: 'mtype' may be used uninitialized in this function Pretty horrid fix, but so's a warning.. Signed-off-by: Jeff Garzik --- drivers/ata/pata_it821x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/ata/pata_it821x.c b/drivers/ata/pata_it821x.c index 27843c7..0221c9a 100644 --- a/drivers/ata/pata_it821x.c +++ b/drivers/ata/pata_it821x.c @@ -606,7 +606,7 @@ static void it821x_display_disk(int n, u8 *buf) { unsigned char id[41]; int mode = 0; - char *mtype; + char *mtype = ""; char mbuf[8]; char *cbl = "(40 wire cable)"; -- cgit v1.1 From 7a8fc9b248e77a4eab0613acf30a6811799786b3 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Sun, 17 Aug 2008 17:36:59 +0300 Subject: removed unused #include 's This patch lets the files using linux/version.h match the files that #include it. Signed-off-by: Adrian Bunk Signed-off-by: Linus Torvalds --- drivers/atm/adummy.c | 1 - drivers/char/xilinx_hwicap/buffer_icap.h | 1 - drivers/char/xilinx_hwicap/fifo_icap.h | 1 - drivers/char/xilinx_hwicap/xilinx_hwicap.h | 1 - drivers/edac/edac_core.h | 1 - drivers/i2c/busses/i2c-at91.c | 1 - drivers/infiniband/hw/ehca/ehca_tools.h | 1 - drivers/infiniband/hw/ipath/ipath_fs.c | 1 - drivers/infiniband/hw/nes/nes.h | 1 - drivers/infiniband/ulp/iser/iser_verbs.c | 1 - drivers/input/keyboard/bf54x-keys.c | 1 - drivers/input/touchscreen/mainstone-wm97xx.c | 1 - drivers/mfd/asic3.c | 1 - drivers/misc/eeprom_93cx6.c | 1 - drivers/mtd/maps/amd76xrom.c | 1 - drivers/mtd/maps/ck804xrom.c | 1 - drivers/mtd/maps/esb2rom.c | 1 - drivers/mtd/nand/au1550nd.c | 1 - drivers/net/myri10ge/myri10ge.c | 1 - drivers/net/netxen/netxen_nic.h | 1 - drivers/net/netxen/netxen_nic_ethtool.c | 1 - drivers/net/netxen/netxen_nic_hdr.h | 2 -- drivers/net/tokenring/lanstreamer.c | 1 - drivers/net/tokenring/lanstreamer.h | 2 -- drivers/net/wireless/b43legacy/main.c | 1 - drivers/net/wireless/iwlwifi/iwl-3945-led.c | 1 - drivers/net/wireless/iwlwifi/iwl-led.c | 1 - drivers/net/wireless/iwlwifi/iwl-rfkill.c | 1 - drivers/rtc/rtc-max6902.c | 2 -- drivers/rtc/rtc-r9701.c | 1 - drivers/s390/net/ctcm_mpc.c | 1 - drivers/scsi/dpt/dpti_i2o.h | 1 - drivers/scsi/ips.c | 1 - drivers/scsi/ips.h | 1 - drivers/scsi/lpfc/lpfc_debugfs.c | 1 - drivers/scsi/nsp32.c | 1 - drivers/scsi/nsp32.h | 1 - drivers/scsi/pcmcia/nsp_cs.c | 1 - drivers/scsi/qla2xxx/qla_mid.c | 1 - drivers/usb/atm/ueagle-atm.c | 1 - drivers/usb/gadget/amd5536udc.c | 1 - drivers/usb/gadget/s3c2410_udc.c | 1 - drivers/usb/misc/iowarrior.c | 1 - drivers/usb/serial/garmin_gps.c | 2 -- drivers/video/arkfb.c | 1 - drivers/video/s3fb.c | 1 - drivers/video/vermilion/vermilion.h | 1 - drivers/video/vt8623fb.c | 1 - drivers/video/xilinxfb.c | 1 - 49 files changed, 53 deletions(-) (limited to 'drivers') diff --git a/drivers/atm/adummy.c b/drivers/atm/adummy.c index 2ebd07f..5effec6 100644 --- a/drivers/atm/adummy.c +++ b/drivers/atm/adummy.c @@ -3,7 +3,6 @@ */ #include -#include #include #include #include diff --git a/drivers/char/xilinx_hwicap/buffer_icap.h b/drivers/char/xilinx_hwicap/buffer_icap.h index c5b1840..8b0252b 100644 --- a/drivers/char/xilinx_hwicap/buffer_icap.h +++ b/drivers/char/xilinx_hwicap/buffer_icap.h @@ -38,7 +38,6 @@ #include #include -#include #include #include diff --git a/drivers/char/xilinx_hwicap/fifo_icap.h b/drivers/char/xilinx_hwicap/fifo_icap.h index ffabd3b..62bda45 100644 --- a/drivers/char/xilinx_hwicap/fifo_icap.h +++ b/drivers/char/xilinx_hwicap/fifo_icap.h @@ -38,7 +38,6 @@ #include #include -#include #include #include diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h index 1f9c8b0..24d0d9b 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h @@ -38,7 +38,6 @@ #include #include -#include #include #include diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index b27b13c..4b55ec6 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h @@ -34,7 +34,6 @@ #include #include #include -#include #define EDAC_MC_LABEL_LEN 31 #define EDAC_DEVICE_NAME_LEN 31 diff --git a/drivers/i2c/busses/i2c-at91.c b/drivers/i2c/busses/i2c-at91.c index c1adcdb..9efb021 100644 --- a/drivers/i2c/busses/i2c-at91.c +++ b/drivers/i2c/busses/i2c-at91.c @@ -14,7 +14,6 @@ */ #include -#include #include #include #include diff --git a/drivers/infiniband/hw/ehca/ehca_tools.h b/drivers/infiniband/hw/ehca/ehca_tools.h index ec950bf..21f7d06 100644 --- a/drivers/infiniband/hw/ehca/ehca_tools.h +++ b/drivers/infiniband/hw/ehca/ehca_tools.h @@ -54,7 +54,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index 23faba9..8bb5170 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c @@ -31,7 +31,6 @@ * SOFTWARE. */ -#include #include #include #include diff --git a/drivers/infiniband/hw/nes/nes.h b/drivers/infiniband/hw/nes/nes.h index 39bd897..8eb7ae9 100644 --- a/drivers/infiniband/hw/nes/nes.h +++ b/drivers/infiniband/hw/nes/nes.h @@ -43,7 +43,6 @@ #include #include #include -#include #include #include diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 63462ec..26ff621 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -33,7 +33,6 @@ #include #include #include -#include #include "iscsi_iser.h" diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 54ed8e2..6f227d3 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -29,7 +29,6 @@ */ #include -#include #include #include diff --git a/drivers/input/touchscreen/mainstone-wm97xx.c b/drivers/input/touchscreen/mainstone-wm97xx.c index 283f93a..37a555f 100644 --- a/drivers/input/touchscreen/mainstone-wm97xx.c +++ b/drivers/input/touchscreen/mainstone-wm97xx.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include diff --git a/drivers/mfd/asic3.c b/drivers/mfd/asic3.c index c6408a6..bc2a807 100644 --- a/drivers/mfd/asic3.c +++ b/drivers/mfd/asic3.c @@ -16,7 +16,6 @@ * */ -#include #include #include #include diff --git a/drivers/misc/eeprom_93cx6.c b/drivers/misc/eeprom_93cx6.c index ea55654..15b1780 100644 --- a/drivers/misc/eeprom_93cx6.c +++ b/drivers/misc/eeprom_93cx6.c @@ -26,7 +26,6 @@ #include #include -#include #include #include diff --git a/drivers/mtd/maps/amd76xrom.c b/drivers/mtd/maps/amd76xrom.c index 948b86f3..d1eec7d 100644 --- a/drivers/mtd/maps/amd76xrom.c +++ b/drivers/mtd/maps/amd76xrom.c @@ -6,7 +6,6 @@ #include #include -#include #include #include #include diff --git a/drivers/mtd/maps/ck804xrom.c b/drivers/mtd/maps/ck804xrom.c index effaf7cd..1a6feb4 100644 --- a/drivers/mtd/maps/ck804xrom.c +++ b/drivers/mtd/maps/ck804xrom.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include diff --git a/drivers/mtd/maps/esb2rom.c b/drivers/mtd/maps/esb2rom.c index aa64a47..bbbcdd4 100644 --- a/drivers/mtd/maps/esb2rom.c +++ b/drivers/mtd/maps/esb2rom.c @@ -12,7 +12,6 @@ #include #include -#include #include #include #include diff --git a/drivers/mtd/nand/au1550nd.c b/drivers/mtd/nand/au1550nd.c index 761946e..92c334f 100644 --- a/drivers/mtd/nand/au1550nd.c +++ b/drivers/mtd/nand/au1550nd.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 5d76cd0..54cd89c 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -56,7 +56,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/netxen/netxen_nic.h b/drivers/net/netxen/netxen_nic.h index ab871df..244ab49 100644 --- a/drivers/net/netxen/netxen_nic.h +++ b/drivers/net/netxen/netxen_nic.h @@ -45,7 +45,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/netxen/netxen_nic_ethtool.c b/drivers/net/netxen/netxen_nic_ethtool.c index 4ad3e08..b974ca0 100644 --- a/drivers/net/netxen/netxen_nic_ethtool.c +++ b/drivers/net/netxen/netxen_nic_ethtool.c @@ -38,7 +38,6 @@ #include #include #include -#include #include "netxen_nic.h" #include "netxen_nic_hw.h" diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h index e8e8d73..e80f9e3 100644 --- a/drivers/net/netxen/netxen_nic_hdr.h +++ b/drivers/net/netxen/netxen_nic_hdr.h @@ -32,8 +32,6 @@ #include #include -#include - #include #include #include diff --git a/drivers/net/tokenring/lanstreamer.c b/drivers/net/tokenring/lanstreamer.c index 47d84cd..59d1673 100644 --- a/drivers/net/tokenring/lanstreamer.c +++ b/drivers/net/tokenring/lanstreamer.c @@ -119,7 +119,6 @@ #include #include #include -#include #include #include diff --git a/drivers/net/tokenring/lanstreamer.h b/drivers/net/tokenring/lanstreamer.h index e7bb349..13ccee6 100644 --- a/drivers/net/tokenring/lanstreamer.h +++ b/drivers/net/tokenring/lanstreamer.h @@ -60,8 +60,6 @@ * */ -#include - /* MAX_INTR - the maximum number of times we can loop * inside the interrupt function before returning * control to the OS (maximum value is 256) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 2541c81..1cb77db 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c index d333696..705c65b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945-led.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index cb11c4a..4eee1b1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c @@ -27,7 +27,6 @@ #include #include -#include #include #include #include diff --git a/drivers/net/wireless/iwlwifi/iwl-rfkill.c b/drivers/net/wireless/iwlwifi/iwl-rfkill.c index e5e5846..5d64229 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rfkill.c +++ b/drivers/net/wireless/iwlwifi/iwl-rfkill.c @@ -27,7 +27,6 @@ *****************************************************************************/ #include #include -#include #include #include diff --git a/drivers/rtc/rtc-max6902.c b/drivers/rtc/rtc-max6902.c index 12f0310..78b2551 100644 --- a/drivers/rtc/rtc-max6902.c +++ b/drivers/rtc/rtc-max6902.c @@ -20,8 +20,6 @@ */ #include -#include - #include #include #include diff --git a/drivers/rtc/rtc-r9701.c b/drivers/rtc/rtc-r9701.c index b35f9bf..395985b 100644 --- a/drivers/rtc/rtc-r9701.c +++ b/drivers/rtc/rtc-r9701.c @@ -14,7 +14,6 @@ */ #include -#include #include #include #include diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 49ae1cd..2de1e2f 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c @@ -19,7 +19,6 @@ #undef DEBUGDATA #undef DEBUGCCW -#include #include #include #include diff --git a/drivers/scsi/dpt/dpti_i2o.h b/drivers/scsi/dpt/dpti_i2o.h index 19406ce..179ad77 100644 --- a/drivers/scsi/dpt/dpti_i2o.h +++ b/drivers/scsi/dpt/dpti_i2o.h @@ -21,7 +21,6 @@ #include -#include #include #include diff --git a/drivers/scsi/ips.c b/drivers/scsi/ips.c index 7c615c7..bc9e6dd 100644 --- a/drivers/scsi/ips.c +++ b/drivers/scsi/ips.c @@ -165,7 +165,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/scsi/ips.h b/drivers/scsi/ips.h index e0657b6..4e49fbc 100644 --- a/drivers/scsi/ips.h +++ b/drivers/scsi/ips.h @@ -50,7 +50,6 @@ #ifndef _IPS_H_ #define _IPS_H_ -#include #include #include #include diff --git a/drivers/scsi/lpfc/lpfc_debugfs.c b/drivers/scsi/lpfc/lpfc_debugfs.c index 90272e6..094b47e 100644 --- a/drivers/scsi/lpfc/lpfc_debugfs.c +++ b/drivers/scsi/lpfc/lpfc_debugfs.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include diff --git a/drivers/scsi/nsp32.c b/drivers/scsi/nsp32.c index edf9fdb..22052bb 100644 --- a/drivers/scsi/nsp32.c +++ b/drivers/scsi/nsp32.c @@ -23,7 +23,6 @@ * 1.2: PowerPC (big endian) support. */ -#include #include #include #include diff --git a/drivers/scsi/nsp32.h b/drivers/scsi/nsp32.h index 6715ecb..9565acf 100644 --- a/drivers/scsi/nsp32.h +++ b/drivers/scsi/nsp32.h @@ -16,7 +16,6 @@ #ifndef _NSP32_H #define _NSP32_H -#include //#define NSP32_DEBUG 9 /* diff --git a/drivers/scsi/pcmcia/nsp_cs.c b/drivers/scsi/pcmcia/nsp_cs.c index a221b6e..24e6cb83 100644 --- a/drivers/scsi/pcmcia/nsp_cs.c +++ b/drivers/scsi/pcmcia/nsp_cs.c @@ -25,7 +25,6 @@ ***********************************************************************/ -#include #include #include #include diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c index 50baf6a..93560cd 100644 --- a/drivers/scsi/qla2xxx/qla_mid.c +++ b/drivers/scsi/qla2xxx/qla_mid.c @@ -6,7 +6,6 @@ */ #include "qla_def.h" -#include #include #include #include diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c index cb01b51..b6483dd 100644 --- a/drivers/usb/atm/ueagle-atm.c +++ b/drivers/usb/atm/ueagle-atm.c @@ -64,7 +64,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index 1500e1b..abf8192 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c @@ -44,7 +44,6 @@ #include #include #include -#include #include #include #include diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index 5388073..29d13eb 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c @@ -35,7 +35,6 @@ #include #include #include -#include #include #include diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c index e6ca997..a4ef77e 100644 --- a/drivers/usb/misc/iowarrior.c +++ b/drivers/usb/misc/iowarrior.c @@ -19,7 +19,6 @@ #include #include #include -#include #include /* Version Information */ diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 2e663f1..d953820 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c @@ -38,8 +38,6 @@ #include #include -#include - /* the mode to be set when the port ist opened */ static int initial_mode = 1; diff --git a/drivers/video/arkfb.c b/drivers/video/arkfb.c index 4bd569e..314d186 100644 --- a/drivers/video/arkfb.c +++ b/drivers/video/arkfb.c @@ -11,7 +11,6 @@ * Code is based on s3fb */ -#include #include #include #include diff --git a/drivers/video/s3fb.c b/drivers/video/s3fb.c index 8361bd0e..4dcec48 100644 --- a/drivers/video/s3fb.c +++ b/drivers/video/s3fb.c @@ -11,7 +11,6 @@ * which is based on the code of neofb. */ -#include #include #include #include diff --git a/drivers/video/vermilion/vermilion.h b/drivers/video/vermilion/vermilion.h index c4aba59..7491abf 100644 --- a/drivers/video/vermilion/vermilion.h +++ b/drivers/video/vermilion/vermilion.h @@ -30,7 +30,6 @@ #define _VERMILION_H_ #include -#include #include #include #include diff --git a/drivers/video/vt8623fb.c b/drivers/video/vt8623fb.c index 34aae7a..3df17dc 100644 --- a/drivers/video/vt8623fb.c +++ b/drivers/video/vt8623fb.c @@ -12,7 +12,6 @@ * (http://davesdomain.org.uk/viafb/) */ -#include #include #include #include diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 7b3a842..5da3d24 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include #include -- cgit v1.1 From 819ddcafb33136f2ba18018a22edcf857f640528 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 02:45:32 +0200 Subject: mv643xx_eth: fix NAPI 'rotting packet' issue When a receive interrupt occurs, mv643xx_eth would first process the receive descriptors and then ACK the receive interrupt, instead of the other way round. This would leave a small race window between processing the last receive descriptor and clearing the receive interrupt status in which a new packet could come in, which would then 'rot' in the receive ring until the next receive interrupt would come in. Fix this by ACKing (clearing) the receive interrupt condition before processing the receive descriptors. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 46819af..af279f2 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -650,8 +650,6 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) if (rx < budget) { netif_rx_complete(mp->dev, napi); - wrl(mp, INT_CAUSE(mp->port_num), 0); - wrl(mp, INT_CAUSE_EXT(mp->port_num), 0); wrl(mp, INT_MASK(mp->port_num), INT_TX_END | INT_RX | INT_EXT); } @@ -1796,6 +1794,7 @@ static irqreturn_t mv643xx_eth_irq(int irq, void *dev_id) */ #ifdef MV643XX_ETH_NAPI if (int_cause & INT_RX) { + wrl(mp, INT_CAUSE(mp->port_num), ~(int_cause & INT_RX)); wrl(mp, INT_MASK(mp->port_num), 0x00000000); rdl(mp, INT_MASK(mp->port_num)); -- cgit v1.1 From 92c70f27d2a78873c940e77c7f075cd8e2e60a2d Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 01:59:05 +0200 Subject: mv643xx_eth: fix double add_timer() on the receive oom timer Commit 12e4ab79cd828563dc090d2117dc8626b344bc8f ("mv643xx_eth: be more agressive about RX refill") changed the condition for the receive out-of-memory timer to be scheduled from "the receive ring is empty" to "the receive ring is not full". This can lead to a situation where the receive out-of-memory timer is pending because a previous rxq_refill() didn't manage to refill the receive ring entirely as a result of being out of memory, and rxq_refill() is then called again as a side effect of a packet receive interrupt, and that rxq_refill() call then again does not succeed to refill the entire receive ring with fresh empty skbuffs because we are still out of memory, and then tries to call add_timer() on the already scheduled out-of-memory timer. This patch fixes this issue by changing the add_timer() call in rxq_refill() to a mod_timer() call. If the OOM timer was not already scheduled, this will behave as before, whereas if it was already scheduled, this patch will push back its firing time a bit, which is safe because we've (unsuccessfully) attempted to refill the receive ring just before we do this. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index af279f2..8a91d79 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -509,10 +509,8 @@ static void rxq_refill(struct rx_queue *rxq) skb_reserve(skb, 2); } - if (rxq->rx_desc_count != rxq->rx_ring_size) { - rxq->rx_oom.expires = jiffies + (HZ / 10); - add_timer(&rxq->rx_oom); - } + if (rxq->rx_desc_count != rxq->rx_ring_size) + mod_timer(&rxq->rx_oom, jiffies + (HZ / 10)); spin_unlock_irqrestore(&mp->lock, flags); } -- cgit v1.1 From 8e0b1bf6ac6c4c6dd985e586cd765aede4678bba Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 02:30:42 +0200 Subject: mv643xx_eth: fix inconsistent lock semantics Nicolas Pitre noted that mv643xx_eth_poll was incorrectly using non-IRQ-safe locks while checking whether to wake up the netdevice's transmit queue. Convert the locking to *_irq() variants, since we are running from softirq context where interrupts are enabled. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 8a91d79..30e6d4b8 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -634,9 +634,9 @@ static int mv643xx_eth_poll(struct napi_struct *napi, int budget) txq_reclaim(mp->txq + i, 0); if (netif_carrier_ok(mp->dev)) { - spin_lock(&mp->lock); + spin_lock_irq(&mp->lock); __txq_maybe_wake(mp->txq + mp->txq_primary); - spin_unlock(&mp->lock); + spin_unlock_irq(&mp->lock); } } #endif -- cgit v1.1 From 9e1f37724265725ad4c14fc2ef60a162dc13ac64 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 02:33:47 +0200 Subject: mv643xx_eth: fix NULL pointer dereference in rxq_process() When we are low on memory, the assumption that every descriptor in the receive ring will have an skbuff associated with it does not hold. rxq_process() was assuming that if the receive descriptor it is working on is not owned by the hardware, it can safely be processed and handed to the networking stack. But a descriptor in the receive ring not being owned by the hardware can also happen when we are low on memory and did not manage to refill the receive ring fully. This patch changes rxq_process()'s bailout condition from "the first receive descriptor to be processed is owned by the hardware" to "the first receive descriptor to be processed is owned by the hardware OR the number of valid receive descriptors in the ring is zero". Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index 30e6d4b8..e33dfc0 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -527,7 +527,7 @@ static int rxq_process(struct rx_queue *rxq, int budget) int rx; rx = 0; - while (rx < budget) { + while (rx < budget && rxq->rx_desc_count) { struct rx_desc *rx_desc; unsigned int cmd_sts; struct sk_buff *skb; -- cgit v1.1 From abe787170bb3888c5e587e8e986711fe32ddf2f9 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 03:00:20 +0200 Subject: mv643xx_eth: enforce multiple-of-8-bytes receive buffer size restriction The mv643xx_eth hardware ignores the lower three bits of the buffer size field in receive descriptors, causing the reception of full-sized packets to fail at some MTUs. Fix this by rounding the size of allocated receive buffers up to a multiple of eight bytes. While we are at it, add a bit of extra space to each receive buffer so that we can handle multiple vlan tags on ingress. Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index e33dfc0..a02a5f4 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -474,11 +474,19 @@ static void rxq_refill(struct rx_queue *rxq) /* * Reserve 2+14 bytes for an ethernet header (the * hardware automatically prepends 2 bytes of dummy - * data to each received packet), 4 bytes for a VLAN - * header, and 4 bytes for the trailing FCS -- 24 - * bytes total. + * data to each received packet), 16 bytes for up to + * four VLAN tags, and 4 bytes for the trailing FCS + * -- 36 bytes total. */ - skb_size = mp->dev->mtu + 24; + skb_size = mp->dev->mtu + 36; + + /* + * Make sure that the skb size is a multiple of 8 + * bytes, as the lower three bits of the receive + * descriptor's buffer size field are ignored by + * the hardware. + */ + skb_size = (skb_size + 7) & ~7; skb = dev_alloc_skb(skb_size + dma_get_cache_alignment() - 1); if (skb == NULL) @@ -552,7 +560,7 @@ static int rxq_process(struct rx_queue *rxq, int budget) spin_unlock_irqrestore(&mp->lock, flags); dma_unmap_single(NULL, rx_desc->buf_ptr + 2, - mp->dev->mtu + 24, DMA_FROM_DEVICE); + rx_desc->buf_size, DMA_FROM_DEVICE); rxq->rx_desc_count--; rx++; -- cgit v1.1 From 83097aca8567a0bd593534853b71fe0fa9a75d69 Mon Sep 17 00:00:00 2001 From: Arjan van de Ven Date: Sat, 23 Aug 2008 21:45:21 -0700 Subject: Fix oops in acer_wmi driver (acer_wmi_init) The acer_wmi driver does a DMI scan for quirks, and then sets flags into the "interface" datastructure for some cases. However, the quirks happen real early before "interface" is per se initialized from NULL. The patch below 1) adds a NULL pointer check and 2) (re)runs the quirks at the end, when "interface" has it's final value. Reported-by: kerneloops.org Acked-by: Carlos Corbacho CC: stable@vger.kernel.org Signed-off-by: Arjan van de Ven Signed-off-by: Linus Torvalds --- drivers/misc/acer-wmi.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'drivers') diff --git a/drivers/misc/acer-wmi.c b/drivers/misc/acer-wmi.c index b2d9878..c6c77a5 100644 --- a/drivers/misc/acer-wmi.c +++ b/drivers/misc/acer-wmi.c @@ -192,6 +192,9 @@ static struct quirk_entry *quirks; static void set_quirks(void) { + if (!interface) + return; + if (quirks->mailled) interface->capability |= ACER_CAP_MAILLED; @@ -1237,6 +1240,8 @@ static int __init acer_wmi_init(void) return -ENODEV; } + set_quirks(); + if (platform_driver_register(&acer_platform_driver)) { printk(ACER_ERR "Unable to register platform driver.\n"); goto error_platform_register; -- cgit v1.1 From c4560318cf8fed91e3146a3c1247e11542d91d91 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sun, 24 Aug 2008 07:33:05 +0200 Subject: mv643xx_eth: bump version to 1.3 Signed-off-by: Lennert Buytenhek --- drivers/net/mv643xx_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/mv643xx_eth.c b/drivers/net/mv643xx_eth.c index a02a5f4..0a18b9e 100644 --- a/drivers/net/mv643xx_eth.c +++ b/drivers/net/mv643xx_eth.c @@ -55,7 +55,7 @@ #include static char mv643xx_eth_driver_name[] = "mv643xx_eth"; -static char mv643xx_eth_driver_version[] = "1.2"; +static char mv643xx_eth_driver_version[] = "1.3"; #define MV643XX_ETH_CHECKSUM_OFFLOAD_TX #define MV643XX_ETH_NAPI -- cgit v1.1 From 54f961a628b737f66710eca0b0d95346645dd33e Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Wed, 13 Aug 2008 09:46:31 +1000 Subject: radeon: fix some hard lockups on r3/4/500s This patch should fix hard lockup and convert them in softlockup (ie you can ssh the box but the gpu is busted and we are waiting in loop for it to come back to reason). Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300_cmdbuf.c | 117 +++++++++++++++++++++++++++++------ drivers/gpu/drm/radeon/r300_reg.h | 5 +- drivers/gpu/drm/radeon/radeon_cp.c | 38 ++++++------ drivers/gpu/drm/radeon/radeon_drv.h | 19 +++--- 4 files changed, 130 insertions(+), 49 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index 702df45..4b3bd63 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -136,6 +136,18 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, ADVANCE_RING(); } + /* flus cache and wait idle clean after cliprect change */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(R300_RB3D_DC_FLUSH); + ADVANCE_RING(); + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(RADEON_WAIT_3D_IDLECLEAN); + ADVANCE_RING(); + /* set flush flag */ + dev_priv->track_flush |= RADEON_FLUSH_EMITED; + return 0; } @@ -166,13 +178,13 @@ void r300_init_reg_flags(struct drm_device *dev) ADD_RANGE(0x21DC, 1); ADD_RANGE(R300_VAP_UNKNOWN_221C, 1); ADD_RANGE(R300_VAP_CLIP_X_0, 4); - ADD_RANGE(R300_VAP_PVS_WAITIDLE, 1); + ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1); ADD_RANGE(R300_VAP_UNKNOWN_2288, 1); ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2); ADD_RANGE(R300_VAP_PVS_CNTL_1, 3); ADD_RANGE(R300_GB_ENABLE, 1); ADD_RANGE(R300_GB_MSPOS0, 5); - ADD_RANGE(R300_TX_CNTL, 1); + ADD_RANGE(R300_TX_INVALTAGS, 1); ADD_RANGE(R300_TX_ENABLE, 1); ADD_RANGE(0x4200, 4); ADD_RANGE(0x4214, 1); @@ -388,15 +400,28 @@ static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv, if (sz * 16 > cmdbuf->bufsz) return -EINVAL; - BEGIN_RING(5 + sz * 4); - /* Wait for VAP to come to senses.. */ - /* there is no need to emit it multiple times, (only once before VAP is programmed, - but this optimization is for later */ - OUT_RING_REG(R300_VAP_PVS_WAITIDLE, 0); + /* VAP is very sensitive so we purge cache before we program it + * and we also flush its state before & after */ + BEGIN_RING(6); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(R300_RB3D_DC_FLUSH); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(RADEON_WAIT_3D_IDLECLEAN); + OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0)); + OUT_RING(0); + ADVANCE_RING(); + /* set flush flag */ + dev_priv->track_flush |= RADEON_FLUSH_EMITED; + + BEGIN_RING(3 + sz * 4); OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr); OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1)); OUT_RING_TABLE((int *)cmdbuf->buf, sz * 4); + ADVANCE_RING(); + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0)); + OUT_RING(0); ADVANCE_RING(); cmdbuf->buf += sz * 16; @@ -424,6 +449,15 @@ static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv, OUT_RING_TABLE((int *)cmdbuf->buf, 8); ADVANCE_RING(); + BEGIN_RING(4); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(R300_RB3D_DC_FLUSH); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(RADEON_WAIT_3D_IDLECLEAN); + ADVANCE_RING(); + /* set flush flag */ + dev_priv->track_flush |= RADEON_FLUSH_EMITED; + cmdbuf->buf += 8 * 4; cmdbuf->bufsz -= 8 * 4; @@ -613,11 +647,19 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, case RADEON_CNTL_BITBLT_MULTI: return r300_emit_bitblt_multi(dev_priv, cmdbuf); - case RADEON_CP_INDX_BUFFER: /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ + case RADEON_CP_INDX_BUFFER: + /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ return r300_emit_indx_buffer(dev_priv, cmdbuf); - case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ - case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ - case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ + case RADEON_CP_3D_DRAW_IMMD_2: + /* triggers drawing using in-packet vertex data */ + case RADEON_CP_3D_DRAW_VBUF_2: + /* triggers drawing of vertex buffers setup elsewhere */ + case RADEON_CP_3D_DRAW_INDX_2: + /* triggers drawing using indices to vertex buffer */ + /* whenever we send vertex we clear flush & purge */ + dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | + RADEON_PURGE_EMITED); + break; case RADEON_WAIT_FOR_IDLE: case RADEON_CP_NOP: /* these packets are safe */ @@ -713,17 +755,53 @@ static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv, */ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv) { + uint32_t cache_z, cache_3d, cache_2d; RING_LOCALS; + + cache_z = R300_ZC_FLUSH; + cache_2d = R300_RB2D_DC_FLUSH; + cache_3d = R300_RB3D_DC_FLUSH; + if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) { + /* we can purge, primitive where draw since last purge */ + cache_z |= R300_ZC_FREE; + cache_2d |= R300_RB2D_DC_FREE; + cache_3d |= R300_RB3D_DC_FREE; + } - BEGIN_RING(6); - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(R300_RB3D_DSTCACHE_UNKNOWN_0A); + /* flush & purge zbuffer */ + BEGIN_RING(2); OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); - OUT_RING(R300_ZB_ZCACHE_CTLSTAT_ZC_FLUSH_FLUSH_AND_FREE| - R300_ZB_ZCACHE_CTLSTAT_ZC_FREE_FREE); - OUT_RING(CP_PACKET3(RADEON_CP_NOP, 0)); - OUT_RING(0x0); + OUT_RING(cache_z); + ADVANCE_RING(); + /* flush & purge 3d */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); + OUT_RING(cache_3d); + ADVANCE_RING(); + /* flush & purge texture */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0)); + OUT_RING(0); + ADVANCE_RING(); + /* FIXME: is this one really needed ? */ + BEGIN_RING(2); + OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0)); + OUT_RING(0); + ADVANCE_RING(); + BEGIN_RING(2); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(RADEON_WAIT_3D_IDLECLEAN); + ADVANCE_RING(); + /* flush & purge 2d through E2 as RB2D will trigger lockup */ + BEGIN_RING(4); + OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0)); + OUT_RING(cache_2d); + OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); + OUT_RING(RADEON_WAIT_2D_IDLECLEAN | + RADEON_WAIT_HOST_IDLECLEAN); ADVANCE_RING(); + /* set flush & purge flags */ + dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED; } /** @@ -905,8 +983,7 @@ int r300_do_cp_cmdbuf(struct drm_device *dev, DRM_DEBUG("\n"); - /* See the comment above r300_emit_begin3d for why this call must be here, - * and what the cleanup gotos are for. */ + /* pacify */ r300_pacify(dev_priv); if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) { diff --git a/drivers/gpu/drm/radeon/r300_reg.h b/drivers/gpu/drm/radeon/r300_reg.h index a6802f2..ee6f811 100644 --- a/drivers/gpu/drm/radeon/r300_reg.h +++ b/drivers/gpu/drm/radeon/r300_reg.h @@ -317,7 +317,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Therefore, I suspect writing zero to 0x2284 synchronizes the engine and * avoids bugs caused by still running shaders reading bad data from memory. */ -#define R300_VAP_PVS_WAITIDLE 0x2284 /* GUESS */ +#define R300_VAP_PVS_STATE_FLUSH_REG 0x2284 /* Absolutely no clue what this register is about. */ #define R300_VAP_UNKNOWN_2288 0x2288 @@ -513,7 +513,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. /* gap */ /* Zero to flush caches. */ -#define R300_TX_CNTL 0x4100 +#define R300_TX_INVALTAGS 0x4100 #define R300_TX_FLUSH 0x0 /* The upper enable bits are guessed, based on fglrx reported limits. */ @@ -1362,6 +1362,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. #define R300_RB3D_COLORPITCH2 0x4E40 /* GUESS */ #define R300_RB3D_COLORPITCH3 0x4E44 /* GUESS */ +#define R300_RB3D_AARESOLVE_CTL 0x4E88 /* gap */ /* Guess by Vladimir. diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index f0de81a..3331f88 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -40,6 +40,7 @@ #define RADEON_FIFO_DEBUG 0 static int radeon_do_cleanup_cp(struct drm_device * dev); +static void radeon_do_cp_start(drm_radeon_private_t * dev_priv); static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) { @@ -198,23 +199,8 @@ static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv) DRM_UDELAY(1); } } else { - /* 3D */ - tmp = RADEON_READ(R300_RB3D_DSTCACHE_CTLSTAT); - tmp |= RADEON_RB3D_DC_FLUSH_ALL; - RADEON_WRITE(R300_RB3D_DSTCACHE_CTLSTAT, tmp); - - /* 2D */ - tmp = RADEON_READ(R300_DSTCACHE_CTLSTAT); - tmp |= RADEON_RB3D_DC_FLUSH_ALL; - RADEON_WRITE(R300_DSTCACHE_CTLSTAT, tmp); - - for (i = 0; i < dev_priv->usec_timeout; i++) { - if (!(RADEON_READ(R300_DSTCACHE_CTLSTAT) - & RADEON_RB3D_DC_BUSY)) { - return 0; - } - DRM_UDELAY(1); - } + /* don't flush or purge cache here or lockup */ + return 0; } #if RADEON_FIFO_DEBUG @@ -237,6 +223,9 @@ static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries) return 0; DRM_UDELAY(1); } + DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n", + RADEON_READ(RADEON_RBBM_STATUS), + RADEON_READ(R300_VAP_CNTL_STATUS)); #if RADEON_FIFO_DEBUG DRM_ERROR("failed!\n"); @@ -263,6 +252,9 @@ static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv) } DRM_UDELAY(1); } + DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n", + RADEON_READ(RADEON_RBBM_STATUS), + RADEON_READ(R300_VAP_CNTL_STATUS)); #if RADEON_FIFO_DEBUG DRM_ERROR("failed!\n"); @@ -443,14 +435,20 @@ static void radeon_do_cp_start(drm_radeon_private_t * dev_priv) dev_priv->cp_running = 1; - BEGIN_RING(6); - + BEGIN_RING(8); + /* isync can only be written through cp on r5xx write it here */ + OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0)); + OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D | + RADEON_ISYNC_ANY3D_IDLE2D | + RADEON_ISYNC_WAIT_IDLEGUI | + RADEON_ISYNC_CPSCRATCH_IDLEGUI); RADEON_PURGE_CACHE(); RADEON_PURGE_ZCACHE(); RADEON_WAIT_UNTIL_IDLE(); - ADVANCE_RING(); COMMIT_RING(); + + dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED; } /* Reset the Command Processor. This will not flush any pending diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 3f0eca9..0993816 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -220,6 +220,9 @@ struct radeon_virt_surface { struct drm_file *file_priv; }; +#define RADEON_FLUSH_EMITED (1 < 0) +#define RADEON_PURGE_EMITED (1 < 1) + typedef struct drm_radeon_private { drm_radeon_ring_buffer_t ring; drm_radeon_sarea_t *sarea_priv; @@ -311,6 +314,7 @@ typedef struct drm_radeon_private { unsigned long fb_aper_offset; int num_gb_pipes; + int track_flush; } drm_radeon_private_t; typedef struct drm_radeon_buf_priv { @@ -693,7 +697,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev, #define R300_ZB_ZCACHE_CTLSTAT 0x4f18 # define R300_ZC_FLUSH (1 << 0) # define R300_ZC_FREE (1 << 1) -# define R300_ZC_FLUSH_ALL 0x3 # define R300_ZC_BUSY (1 << 31) #define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c # define RADEON_RB3D_DC_FLUSH (3 << 0) @@ -701,6 +704,8 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev, # define RADEON_RB3D_DC_FLUSH_ALL 0xf # define RADEON_RB3D_DC_BUSY (1 << 31) #define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c +# define R300_RB3D_DC_FLUSH (2 << 0) +# define R300_RB3D_DC_FREE (2 << 2) # define R300_RB3D_DC_FINISH (1 << 4) #define RADEON_RB3D_ZSTENCILCNTL 0x1c2c # define RADEON_Z_TEST_MASK (7 << 4) @@ -1246,17 +1251,17 @@ do { \ OUT_RING(RADEON_RB3D_DC_FLUSH); \ } else { \ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_DC_FLUSH); \ + OUT_RING(R300_RB3D_DC_FLUSH); \ } \ } while (0) #define RADEON_PURGE_CACHE() do { \ if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \ + OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE); \ } else { \ OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_DC_FLUSH_ALL); \ + OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); \ } \ } while (0) @@ -1273,10 +1278,10 @@ do { \ #define RADEON_PURGE_ZCACHE() do { \ if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_ZC_FLUSH_ALL); \ + OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE); \ } else { \ - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(R300_ZC_FLUSH_ALL); \ + OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); \ + OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE); \ } \ } while (0) -- cgit v1.1 From e2898c5fdd91f54c9c84fbf7d32edb8e4dfda574 Mon Sep 17 00:00:00 2001 From: Nicolai Haehnle Date: Wed, 13 Aug 2008 09:49:15 +1000 Subject: drm/radeon: r300_cmdbuf: Always emit INDX_BUFFER immediately after DRAW_INDEX DRAW_INDEX writes a vertex count to VAP_VF_CNTL. Docs say that behaviour is undefined (i.e. lockups happen) when this write is not followed by the right number of vertex indices. Thus we used to do the wrong thing when drawing across many cliprects was necessary, because we emitted a sequence DRAW_INDEX, DRAW_INDEX, INDX_BUFFER, INDX_BUFFER instead of DRAW_INDEX, INDX_BUFFER, DRAW_INDEX, INDX_BUFFER The latter is what we're doing now and which ought to be correct. Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300_cmdbuf.c | 80 ++++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index 4b3bd63..b1fdfc6 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -577,22 +577,23 @@ static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, return 0; } -static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf) +static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv, + drm_radeon_kcmd_buffer_t *cmdbuf) { - u32 *cmd = (u32 *) cmdbuf->buf; - int count, ret; + u32 *cmd; + int count; + int expected_count; RING_LOCALS; - count=(cmd[0]>>16) & 0x3fff; + cmd = (u32 *) cmdbuf->buf; + count = (cmd[0]>>16) & 0x3fff; + expected_count = cmd[1] >> 16; + if (!(cmd[1] & R300_VAP_VF_CNTL__INDEX_SIZE_32bit)) + expected_count = (expected_count+1)/2; - if ((cmd[1] & 0x8000ffff) != 0x80000810) { - DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); - return -EINVAL; - } - ret = !radeon_check_offset(dev_priv, cmd[2]); - if (ret) { - DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); + if (count && count != expected_count) { + DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n", + count, expected_count); return -EINVAL; } @@ -604,6 +605,50 @@ static __inline__ int r300_emit_indx_buffer(drm_radeon_private_t *dev_priv, cmdbuf->buf += (count+2)*4; cmdbuf->bufsz -= (count+2)*4; + if (!count) { + drm_r300_cmd_header_t header; + + if (cmdbuf->bufsz < 4*4 + sizeof(header)) { + DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n"); + return -EINVAL; + } + + header.u = *(unsigned int *)cmdbuf->buf; + + cmdbuf->buf += sizeof(header); + cmdbuf->bufsz -= sizeof(header); + cmd = (u32 *) cmdbuf->buf; + + if (header.header.cmd_type != R300_CMD_PACKET3 || + header.packet3.packet != R300_CMD_PACKET3_RAW || + cmd[0] != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) { + DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n"); + return -EINVAL; + } + + if ((cmd[1] & 0x8000ffff) != 0x80000810) { + DRM_ERROR("Invalid indx_buffer reg address %08X\n", cmd[1]); + return -EINVAL; + } + if (!radeon_check_offset(dev_priv, cmd[2])) { + DRM_ERROR("Invalid indx_buffer offset is %08X\n", cmd[2]); + return -EINVAL; + } + if (cmd[3] != expected_count) { + DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n", + cmd[3], expected_count); + return -EINVAL; + } + + BEGIN_RING(4); + OUT_RING(cmd[0]); + OUT_RING_TABLE((int *)(cmdbuf->buf + 4), 3); + ADVANCE_RING(); + + cmdbuf->buf += 4*4; + cmdbuf->bufsz -= 4*4; + } + return 0; } @@ -648,18 +693,21 @@ static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, return r300_emit_bitblt_multi(dev_priv, cmdbuf); case RADEON_CP_INDX_BUFFER: - /* DRAW_INDX_2 without INDX_BUFFER seems to lock up the gpu */ - return r300_emit_indx_buffer(dev_priv, cmdbuf); + DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n"); + return -EINVAL; case RADEON_CP_3D_DRAW_IMMD_2: /* triggers drawing using in-packet vertex data */ case RADEON_CP_3D_DRAW_VBUF_2: /* triggers drawing of vertex buffers setup elsewhere */ + dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | + RADEON_PURGE_EMITED); + break; case RADEON_CP_3D_DRAW_INDX_2: /* triggers drawing using indices to vertex buffer */ /* whenever we send vertex we clear flush & purge */ dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED); - break; + return r300_emit_draw_indx_2(dev_priv, cmdbuf); case RADEON_WAIT_FOR_IDLE: case RADEON_CP_NOP: /* these packets are safe */ @@ -757,7 +805,7 @@ static __inline__ void r300_pacify(drm_radeon_private_t *dev_priv) { uint32_t cache_z, cache_3d, cache_2d; RING_LOCALS; - + cache_z = R300_ZC_FLUSH; cache_2d = R300_RB2D_DC_FLUSH; cache_3d = R300_RB3D_DC_FLUSH; -- cgit v1.1 From 649ffc06a62bf487b78440669bdfeb637f1d675b Mon Sep 17 00:00:00 2001 From: Nicolai Haehnle Date: Wed, 13 Aug 2008 09:50:12 +1000 Subject: r300: Fix cliprect emit This makes our handling of cliprects sane. drm_clip_rect always has exclusiv bottom-right corners, but the hardware expects inclusive bottom-right corner so we adjust this here. This complements Michel Daenzer's commit 57aea290e1e0a26d1e74df6cff777eb9f03 to Mesa. See also http://bugs.freedesktop.org/show_bug.cgi?id=16123 Signed-off-by: Dave Airlie --- drivers/gpu/drm/radeon/r300_cmdbuf.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c index b1fdfc6..4b27d9a 100644 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ b/drivers/gpu/drm/radeon/r300_cmdbuf.c @@ -77,6 +77,9 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, return -EFAULT; } + box.x2--; /* Hardware expects inclusive bottom-right corner */ + box.y2--; + if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { box.x1 = (box.x1) & R300_CLIPRECT_MASK; @@ -95,8 +98,8 @@ static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, R300_CLIPRECT_MASK; box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & R300_CLIPRECT_MASK; - } + OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) | (box.y1 << R300_CLIPRECT_Y_SHIFT)); OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) | -- cgit v1.1 From e5b4f19417b75a2d7c1e36934f60a3e836c4337e Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Sun, 24 Aug 2008 17:00:00 +1000 Subject: drm: don't call the vblank tasklet with irqs disabled. If a specific tasklet shares data with irq context, it needs to take a private irq-blocking spinlock within the tasklet itself. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_irq.c | 20 ++++++++++++-------- drivers/gpu/drm/drm_lock.c | 12 +++++------- 2 files changed, 17 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 089c015..53f0e5a 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c @@ -400,27 +400,31 @@ static void drm_locked_tasklet_func(unsigned long data) { struct drm_device *dev = (struct drm_device *)data; unsigned long irqflags; - + void (*tasklet_func)(struct drm_device *); + spin_lock_irqsave(&dev->tasklet_lock, irqflags); + tasklet_func = dev->locked_tasklet_func; + spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); - if (!dev->locked_tasklet_func || + if (!tasklet_func || !drm_lock_take(&dev->lock, DRM_KERNEL_CONTEXT)) { - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); return; } dev->lock.lock_time = jiffies; atomic_inc(&dev->counts[_DRM_STAT_LOCKS]); - dev->locked_tasklet_func(dev); + spin_lock_irqsave(&dev->tasklet_lock, irqflags); + tasklet_func = dev->locked_tasklet_func; + dev->locked_tasklet_func = NULL; + spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); + + if (tasklet_func != NULL) + tasklet_func(dev); drm_lock_free(&dev->lock, DRM_KERNEL_CONTEXT); - - dev->locked_tasklet_func = NULL; - - spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); } /** diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index 0998723..d78e0dc 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -150,6 +150,7 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) { struct drm_lock *lock = data; unsigned long irqflags; + void (*tasklet_func)(struct drm_device *); if (lock->context == DRM_KERNEL_CONTEXT) { DRM_ERROR("Process %d using kernel context %d\n", @@ -158,14 +159,11 @@ int drm_unlock(struct drm_device *dev, void *data, struct drm_file *file_priv) } spin_lock_irqsave(&dev->tasklet_lock, irqflags); - - if (dev->locked_tasklet_func) { - dev->locked_tasklet_func(dev); - - dev->locked_tasklet_func = NULL; - } - + tasklet_func = dev->locked_tasklet_func; + dev->locked_tasklet_func = NULL; spin_unlock_irqrestore(&dev->tasklet_lock, irqflags); + if (tasklet_func != NULL) + tasklet_func(dev); atomic_inc(&dev->counts[_DRM_STAT_UNLOCKS]); -- cgit v1.1 From 3e5fc80a404a24c858468030b63555cccfb3e79c Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sun, 24 Aug 2008 17:02:26 +1000 Subject: drm: don't set the signal blocker on the master process. There is a problem with debugging the X server and gdb crashes in the xkb startup code. This avoids the problem by allowing the master process to get signals. It should be safe as the signal blocker is mainly so that you can Ctrl-Z a 3D application without locking up the whole box. Ctrl-Z the X server isn't something many people do. Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_lock.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/gpu/drm/drm_lock.c b/drivers/gpu/drm/drm_lock.c index d78e0dc..a4caf95 100644 --- a/drivers/gpu/drm/drm_lock.c +++ b/drivers/gpu/drm/drm_lock.c @@ -105,14 +105,19 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv) ret ? "interrupted" : "has lock"); if (ret) return ret; - sigemptyset(&dev->sigmask); - sigaddset(&dev->sigmask, SIGSTOP); - sigaddset(&dev->sigmask, SIGTSTP); - sigaddset(&dev->sigmask, SIGTTIN); - sigaddset(&dev->sigmask, SIGTTOU); - dev->sigdata.context = lock->context; - dev->sigdata.lock = dev->lock.hw_lock; - block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); + /* don't set the block all signals on the master process for now + * really probably not the correct answer but lets us debug xkb + * xserver for now */ + if (!file_priv->master) { + sigemptyset(&dev->sigmask); + sigaddset(&dev->sigmask, SIGSTOP); + sigaddset(&dev->sigmask, SIGTSTP); + sigaddset(&dev->sigmask, SIGTTIN); + sigaddset(&dev->sigmask, SIGTTOU); + dev->sigdata.context = lock->context; + dev->sigdata.lock = dev->lock.hw_lock; + block_all_signals(drm_notifier, &dev->sigdata, &dev->sigmask); + } if (dev->driver->dma_ready && (lock->flags & _DRM_LOCK_READY)) dev->driver->dma_ready(dev); -- cgit v1.1 From 532a6086e35fa3b5761e68af36d4e42a550eba15 Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Mon, 18 Aug 2008 17:15:31 -0500 Subject: virtio_balloon: fix towards_target when deflating balloon Both v and vb->num_pages are u32 and unsigned int respectively. If v is less than vb->num_pages (and it is, when deflating the balloon), the result is a very large 32-bit number. Since we're returning a s64, instead of getting the same negative number we desire, we get a very large positive number. This handles the case where v < vb->num_pages and ensures we get a small, negative, s64 as the result. Rusty: please push this for 2.6.27-rc4. It's probably appropriate for the stable tree too as it will cause an unexpected OOM when ballooning. Signed-off-by: Anthony Liguori Signed-off-by: Rusty Russell (simplified) --- drivers/virtio/virtio_balloon.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c index bfef604..62eab43 100644 --- a/drivers/virtio/virtio_balloon.c +++ b/drivers/virtio/virtio_balloon.c @@ -158,7 +158,7 @@ static inline s64 towards_target(struct virtio_balloon *vb) vb->vdev->config->get(vb->vdev, offsetof(struct virtio_balloon_config, num_pages), &v, sizeof(v)); - return v - vb->num_pages; + return (s64)v - vb->num_pages; } static void update_balloon_size(struct virtio_balloon *vb) -- cgit v1.1 From 37a7c0f3e3e808b8d24f2187a25d2de39e46d822 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 26 Aug 2008 00:19:26 -0500 Subject: stop_machine: wean Xen off stop_machine_run This is the last use of (the deprecated) stop_machine_run in the tree. Signed-off-by: Rusty Russell Acked-by: Jeremy Fitzhardinge --- drivers/xen/manage.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index a5bc91a..d0e87cb 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c @@ -102,7 +102,7 @@ static void do_suspend(void) /* XXX use normal device tree? */ xenbus_suspend(); - err = stop_machine_run(xen_suspend, &cancelled, 0); + err = stop_machine(xen_suspend, &cancelled, &cpumask_of_cpu(0)); if (err) { printk(KERN_ERR "failed to start xen_suspend: %d\n", err); goto out; -- cgit v1.1 From 1dc3e3bcbfe335843ec938bfdddb34d10f4dd278 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 26 Aug 2008 00:19:27 -0500 Subject: lguest: update commentry Signed-off-by: Rusty Russell --- drivers/lguest/lguest_device.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'drivers') diff --git a/drivers/lguest/lguest_device.c b/drivers/lguest/lguest_device.c index 37344aa..a661bbd 100644 --- a/drivers/lguest/lguest_device.c +++ b/drivers/lguest/lguest_device.c @@ -98,6 +98,10 @@ static u32 lg_get_features(struct virtio_device *vdev) return features; } +/* The virtio core takes the features the Host offers, and copies the + * ones supported by the driver into the vdev->features array. Once + * that's all sorted out, this routine is called so we can tell the + * Host which features we understand and accept. */ static void lg_finalize_features(struct virtio_device *vdev) { unsigned int i, bits; @@ -108,6 +112,10 @@ static void lg_finalize_features(struct virtio_device *vdev) /* Give virtio_ring a chance to accept features. */ vring_transport_features(vdev); + /* The vdev->feature array is a Linux bitmask: this isn't the + * same as a the simple array of bits used by lguest devices + * for features. So we do this slow, manual conversion which is + * completely general. */ memset(out_features, 0, desc->feature_len); bits = min_t(unsigned, desc->feature_len, sizeof(vdev->features)) * 8; for (i = 0; i < bits; i++) { -- cgit v1.1 From dbe13d9981e55c60a030d0509acc9a8968b9c5bf Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 25 Aug 2008 18:13:27 +0200 Subject: [S390] dcss: fix build bug. Fix this compile bug: CC drivers/s390/block/dcssblk.o drivers/s390/block/dcssblk.c: In function 'dcssblk_add_store': drivers/s390/block/dcssblk.c:387: error: implicit declaration of function 'dcssblk_get_segment_by_name' drivers/s390/block/dcssblk.c:389: error: label 'release_gd' used but not defined make[1]: *** [drivers/s390/block/dcssblk.o] Error 1 make: *** [drivers/s390/block/] Error 2 Cc: Gerald Schaefer Signed-off-by: Heiko Carstens Signed-off-by: Martin Schwidefsky --- drivers/s390/block/dcssblk.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index db85f1f..711b300 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c @@ -384,9 +384,10 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char * get minor, add to list */ down_write(&dcssblk_devices_sem); - if (dcssblk_get_segment_by_name(local_buf)) { + if (dcssblk_get_device_by_name(local_buf)) { + up_write(&dcssblk_devices_sem); rc = -EEXIST; - goto release_gd; + goto unload_seg; } rc = dcssblk_assign_free_minor(dev_info); if (rc) { -- cgit v1.1 From 2772f9037355a031725987661621290380e58f52 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 25 Aug 2008 15:19:17 -0700 Subject: bnx2x: Rx work check The has Rx work check was wrong: when the FW was at the end of the page, the driver was already at the beginning of the next page. Since the check only validated that both driver and FW are pointing to the same place, it concluded that there is still work to be done. This caused some serious issues including long latency results on ping-pong test and lockups while unloading the driver in that condition. Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x.h | 2 +- drivers/net/bnx2x_main.c | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x.h b/drivers/net/bnx2x.h index b468f90..a14dba1 100644 --- a/drivers/net/bnx2x.h +++ b/drivers/net/bnx2x.h @@ -271,7 +271,7 @@ struct bnx2x_fastpath { (fp->tx_pkt_prod != fp->tx_pkt_cons)) #define BNX2X_HAS_RX_WORK(fp) \ - (fp->rx_comp_cons != le16_to_cpu(*fp->rx_cons_sb)) + (fp->rx_comp_cons != rx_cons_sb) #define BNX2X_HAS_WORK(fp) (BNX2X_HAS_RX_WORK(fp) || BNX2X_HAS_TX_WORK(fp)) diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 971576b..272f5d1 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -9250,6 +9250,7 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) napi); struct bnx2x *bp = fp->bp; int work_done = 0; + u16 rx_cons_sb; #ifdef BNX2X_STOP_ON_ERROR if (unlikely(bp->panic)) @@ -9265,10 +9266,16 @@ static int bnx2x_poll(struct napi_struct *napi, int budget) if (BNX2X_HAS_TX_WORK(fp)) bnx2x_tx_int(fp, budget); + rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); + if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) + rx_cons_sb++; if (BNX2X_HAS_RX_WORK(fp)) work_done = bnx2x_rx_int(fp, budget); rmb(); /* BNX2X_HAS_WORK() reads the status block */ + rx_cons_sb = le16_to_cpu(*fp->rx_cons_sb); + if ((rx_cons_sb & MAX_RCQ_DESC_CNT) == MAX_RCQ_DESC_CNT) + rx_cons_sb++; /* must not complete if we consumed full budget */ if ((work_done < budget) && !BNX2X_HAS_WORK(fp)) { -- cgit v1.1 From 7add905f93fa62d11d45fb1d2d05980661f2ccde Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 25 Aug 2008 15:20:48 -0700 Subject: bnx2x: Fan failure mechanism on additional design The A1021G board is also using the fan failure mechanism in the same way the A1022G board does Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 272f5d1..2e207b8 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -2550,6 +2550,7 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn) BNX2X_ERR("SPIO5 hw attention\n"); switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) { + case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1021G: case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G: /* Fan failure attention */ @@ -5337,6 +5338,7 @@ static int bnx2x_init_common(struct bnx2x *bp) } switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) { + case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1021G: case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G: /* Fan failure is indicated by SPIO 5 */ bnx2x_set_spio(bp, MISC_REGISTERS_SPIO_5, @@ -5531,6 +5533,7 @@ static int bnx2x_init_port(struct bnx2x *bp) /* Port DMAE comes here */ switch (bp->common.board & SHARED_HW_CFG_BOARD_TYPE_MASK) { + case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1021G: case SHARED_HW_CFG_BOARD_TYPE_BCM957710A1022G: /* add SPIO 5 to group 0 */ val = REG_RD(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); -- cgit v1.1 From 76b190c592d952b37227f057a14f39e316754156 Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 25 Aug 2008 15:22:46 -0700 Subject: bnx2x: Minimize lock time After iSCSI boot, the HW lock should only protect the flag so only the first function will reset the chip and not then entire chip reset process Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 2e207b8..9972d0c 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6824,6 +6824,10 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) */ bnx2x_acquire_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); val = REG_RD(bp, DORQ_REG_NORM_CID_OFST); + if (val == 0x7) + REG_WR(bp, DORQ_REG_NORM_CID_OFST, 0); + bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); + if (val == 0x7) { u32 reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; /* save our func */ @@ -6901,7 +6905,6 @@ static void __devinit bnx2x_undi_unload(struct bnx2x *bp) (SHMEM_RD(bp, func_mb[bp->func].drv_mb_header) & DRV_MSG_SEQ_NUMBER_MASK); } - bnx2x_release_hw_lock(bp, HW_LOCK_RESOURCE_UNDI); } } -- cgit v1.1 From 46230476b7c66f7cbc013b771873c797f7ba770b Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 25 Aug 2008 15:23:30 -0700 Subject: bnx2x: HW lock timeout Increasing the lock timeout to 5 seconds instead of 1 second to minimize the chance of failures due to timeout Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 9972d0c..cb91802 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -1717,8 +1717,8 @@ static int bnx2x_acquire_hw_lock(struct bnx2x *bp, u32 resource) return -EEXIST; } - /* Try for 1 second every 5ms */ - for (cnt = 0; cnt < 200; cnt++) { + /* Try for 5 second every 5ms */ + for (cnt = 0; cnt < 1000; cnt++) { /* Try to acquire the lock */ REG_WR(bp, hw_lock_control_reg + 4, resource_bit); lock_status = REG_RD(bp, hw_lock_control_reg); -- cgit v1.1 From 3cdf1db7db1649771d683b6ba323ff604ea3cc5e Mon Sep 17 00:00:00 2001 From: Yitchak Gertner Date: Mon, 25 Aug 2008 15:24:21 -0700 Subject: bnx2x: Initialization structure The TPA initialization is part of the FW internal memory initialization and so it is moved to the appropriate function Signed-off-by: Yitchak Gertner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index cb91802..398daeb 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -4606,6 +4606,17 @@ static void bnx2x_init_internal_common(struct bnx2x *bp) { int i; + if (bp->flags & TPA_ENABLE_FLAG) { + struct tstorm_eth_tpa_exist tpa = {0}; + + tpa.tpa_exist = 1; + + REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_TPA_EXIST_OFFSET, + ((u32 *)&tpa)[0]); + REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_TPA_EXIST_OFFSET + 4, + ((u32 *)&tpa)[1]); + } + /* Zero this manually as its initialization is currently missing in the initTool */ for (i = 0; i < (USTORM_AGG_DATA_SIZE >> 2); i++) @@ -5365,17 +5376,6 @@ static int bnx2x_init_common(struct bnx2x *bp) enable_blocks_attention(bp); - if (bp->flags & TPA_ENABLE_FLAG) { - struct tstorm_eth_tpa_exist tmp = {0}; - - tmp.tpa_exist = 1; - - REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_TPA_EXIST_OFFSET, - ((u32 *)&tmp)[0]); - REG_WR(bp, BAR_TSTRORM_INTMEM + TSTORM_TPA_EXIST_OFFSET + 4, - ((u32 *)&tmp)[1]); - } - if (!BP_NOMCP(bp)) { bnx2x_acquire_phy_lock(bp); bnx2x_common_init_phy(bp, bp->common.shmem_base); -- cgit v1.1 From d101463499b769d04e37d3bcb0e0c6876780ce08 Mon Sep 17 00:00:00 2001 From: Yitchak Gertner Date: Mon, 25 Aug 2008 15:25:45 -0700 Subject: bnx2x: NIC load failure cleanup Load failures were not handled correctly Signed-off-by: Yitchak Gertner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 398daeb..1c81da4 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6341,7 +6341,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = bnx2x_init_hw(bp, load_code); if (rc) { BNX2X_ERR("HW init failed, aborting\n"); - goto load_error; + goto load_int_disable; } /* Setup NIC internals and enable interrupts */ @@ -6353,7 +6353,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) if (!load_code) { BNX2X_ERR("MCP response failure, aborting\n"); rc = -EBUSY; - goto load_int_disable; + goto load_rings_free; } } @@ -6372,7 +6372,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) rc = bnx2x_setup_leading(bp); if (rc) { BNX2X_ERR("Setup leading failed!\n"); - goto load_stop_netif; + goto load_netif_stop; } if (CHIP_IS_E1H(bp)) @@ -6385,7 +6385,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) for_each_nondefault_queue(bp, i) { rc = bnx2x_setup_multi(bp, i); if (rc) - goto load_stop_netif; + goto load_netif_stop; } if (CHIP_IS_E1(bp)) @@ -6430,20 +6430,18 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) return 0; -load_stop_netif: +load_netif_stop: for_each_queue(bp, i) napi_disable(&bnx2x_fp(bp, i, napi)); - -load_int_disable: - bnx2x_int_disable_sync(bp); - - /* Release IRQs */ - bnx2x_free_irq(bp); - +load_rings_free: /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); for_each_queue(bp, i) bnx2x_free_rx_sge_range(bp, bp->fp + i, NUM_RX_SGE); +load_int_disable: + bnx2x_int_disable_sync(bp); + /* Release IRQs */ + bnx2x_free_irq(bp); load_error: bnx2x_free_mem(bp); -- cgit v1.1 From 65abd74dd52a79226070904f138f3f8cbcdcf10b Mon Sep 17 00:00:00 2001 From: Yitchak Gertner Date: Mon, 25 Aug 2008 15:26:24 -0700 Subject: bnx2x: NAPI and interrupts enable/disable Fixing the order of enabling and disabling NAPI and the interrupts Signed-off-by: Yitchak Gertner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 149 +++++++++++++++++++++++------------------------ 1 file changed, 73 insertions(+), 76 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 1c81da4..f0b04c9 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6058,6 +6058,44 @@ static int bnx2x_req_irq(struct bnx2x *bp) return rc; } +static void bnx2x_napi_enable(struct bnx2x *bp) +{ + int i; + + for_each_queue(bp, i) + napi_enable(&bnx2x_fp(bp, i, napi)); +} + +static void bnx2x_napi_disable(struct bnx2x *bp) +{ + int i; + + for_each_queue(bp, i) + napi_disable(&bnx2x_fp(bp, i, napi)); +} + +static void bnx2x_netif_start(struct bnx2x *bp) +{ + if (atomic_dec_and_test(&bp->intr_sem)) { + if (netif_running(bp->dev)) { + if (bp->state == BNX2X_STATE_OPEN) + netif_wake_queue(bp->dev); + bnx2x_napi_enable(bp); + bnx2x_int_enable(bp); + } + } +} + +static void bnx2x_netif_stop(struct bnx2x *bp) +{ + bnx2x_int_disable_sync(bp); + if (netif_running(bp->dev)) { + bnx2x_napi_disable(bp); + netif_tx_disable(bp->dev); + bp->dev->trans_start = jiffies; /* prevent tx timeout */ + } +} + /* * Init service functions */ @@ -6363,8 +6401,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) /* Enable Rx interrupt handling before sending the ramrod as it's completed on Rx FP queue */ - for_each_queue(bp, i) - napi_enable(&bnx2x_fp(bp, i, napi)); + bnx2x_napi_enable(bp); /* Enable interrupt handling */ atomic_set(&bp->intr_sem, 0); @@ -6431,8 +6468,7 @@ static int bnx2x_nic_load(struct bnx2x *bp, int load_mode) return 0; load_netif_stop: - for_each_queue(bp, i) - napi_disable(&bnx2x_fp(bp, i, napi)); + bnx2x_napi_disable(bp); load_rings_free: /* Free SKBs, SGEs, TPA pool and driver internals */ bnx2x_free_skbs(bp); @@ -6614,11 +6650,9 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) bp->rx_mode = BNX2X_RX_MODE_NONE; bnx2x_set_storm_rx_mode(bp); - if (netif_running(bp->dev)) { - netif_tx_disable(bp->dev); - bp->dev->trans_start = jiffies; /* prevent tx timeout */ - } - + bnx2x_netif_stop(bp); + if (!netif_running(bp->dev)) + bnx2x_napi_disable(bp); del_timer_sync(&bp->timer); SHMEM_WR(bp, func_mb[BP_FUNC(bp)].drv_pulse_mb, (DRV_PULSE_ALWAYS_ALIVE | bp->fw_drv_pulse_wr_seq)); @@ -6632,9 +6666,7 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) smp_rmb(); while (BNX2X_HAS_TX_WORK(fp)) { - if (!netif_running(bp->dev)) - bnx2x_tx_int(fp, 1000); - + bnx2x_tx_int(fp, 1000); if (!cnt) { BNX2X_ERR("timeout waiting for queue[%d]\n", i); @@ -6650,46 +6682,12 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) smp_rmb(); } } - /* Give HW time to discard old tx messages */ msleep(1); - for_each_queue(bp, i) - napi_disable(&bnx2x_fp(bp, i, napi)); - /* Disable interrupts after Tx and Rx are disabled on stack level */ - bnx2x_int_disable_sync(bp); - /* Release IRQs */ bnx2x_free_irq(bp); - if (unload_mode == UNLOAD_NORMAL) - reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; - - else if (bp->flags & NO_WOL_FLAG) { - reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP; - if (CHIP_IS_E1H(bp)) - REG_WR(bp, MISC_REG_E1HMF_MODE, 0); - - } else if (bp->wol) { - u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; - u8 *mac_addr = bp->dev->dev_addr; - u32 val; - /* The mac address is written to entries 1-4 to - preserve entry 0 which is used by the PMF */ - u8 entry = (BP_E1HVN(bp) + 1)*8; - - val = (mac_addr[0] << 8) | mac_addr[1]; - EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry, val); - - val = (mac_addr[2] << 24) | (mac_addr[3] << 16) | - (mac_addr[4] << 8) | mac_addr[5]; - EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val); - - reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN; - - } else - reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; - if (CHIP_IS_E1(bp)) { struct mac_configuration_cmd *config = bnx2x_sp(bp, mcast_config); @@ -6712,14 +6710,41 @@ static int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode) U64_LO(bnx2x_sp_mapping(bp, mcast_config)), 0); } else { /* E1H */ + REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0); + bnx2x_set_mac_addr_e1h(bp, 0); for (i = 0; i < MC_HASH_SIZE; i++) REG_WR(bp, MC_HASH_OFFSET(bp, i), 0); } - if (CHIP_IS_E1H(bp)) - REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0); + if (unload_mode == UNLOAD_NORMAL) + reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; + + else if (bp->flags & NO_WOL_FLAG) { + reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_MCP; + if (CHIP_IS_E1H(bp)) + REG_WR(bp, MISC_REG_E1HMF_MODE, 0); + + } else if (bp->wol) { + u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; + u8 *mac_addr = bp->dev->dev_addr; + u32 val; + /* The mac address is written to entries 1-4 to + preserve entry 0 which is used by the PMF */ + u8 entry = (BP_E1HVN(bp) + 1)*8; + + val = (mac_addr[0] << 8) | mac_addr[1]; + EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry, val); + + val = (mac_addr[2] << 24) | (mac_addr[3] << 16) | + (mac_addr[4] << 8) | mac_addr[5]; + EMAC_WR(bp, EMAC_REG_EMAC_MAC_MATCH + entry + 4, val); + + reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_EN; + + } else + reset_code = DRV_MSG_CODE_UNLOAD_REQ_WOL_DIS; /* Close multi and leading connections Completions for ramrods are collected in a synchronous way */ @@ -8621,34 +8646,6 @@ test_mem_exit: return rc; } -static void bnx2x_netif_start(struct bnx2x *bp) -{ - int i; - - if (atomic_dec_and_test(&bp->intr_sem)) { - if (netif_running(bp->dev)) { - bnx2x_int_enable(bp); - for_each_queue(bp, i) - napi_enable(&bnx2x_fp(bp, i, napi)); - if (bp->state == BNX2X_STATE_OPEN) - netif_wake_queue(bp->dev); - } - } -} - -static void bnx2x_netif_stop(struct bnx2x *bp) -{ - int i; - - if (netif_running(bp->dev)) { - netif_tx_disable(bp->dev); - bp->dev->trans_start = jiffies; /* prevent tx timeout */ - for_each_queue(bp, i) - napi_disable(&bnx2x_fp(bp, i, napi)); - } - bnx2x_int_disable_sync(bp); -} - static void bnx2x_wait_for_link(struct bnx2x *bp, u8 link_up) { int cnt = 1000; -- cgit v1.1 From 231fd58a4d21aa633db734274a27a67395155e51 Mon Sep 17 00:00:00 2001 From: Yitchak Gertner Date: Mon, 25 Aug 2008 15:27:06 -0700 Subject: bnx2x: Multi Queue The multi queue support is still disabled by default for the bnx2x (needs some more testing and validation), but there are 2 obvious bug in it which are fixed in this patch Signed-off-by: Yitchak Gertner Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index f0b04c9..95e0582 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -6492,7 +6492,7 @@ static int bnx2x_stop_multi(struct bnx2x *bp, int index) /* halt the connection */ bp->fp[index].state = BNX2X_FP_STATE_HALTING; - bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, index, 0, 0, 0); + bnx2x_sp_post(bp, RAMROD_CMD_ID_ETH_HALT, index, 0, index, 0); /* Wait for completion */ rc = bnx2x_wait_ramrod(bp, BNX2X_FP_STATE_HALTED, index, @@ -9492,8 +9492,7 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) fp_index = (smp_processor_id() % bp->num_queues); fp = &bp->fp[fp_index]; - if (unlikely(bnx2x_tx_avail(bp->fp) < - (skb_shinfo(skb)->nr_frags + 3))) { + if (unlikely(bnx2x_tx_avail(fp) < (skb_shinfo(skb)->nr_frags + 3))) { bp->eth_stats.driver_xoff++, netif_stop_queue(dev); BNX2X_ERR("BUG! Tx ring full when queue awake!\n"); @@ -9556,7 +9555,6 @@ static int bnx2x_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_bd->vlan = cpu_to_le16(pkt_prod); if (xmit_type) { - /* turn on parsing and get a BD */ bd_prod = TX_BD(NEXT_TX_IDX(bd_prod)); pbd = (void *)&fp->tx_desc_ring[bd_prod]; -- cgit v1.1 From c2d42545774c4bba7232521d836d0793330e3a4e Mon Sep 17 00:00:00 2001 From: Eilon Greenstein Date: Mon, 25 Aug 2008 15:30:39 -0700 Subject: bnx2x: Version update Version update Signed-off-by: Eilon Greenstein Signed-off-by: David S. Miller --- drivers/net/bnx2x_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 95e0582..82deea0 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c @@ -59,8 +59,8 @@ #include "bnx2x.h" #include "bnx2x_init.h" -#define DRV_MODULE_VERSION "1.45.17" -#define DRV_MODULE_RELDATE "2008/08/13" +#define DRV_MODULE_VERSION "1.45.20" +#define DRV_MODULE_RELDATE "2008/08/25" #define BNX2X_BC_VER 0x040200 /* Time in jiffies before concluding the transmitter is hung */ -- cgit v1.1 From f4156d1cd1dc260cca767a6c0636625f05446799 Mon Sep 17 00:00:00 2001 From: Carl Love Date: Mon, 11 Aug 2008 17:25:43 +1000 Subject: powerpc/cell/oprofile: Avoid double vfree of profile buffer If an error occurs on opcontrol start, the event and per cpu buffers are released. If later opcontrol shutdown is called then the free function will be called again to free buffers that no longer exist. This results in a kernel oops. The following changes prevent the call to delete buffers that don't exist. Signed-off-by: Carl Love Signed-off-by: Arnd Bergmann Acked-by: Robert Richter Signed-off-by: Paul Mackerras --- drivers/oprofile/cpu_buffer.c | 4 +++- drivers/oprofile/event_buffer.c | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 2450b3a3..7ba78e6 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c @@ -38,8 +38,10 @@ void free_cpu_buffers(void) { int i; - for_each_online_cpu(i) + for_each_online_cpu(i) { vfree(per_cpu(cpu_buffer, i).buffer); + per_cpu(cpu_buffer, i).buffer = NULL; + } } int alloc_cpu_buffers(void) diff --git a/drivers/oprofile/event_buffer.c b/drivers/oprofile/event_buffer.c index e7fbac5..8d692a5 100644 --- a/drivers/oprofile/event_buffer.c +++ b/drivers/oprofile/event_buffer.c @@ -93,6 +93,8 @@ out: void free_event_buffer(void) { vfree(event_buffer); + + event_buffer = NULL; } -- cgit v1.1 From b4253f8fc1293cdbfb6a474394e1a66febb70e3d Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sun, 22 Jun 2008 22:36:49 +0100 Subject: [WATCHDOG] Fix NULL usage in s3c2410_wdt driver. Fix comparison of a pointer to 0, instead of using NULL for a invalid pointer. Signed-off-by: Ben Dooks Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/s3c2410_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 22715e3..27af55f 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -374,7 +374,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) } wdt_base = ioremap(res->start, size); - if (wdt_base == 0) { + if (wdt_base == NULL) { dev_err(dev, "failed to ioremap() region\n"); ret = -EINVAL; goto err_req; -- cgit v1.1 From 9e3eaf149043f29cfcb77c2fa163dfa1d2ccbfab Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sun, 22 Jun 2008 22:36:50 +0100 Subject: [WATCHDOG] Clean out header of s3c2410_wdt driver. Remove the changelog from the top of the driver, which is redundant as this information is more accurately represented from the revision control holding the file. Signed-off-by: Ben Dooks Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/s3c2410_wdt.c | 12 ------------ 1 file changed, 12 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 27af55f..825dbd5 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -21,18 +21,6 @@ * 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 - * - * Changelog: - * 05-Oct-2004 BJD Added semaphore init to stop crashes on open - * Fixed tmr_count / wdt_count confusion - * Added configurable debug - * - * 11-Jan-2005 BJD Fixed divide-by-2 in timeout code - * - * 25-Jan-2005 DA Added suspend/resume support - * Replaced reboot notifier with .shutdown method - * - * 10-Mar-2005 LCVR Changed S3C2410_VA to S3C24XX_VA */ #include -- cgit v1.1 From 0e65fb2978467a3538af69858ae6bc13d332b9b2 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Sun, 22 Jun 2008 22:36:51 +0100 Subject: [WATCHDOG] Fix s3c2410_wdt driver coding style issues Fixup coding style issues in the s3c2410_wdt driver. Signed-off-by: Ben Dooks Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/s3c2410_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index 825dbd5..86d4280 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c @@ -353,7 +353,7 @@ static int s3c2410wdt_probe(struct platform_device *pdev) return -ENOENT; } - size = (res->end-res->start)+1; + size = (res->end - res->start) + 1; wdt_mem = request_mem_region(res->start, size, pdev->name); if (wdt_mem == NULL) { dev_err(dev, "failed to get memory region\n"); -- cgit v1.1 From eaa95eb6ea43e6de8bea702c13556de9a1a1195a Mon Sep 17 00:00:00 2001 From: Jochen Friedrich Date: Thu, 24 Jul 2008 12:22:05 +0200 Subject: [WATHDOG] delete unused driver mpc8xx_wdt.c The watchdog driver mpc8xx_wdt.c was a device interface to arch/ppc/syslib/m8xx_wdt.c for MPC8xx hardware. Now that ARCH=ppc is gone, this driver is of no more use. For ARCH=powerpc, MPC8xx hardware is supported by mpc8xxx_wdt.c. Signed-off-by: Jochen Friedrich Signed-off-by: Wim Van Sebroeck Acked-by: Vitaly Bordug Signed-off-by: Andrew Morton --- drivers/watchdog/Kconfig | 4 - drivers/watchdog/Makefile | 1 - drivers/watchdog/mpc8xx_wdt.c | 170 ------------------------------------------ 3 files changed, 175 deletions(-) delete mode 100644 drivers/watchdog/mpc8xx_wdt.c (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index db20542..a8e80f2 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -692,10 +692,6 @@ config MPC5200_WDT tristate "MPC5200 Watchdog Timer" depends on PPC_MPC52xx -config 8xx_WDT - tristate "MPC8xx Watchdog Timer" - depends on 8xx - config 8xxx_WDT tristate "MPC8xxx Platform Watchdog Timer" depends on PPC_8xx || PPC_83xx || PPC_86xx diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index ca3dc04..1b5c011 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -104,7 +104,6 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o # PARISC Architecture # POWERPC Architecture -obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o diff --git a/drivers/watchdog/mpc8xx_wdt.c b/drivers/watchdog/mpc8xx_wdt.c deleted file mode 100644 index 1336425..0000000 --- a/drivers/watchdog/mpc8xx_wdt.c +++ /dev/null @@ -1,170 +0,0 @@ -/* - * mpc8xx_wdt.c - MPC8xx watchdog userspace interface - * - * Author: Florian Schirmer - * - * 2002 (c) Florian Schirmer This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned long wdt_opened; -static int wdt_status; -static spinlock_t wdt_lock; - -static void mpc8xx_wdt_handler_disable(void) -{ - volatile uint __iomem *piscr; - piscr = (uint *)&((immap_t *)IMAP_ADDR)->im_sit.sit_piscr; - - if (!m8xx_has_internal_rtc) - m8xx_wdt_stop_timer(); - else - out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE)); - printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); -} - -static void mpc8xx_wdt_handler_enable(void) -{ - volatile uint __iomem *piscr; - piscr = (uint *)&((immap_t *)IMAP_ADDR)->im_sit.sit_piscr; - - if (!m8xx_has_internal_rtc) - m8xx_wdt_install_timer(); - else - out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE); - printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n"); -} - -static int mpc8xx_wdt_open(struct inode *inode, struct file *file) -{ - if (test_and_set_bit(0, &wdt_opened)) - return -EBUSY; - m8xx_wdt_reset(); - mpc8xx_wdt_handler_disable(); - return nonseekable_open(inode, file); -} - -static int mpc8xx_wdt_release(struct inode *inode, struct file *file) -{ - m8xx_wdt_reset(); -#if !defined(CONFIG_WATCHDOG_NOWAYOUT) - mpc8xx_wdt_handler_enable(); -#endif - clear_bit(0, &wdt_opened); - return 0; -} - -static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, - size_t len, loff_t *ppos) -{ - if (len) { - spin_lock(&wdt_lock); - m8xx_wdt_reset(); - spin_unlock(&wdt_lock); - } - return len; -} - -static long mpc8xx_wdt_ioctl(struct file *file, - unsigned int cmd, unsigned long arg) -{ - int timeout; - static struct watchdog_info info = { - .options = WDIOF_KEEPALIVEPING, - .firmware_version = 0, - .identity = "MPC8xx watchdog", - }; - - switch (cmd) { - case WDIOC_GETSUPPORT: - if (copy_to_user((void *)arg, &info, sizeof(info))) - return -EFAULT; - break; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - if (put_user(wdt_status, (int *)arg)) - return -EFAULT; - wdt_status &= ~WDIOF_KEEPALIVEPING; - break; - - case WDIOC_GETTEMP: - return -EOPNOTSUPP; - - case WDIOC_SETOPTIONS: - return -EOPNOTSUPP; - - case WDIOC_KEEPALIVE: - spin_lock(&wdt_lock); - m8xx_wdt_reset(); - wdt_status |= WDIOF_KEEPALIVEPING; - spin_unlock(&wdt_lock); - break; - - case WDIOC_SETTIMEOUT: - return -EOPNOTSUPP; - - case WDIOC_GETTIMEOUT: - spin_lock(&wdt_lock); - timeout = m8xx_wdt_get_timeout(); - spin_unlock(&wdt_lock); - if (put_user(timeout, (int *)arg)) - return -EFAULT; - break; - - default: - return -ENOTTY; - } - - return 0; -} - -static const struct file_operations mpc8xx_wdt_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .write = mpc8xx_wdt_write, - .unlocked_ioctl = mpc8xx_wdt_ioctl, - .open = mpc8xx_wdt_open, - .release = mpc8xx_wdt_release, -}; - -static struct miscdevice mpc8xx_wdt_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &mpc8xx_wdt_fops, -}; - -static int __init mpc8xx_wdt_init(void) -{ - spin_lock_init(&wdt_lock); - return misc_register(&mpc8xx_wdt_miscdev); -} - -static void __exit mpc8xx_wdt_exit(void) -{ - misc_deregister(&mpc8xx_wdt_miscdev); - - m8xx_wdt_reset(); - mpc8xx_wdt_handler_enable(); -} - -module_init(mpc8xx_wdt_init); -module_exit(mpc8xx_wdt_exit); - -MODULE_AUTHOR("Florian Schirmer "); -MODULE_DESCRIPTION("MPC8xx watchdog driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.1 From b3e8f2c13ae964a8889fe96a2f3f7fd7e0cfae76 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 25 Feb 2008 12:59:26 +0100 Subject: [WATCHDOG] Add support for the built-int RDC R-321x SoC watchdog This patch adds support for the built-in RDC R-321x SoC watchdog. Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 10 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/rdc321x_wdt.c | 285 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 296 insertions(+) create mode 100644 drivers/watchdog/rdc321x_wdt.c (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index a8e80f2..a1f47c7 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -465,6 +465,16 @@ config PC87413_WDT Most people will say N. +config RDC321X_WDT + tristate "RDC R-321x SoC watchdog" + depends on X86_RDC321X + help + This is the driver for the built in hardware watchdog + in the RDC R-321x SoC. + + To compile this driver as a module, choose M here: the + module will be called rdc321x_wdt. + config 60XX_WDT tristate "SBC-60XX Watchdog Timer" depends on X86 diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index 1b5c011..a88be6f 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -75,6 +75,7 @@ obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o obj-$(CONFIG_PC87413_WDT) += pc87413_wdt.o +obj-$(CONFIG_RDC321X_WDT) += rdc321x_wdt.o obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o obj-$(CONFIG_SBC8360_WDT) += sbc8360.o obj-$(CONFIG_SBC7240_WDT) += sbc7240_wdt.o diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c new file mode 100644 index 0000000..9108efa --- /dev/null +++ b/drivers/watchdog/rdc321x_wdt.c @@ -0,0 +1,285 @@ +/* + * RDC321x watchdog driver + * + * Copyright (C) 2007 Florian Fainelli + * + * This driver is highly inspired from the cpu5_wdt 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 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 +#include +#include +#include + +#include + +#define RDC_WDT_MASK 0x80000000 /* Mask */ +#define RDC_WDT_EN 0x00800000 /* Enable bit */ +#define RDC_WDT_WTI 0x00200000 /* Generate CPU reset/NMI/WDT on timeout */ +#define RDC_WDT_RST 0x00100000 /* Reset bit */ +#define RDC_WDT_WIF 0x00040000 /* WDT IRQ Flag */ +#define RDC_WDT_IRT 0x00000100 /* IRQ Routing table */ +#define RDC_WDT_CNT 0x00000001 /* WDT count */ + +#define RDC_CLS_TMR 0x80003844 /* Clear timer */ + +#define RDC_WDT_INTERVAL (HZ/10+1) + +static int ticks = 1000; + +/* some device data */ + +static struct { + struct completion stop; + int running; + struct timer_list timer; + int queue; + int default_ticks; + unsigned long inuse; + spinlock_t lock; +} rdc321x_wdt_device; + +/* generic helper functions */ + +static void rdc321x_wdt_trigger(unsigned long unused) +{ + unsigned long flags; + + if (rdc321x_wdt_device.running) + ticks--; + + /* keep watchdog alive */ + spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); + outl(RDC_WDT_EN | inl(RDC3210_CFGREG_DATA), + RDC3210_CFGREG_DATA); + spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); + + /* requeue?? */ + if (rdc321x_wdt_device.queue && ticks) + mod_timer(&rdc321x_wdt_device.timer, + jiffies + RDC_WDT_INTERVAL); + else { + /* ticks doesn't matter anyway */ + complete(&rdc321x_wdt_device.stop); + } + +} + +static void rdc321x_wdt_reset(void) +{ + ticks = rdc321x_wdt_device.default_ticks; +} + +static void rdc321x_wdt_start(void) +{ + unsigned long flags; + + if (!rdc321x_wdt_device.queue) { + rdc321x_wdt_device.queue = 1; + + /* Clear the timer */ + spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); + outl(RDC_CLS_TMR, RDC3210_CFGREG_ADDR); + + /* Enable watchdog and set the timeout to 81.92 us */ + outl(RDC_WDT_EN | RDC_WDT_CNT, RDC3210_CFGREG_DATA); + spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); + + mod_timer(&rdc321x_wdt_device.timer, + jiffies + RDC_WDT_INTERVAL); + } + + /* if process dies, counter is not decremented */ + rdc321x_wdt_device.running++; +} + +static int rdc321x_wdt_stop(void) +{ + if (rdc321x_wdt_device.running) + rdc321x_wdt_device.running = 0; + + ticks = rdc321x_wdt_device.default_ticks; + + return -EIO; +} + +/* filesystem operations */ +static int rdc321x_wdt_open(struct inode *inode, struct file *file) +{ + if (test_and_set_bit(0, &rdc321x_wdt_device.inuse)) + return -EBUSY; + + return nonseekable_open(inode, file); +} + +static int rdc321x_wdt_release(struct inode *inode, struct file *file) +{ + clear_bit(0, &rdc321x_wdt_device.inuse); + return 0; +} + +static int rdc321x_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + unsigned int value; + static struct watchdog_info ident = { + .options = WDIOF_CARDRESET, + .identity = "RDC321x WDT", + }; + unsigned long flags; + + switch (cmd) { + case WDIOC_KEEPALIVE: + rdc321x_wdt_reset(); + break; + case WDIOC_GETSTATUS: + /* Read the value from the DATA register */ + spin_lock_irqsave(&rdc321x_wdt_device.lock, flags); + value = inl(RDC3210_CFGREG_DATA); + spin_unlock_irqrestore(&rdc321x_wdt_device.lock, flags); + if (copy_to_user(argp, &value, sizeof(int))) + return -EFAULT; + break; + case WDIOC_GETSUPPORT: + if (copy_to_user(argp, &ident, sizeof(ident))) + return -EFAULT; + break; + case WDIOC_SETOPTIONS: + if (copy_from_user(&value, argp, sizeof(int))) + return -EFAULT; + switch (value) { + case WDIOS_ENABLECARD: + rdc321x_wdt_start(); + break; + case WDIOS_DISABLECARD: + return rdc321x_wdt_stop(); + default: + return -EINVAL; + } + break; + default: + return -ENOTTY; + } + return 0; +} + +static ssize_t rdc321x_wdt_write(struct file *file, const char __user *buf, + size_t count, loff_t *ppos) +{ + if (!count) + return -EIO; + + rdc321x_wdt_reset(); + + return count; +} + +static const struct file_operations rdc321x_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .ioctl = rdc321x_wdt_ioctl, + .open = rdc321x_wdt_open, + .write = rdc321x_wdt_write, + .release = rdc321x_wdt_release, +}; + +static struct miscdevice rdc321x_wdt_misc = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &rdc321x_wdt_fops, +}; + +static int __devinit rdc321x_wdt_probe(struct platform_device *pdev) +{ + int err; + + err = misc_register(&rdc321x_wdt_misc); + if (err < 0) { + printk(KERN_ERR PFX "watchdog misc_register failed\n"); + return err; + } + + spin_lock_init(&rdc321x_wdt_device.lock); + + /* Reset the watchdog */ + outl(RDC_WDT_RST, RDC3210_CFGREG_DATA); + + init_completion(&rdc321x_wdt_device.stop); + rdc321x_wdt_device.queue = 0; + + clear_bit(0, &rdc321x_wdt_device.inuse); + + setup_timer(&rdc321x_wdt_device.timer, rdc321x_wdt_trigger, 0); + + rdc321x_wdt_device.default_ticks = ticks; + + printk(KERN_INFO PFX "watchdog init success\n"); + + return 0; +} + +static int rdc321x_wdt_remove(struct platform_device *pdev) +{ + if (rdc321x_wdt_device.queue) { + rdc321x_wdt_device.queue = 0; + wait_for_completion(&rdc321x_wdt_device.stop); + } + + misc_deregister(&rdc321x_wdt_misc); + + return 0; +} + +static struct platform_driver rdc321x_wdt_driver = { + .probe = rdc321x_wdt_probe, + .remove = rdc321x_wdt_remove, + .driver = { + .owner = THIS_MODULE, + .name = "rdc321x-wdt", + }, +}; + +static int __init rdc321x_wdt_init(void) +{ + return platform_driver_register(&rdc321x_wdt_driver); +} + +static void __exit rdc321x_wdt_exit(void) +{ + platform_driver_unregister(&rdc321x_wdt_driver); +} + +module_init(rdc321x_wdt_init); +module_exit(rdc321x_wdt_exit); + +MODULE_AUTHOR("Florian Fainelli "); +MODULE_DESCRIPTION("RDC321x watchdog driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.1 From 03ec58568a3c66cac4b23ff74db95c966a1521de Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Mon, 25 Feb 2008 13:11:31 +0100 Subject: [WATCHDOG] Add support for the IDT RC32434 watchdog Add driver for the IDT RC32434 SoC built-in watchdog. Signed-off-by: Florian Fainelli Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/Kconfig | 10 ++ drivers/watchdog/Makefile | 1 + drivers/watchdog/rc32434_wdt.c | 344 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 355 insertions(+) create mode 100644 drivers/watchdog/rc32434_wdt.c (limited to 'drivers') diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index a1f47c7..c510367 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -643,6 +643,16 @@ config SBC_EPX_C3_WATCHDOG # MIPS Architecture +config RC32434_WDT + tristate "IDT RC32434 SoC Watchdog Timer" + depends on MIKROTIK_RB532 + help + Hardware driver for the IDT RC32434 SoC built-in + watchdog timer. + + To compile this driver as a module, choose M here: the + module will be called rc32434_wdt. + config INDYDOG tristate "Indy/I2 Hardware Watchdog" depends on SGI_HAS_INDYDOG diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index a88be6f..e0ef123 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile @@ -95,6 +95,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o # M68KNOMMU Architecture # MIPS Architecture +obj-$(CONFIG_RC32434_WDT) += rc32434_wdt.o obj-$(CONFIG_INDYDOG) += indydog.o obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c new file mode 100644 index 0000000..6756bcb --- /dev/null +++ b/drivers/watchdog/rc32434_wdt.c @@ -0,0 +1,344 @@ +/* + * IDT Interprise 79RC32434 watchdog driver + * + * Copyright (C) 2006, Ondrej Zajicek + * Copyright (C) 2008, Florian Fainelli + * + * based on + * SoftDog 0.05: A Software Watchdog Device + * + * (c) Copyright 1996 Alan Cox , 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 Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define MAX_TIMEOUT 20 +#define RC32434_WDT_INTERVAL (15 * HZ) + +#define VERSION "0.2" + +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; + +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) ")"); + + +static void rc32434_wdt_start(void) +{ + u32 val; + + if (!rc32434_wdt_device.inuse) { + writel(0, &wdt_reg->wtcount); + + val = RC32434_ERR_WRE; + writel(readl(&wdt_reg->errcs) | val, &wdt_reg->errcs); + + val = RC32434_WTC_EN; + writel(readl(&wdt_reg->wtc) | val, &wdt_reg->wtc); + } + rc32434_wdt_device.running++; +} + +static void rc32434_wdt_stop(void) +{ + u32 val; + + if (rc32434_wdt_device.running) { + + val = ~RC32434_WTC_EN; + writel(readl(&wdt_reg->wtc) & val, &wdt_reg->wtc); + + val = ~RC32434_ERR_WRE; + writel(readl(&wdt_reg->errcs) & val, &wdt_reg->errcs); + + rc32434_wdt_device.running = 0; + } +} + +static void rc32434_wdt_set(int new_timeout) +{ + u32 cmp = new_timeout * HZ; + u32 state, val; + + 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); +} + +static void rc32434_wdt_reset(void) +{ + ticks = rc32434_wdt_device.default_ticks; +} + +static void rc32434_wdt_update(unsigned long unused) +{ + 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) +{ + if (test_and_set_bit(0, &rc32434_wdt_device.inuse)) + return -EBUSY; + + if (nowayout) + __module_get(THIS_MODULE); + + return nonseekable_open(inode, file); +} + +static int rc32434_wdt_release(struct inode *inode, struct file *file) +{ + if (expect_close && nowayout == 0) { + rc32434_wdt_stop(); + printk(KERN_INFO KBUILD_MODNAME ": disabling watchdog timer\n"); + module_put(THIS_MODULE); + } else + printk(KERN_CRIT KBUILD_MODNAME + ": device closed unexpectedly. WDT will not stop !\n"); + + clear_bit(0, &rc32434_wdt_device.inuse); + return 0; +} + +static ssize_t rc32434_wdt_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + if (len) { + if (!nowayout) { + size_t i; + + /* In case it was set long ago */ + expect_close = 0; + + for (i = 0; i != len; i++) { + char c; + if (get_user(c, data + i)) + return -EFAULT; + if (c == 'V') + expect_close = 1; + } + } + rc32434_wdt_update(0); + return len; + } + return 0; +} + +static int rc32434_wdt_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + void __user *argp = (void __user *)arg; + int new_timeout; + unsigned int value; + static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .identity = "RC32434_WDT Watchdog", + }; + switch (cmd) { + case WDIOC_KEEPALIVE: + rc32434_wdt_reset(); + break; + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + value = readl(&wdt_reg->wtcount); + if (copy_to_user(argp, &value, sizeof(int))) + return -EFAULT; + break; + case WDIOC_GETSUPPORT: + if (copy_to_user(argp, &ident, sizeof(ident))) + return -EFAULT; + break; + case WDIOC_SETOPTIONS: + if (copy_from_user(&value, argp, sizeof(int))) + return -EFAULT; + switch (value) { + case WDIOS_ENABLECARD: + rc32434_wdt_start(); + break; + case WDIOS_DISABLECARD: + rc32434_wdt_stop(); + default: + return -EINVAL; + } + break; + case WDIOC_SETTIMEOUT: + if (copy_from_user(&new_timeout, argp, sizeof(int))) + return -EFAULT; + if (new_timeout < 1) + return -EINVAL; + if (new_timeout > MAX_TIMEOUT) + return -EINVAL; + rc32434_wdt_set(new_timeout); + case WDIOC_GETTIMEOUT: + return copy_to_user(argp, &timeout, sizeof(int)); + default: + return -ENOTTY; + } + + return 0; +} + +static struct file_operations rc32434_wdt_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = rc32434_wdt_write, + .ioctl = rc32434_wdt_ioctl, + .open = rc32434_wdt_open, + .release = rc32434_wdt_release, +}; + +static struct miscdevice rc32434_wdt_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &rc32434_wdt_fops, +}; + +static char banner[] = KERN_INFO KBUILD_MODNAME + ": Watchdog Timer version " VERSION ", timer margin: %d sec\n"; + +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"); + if (!r) { + printk(KERN_ERR KBUILD_MODNAME + "failed to retrieve resources\n"); + return -ENODEV; + } + + wdt_reg = ioremap_nocache(r->start, r->end - r->start); + if (!wdt_reg) { + printk(KERN_ERR KBUILD_MODNAME + "failed to remap I/O resources\n"); + return -ENXIO; + } + + 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; + +unmap: + iounmap(wdt_reg); + return ret; +} + +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; +} + +static struct platform_driver rc32434_wdt = { + .probe = rc32434_wdt_probe, + .remove = rc32434_wdt_remove, + .driver = { + .name = "rc32434_wdt", + } +}; + +static int __init rc32434_wdt_init(void) +{ + return platform_driver_register(&rc32434_wdt); +} + +static void __exit rc32434_wdt_exit(void) +{ + platform_driver_unregister(&rc32434_wdt); +} + +module_init(rc32434_wdt_init); +module_exit(rc32434_wdt_exit); + +MODULE_AUTHOR("Ondrej Zajicek ," + "Florian Fainelli "); +MODULE_DESCRIPTION("Driver for the IDT RC32434 SoC watchdog"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); -- cgit v1.1 From ab4ba3cdeb59e85552422680b5bac99e28740330 Mon Sep 17 00:00:00 2001 From: Thomas Mingarelli Date: Tue, 15 Jul 2008 19:40:41 +0000 Subject: [WATCHDOG] hpwdt.c kdebug support add kdebug support for the hpwdt.c driver. Signed-off-by: Thomas Mingarelli Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/hpwdt.c | 93 ++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 43 deletions(-) (limited to 'drivers') diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index d039d5f..a3765e0b 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c @@ -116,6 +116,7 @@ static unsigned int reload; /* the computed soft_margin */ static int nowayout = WATCHDOG_NOWAYOUT; static char expect_release; static unsigned long hpwdt_is_open; +static unsigned int allow_kdump; static void __iomem *pci_mem_addr; /* the PCI-memory address */ static unsigned long __iomem *hpwdt_timer_reg; @@ -221,19 +222,19 @@ static int __devinit cru_detect(unsigned long map_entry, if (cmn_regs.u1.ral != 0) { printk(KERN_WARNING - "hpwdt: Call succeeded but with an error: 0x%x\n", - cmn_regs.u1.ral); + "hpwdt: Call succeeded but with an error: 0x%x\n", + cmn_regs.u1.ral); } else { physical_bios_base = cmn_regs.u2.rebx; physical_bios_offset = cmn_regs.u4.redx; cru_length = cmn_regs.u3.recx; cru_physical_address = - physical_bios_base + physical_bios_offset; + physical_bios_base + physical_bios_offset; /* If the values look OK, then map it in. */ if ((physical_bios_base + physical_bios_offset)) { cru_rom_addr = - ioremap(cru_physical_address, cru_length); + ioremap(cru_physical_address, cru_length); if (cru_rom_addr) retval = 0; } @@ -356,7 +357,6 @@ asm(".text \n\t" "call *%r12 \n\t" "pushfq \n\t" "popq %r12 \n\t" - "popfq \n\t" "movl %eax, (%r9) \n\t" "movl %ebx, 4(%r9) \n\t" "movl %ecx, 8(%r9) \n\t" @@ -390,10 +390,10 @@ static void __devinit dmi_find_cru(const struct dmi_header *dm) smbios_cru64_ptr = (struct smbios_cru64_info *) dm; if (smbios_cru64_ptr->signature == CRU_BIOS_SIGNATURE_VALUE) { cru_physical_address = - smbios_cru64_ptr->physical_address + - smbios_cru64_ptr->double_offset; + smbios_cru64_ptr->physical_address + + smbios_cru64_ptr->double_offset; cru_rom_addr = ioremap(cru_physical_address, - smbios_cru64_ptr->double_length); + smbios_cru64_ptr->double_length); } } } @@ -405,7 +405,7 @@ static int __devinit detect_cru_service(void) dmi_walk(dmi_find_cru); /* if cru_rom_addr has been set then we found a CRU service */ - return ((cru_rom_addr != NULL) ? 0: -ENODEV); + return ((cru_rom_addr != NULL) ? 0 : -ENODEV); } /* ------------------------------------------------------------------------- */ @@ -413,34 +413,6 @@ static int __devinit detect_cru_service(void) #endif /* - * NMI Handler - */ -static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, - void *data) -{ - unsigned long rom_pl; - static int die_nmi_called; - - if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) - return NOTIFY_OK; - - spin_lock_irqsave(&rom_lock, rom_pl); - if (!die_nmi_called) - asminline_call(&cmn_regs, cru_rom_addr); - die_nmi_called = 1; - spin_unlock_irqrestore(&rom_lock, rom_pl); - if (cmn_regs.u1.ral == 0) { - printk(KERN_WARNING "hpwdt: An NMI occurred, " - "but unable to determine source.\n"); - } else { - panic("An NMI occurred, please see the Integrated " - "Management Log for details.\n"); - } - - return NOTIFY_STOP; -} - -/* * Watchdog operations */ static void hpwdt_start(void) @@ -484,6 +456,36 @@ static int hpwdt_change_timer(int new_margin) } /* + * NMI Handler + */ +static int hpwdt_pretimeout(struct notifier_block *nb, unsigned long ulReason, + void *data) +{ + unsigned long rom_pl; + static int die_nmi_called; + + if (ulReason != DIE_NMI && ulReason != DIE_NMI_IPI) + return NOTIFY_OK; + + spin_lock_irqsave(&rom_lock, rom_pl); + if (!die_nmi_called) + asminline_call(&cmn_regs, cru_rom_addr); + die_nmi_called = 1; + spin_unlock_irqrestore(&rom_lock, rom_pl); + if (cmn_regs.u1.ral == 0) { + printk(KERN_WARNING "hpwdt: An NMI occurred, " + "but unable to determine source.\n"); + } else { + if (allow_kdump) + hpwdt_stop(); + panic("An NMI occurred, please see the Integrated " + "Management Log for details.\n"); + } + + return NOTIFY_STOP; +} + +/* * /dev/watchdog handling */ static int hpwdt_open(struct inode *inode, struct file *file) @@ -625,17 +627,18 @@ static struct notifier_block die_notifier = { */ static int __devinit hpwdt_init_one(struct pci_dev *dev, - const struct pci_device_id *ent) + const struct pci_device_id *ent) { int retval; /* * First let's find out if we are on an iLO2 server. We will * not run on a legacy ASM box. + * So we only support the G5 ProLiant servers and higher. */ if (dev->subsystem_vendor != PCI_VENDOR_ID_HP) { dev_warn(&dev->dev, - "This server does not have an iLO2 ASIC.\n"); + "This server does not have an iLO2 ASIC.\n"); return -ENODEV; } @@ -669,7 +672,7 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, retval = detect_cru_service(); if (retval < 0) { dev_warn(&dev->dev, - "Unable to detect the %d Bit CRU Service.\n", + "Unable to detect the %d Bit CRU Service.\n", HPWDT_ARCH); goto error_get_cru; } @@ -684,7 +687,7 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, retval = register_die_notifier(&die_notifier); if (retval != 0) { dev_warn(&dev->dev, - "Unable to register a die notifier (err=%d).\n", + "Unable to register a die notifier (err=%d).\n", retval); goto error_die_notifier; } @@ -699,8 +702,9 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev, printk(KERN_INFO "hp Watchdog Timer Driver: 1.00" - ", timer margin: %d seconds( nowayout=%d).\n", - soft_margin, nowayout); + ", timer margin: %d seconds (nowayout=%d)" + ", allow kernel dump: %s (default = 0/OFF).\n", + soft_margin, nowayout, (allow_kdump == 0) ? "OFF" : "ON"); return 0; @@ -755,6 +759,9 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); module_param(soft_margin, int, 0); MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds"); +module_param(allow_kdump, int, 0); +MODULE_PARM_DESC(allow_kdump, "Start a kernel dump after NMI occurs"); + module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); -- cgit v1.1 From 593fc178f634b742d03660a35fcb5694c0751718 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Wed, 20 Aug 2008 16:38:36 -0700 Subject: [WATCHDOG] mpc8xxx_wdt: fix modular build Fix the following build error when mpc8xxx_wdt is selected to build as a module: drivers/watchdog/mpc8xxx_wdt.c:304: error: redefinition of '__inittest' drivers/watchdog/mpc8xxx_wdt.c:298: error: previous definition of '__inittest' was here drivers/watchdog/mpc8xxx_wdt.c:304: error: redefinition of 'init_module' drivers/watchdog/mpc8xxx_wdt.c:298: error: previous definition of 'init_module' was here Reported-by: Dave Jones Signed-off-by: Anton Vorontsov Signed-off-by: Wim Van Sebroeck Cc: Adrian Bunk Signed-off-by: Andrew Morton --- drivers/watchdog/mpc8xxx_wdt.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c index f209496..38c588e 100644 --- a/drivers/watchdog/mpc8xxx_wdt.c +++ b/drivers/watchdog/mpc8xxx_wdt.c @@ -48,6 +48,7 @@ struct mpc8xxx_wdt_type { }; static struct mpc8xxx_wdt __iomem *wd_base; +static int mpc8xxx_wdt_init_late(void); static u16 timeout = 0xffff; module_param(timeout, ushort, 0); @@ -213,6 +214,12 @@ static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, else timeout_sec = timeout / freq; +#ifdef MODULE + ret = mpc8xxx_wdt_init_late(); + if (ret) + goto err_unmap; +#endif + pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d " "(%d seconds)\n", reset ? "reset" : "interrupt", timeout, timeout_sec); @@ -280,7 +287,7 @@ static struct of_platform_driver mpc8xxx_wdt_driver = { * very early to start pinging the watchdog (misc devices are not yet * available), and later module_init() just registers the misc device. */ -static int __init mpc8xxx_wdt_init_late(void) +static int mpc8xxx_wdt_init_late(void) { int ret; @@ -295,7 +302,9 @@ static int __init mpc8xxx_wdt_init_late(void) } return 0; } +#ifndef MODULE module_init(mpc8xxx_wdt_init_late); +#endif static int __init mpc8xxx_wdt_init(void) { -- cgit v1.1 From 95f62bdc550eecfb9c7396b0f7cb5ebd349d0835 Mon Sep 17 00:00:00 2001 From: Ilpo Jarvinen Date: Tue, 19 Aug 2008 09:01:14 +0300 Subject: [WATCHDOG] at91rm9200_wdt.c: fix misleading indentation Signed-off-by: Ilpo Jarvinen Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/at91rm9200_wdt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index d061f0a..993e5f5 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c @@ -241,7 +241,7 @@ static int at91wdt_resume(struct platform_device *pdev) { if (at91wdt_busy) at91_wdt_start(); - return 0; + return 0; } #else -- cgit v1.1 From 3ccd3ec6d4a7750c49c4d2bbcc1d0e82cd4c8a7f Mon Sep 17 00:00:00 2001 From: Huang Weiyi Date: Sun, 17 Aug 2008 07:51:12 +0800 Subject: [WATCHDOG] removed unused #include The drivers below do not use LINUX_VERSION_CODE nor KERNEL_VERSION. drivers/watchdog/pc87413_wdt.c This patch removes the said #include . Signed-off-by: Huang Weiyi Signed-off-by: Wim Van Sebroeck --- drivers/watchdog/pc87413_wdt.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index e91ada7..484c215 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c @@ -30,7 +30,6 @@ #include #include #include -#include #include #include -- cgit v1.1 From 3c34a5d821b825b720189e87561ba18500cf8026 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 18 Aug 2008 15:40:02 -0400 Subject: atmel: return ENOENT on request_firmware failure Return errors from request_firmware() (like other drivers that do firmware load on device open) and make up plausible codes for other error conditions. Gives userspace tools like NetworkManager a clue that firmware may be missing when the result of setting IFF_UP is ENOENT. Signed-off-by: Dan Williams v2: fix reversed check of atmel_wakeup_firmware() in probe_atmel_card() Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index bd35bb0..f23bcd0 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1304,7 +1304,7 @@ EXPORT_SYMBOL(atmel_open); int atmel_open(struct net_device *dev) { struct atmel_private *priv = netdev_priv(dev); - int i, channel; + int i, channel, err; /* any scheduled timer is no longer needed and might screw things up.. */ del_timer_sync(&priv->management_timer); @@ -1328,8 +1328,9 @@ int atmel_open(struct net_device *dev) priv->site_survey_state = SITE_SURVEY_IDLE; priv->station_is_associated = 0; - if (!reset_atmel_card(dev)) - return -EAGAIN; + err = reset_atmel_card(dev); + if (err) + return err; if (priv->config_reg_domain) { priv->reg_domain = priv->config_reg_domain; @@ -3580,12 +3581,12 @@ static int atmel_wakeup_firmware(struct atmel_private *priv) if (i == 0) { printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name); - return 0; + return -EIO; } if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) { printk(KERN_ALERT "%s: card missing.\n", priv->dev->name); - return 0; + return -ENODEV; } /* now check for completion of MAC initialization through @@ -3609,19 +3610,19 @@ static int atmel_wakeup_firmware(struct atmel_private *priv) if (i == 0) { printk(KERN_ALERT "%s: MAC failed to initialise.\n", priv->dev->name); - return 0; + return -EIO; } /* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */ if ((mr3 & MAC_INIT_COMPLETE) && !(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) { printk(KERN_ALERT "%s: MAC failed MR3 self-test.\n", priv->dev->name); - return 0; + return -EIO; } if ((mr1 & MAC_INIT_COMPLETE) && !(atmel_read16(priv->dev, MR1) & MAC_INIT_OK)) { printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name); - return 0; + return -EIO; } atmel_copy_to_host(priv->dev, (unsigned char *)iface, @@ -3642,7 +3643,7 @@ static int atmel_wakeup_firmware(struct atmel_private *priv) iface->func_ctrl = le16_to_cpu(iface->func_ctrl); iface->mac_status = le16_to_cpu(iface->mac_status); - return 1; + return 0; } /* determine type of memory and MAC address */ @@ -3693,7 +3694,7 @@ static int probe_atmel_card(struct net_device *dev) /* Standard firmware in flash, boot it up and ask for the Mac Address */ priv->card_type = CARD_TYPE_SPI_FLASH; - if (atmel_wakeup_firmware(priv)) { + if (atmel_wakeup_firmware(priv) == 0) { atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6); /* got address, now squash it again until the network @@ -3835,6 +3836,7 @@ static int reset_atmel_card(struct net_device *dev) struct atmel_private *priv = netdev_priv(dev); u8 configuration; int old_state = priv->station_state; + int err = 0; /* data to add to the firmware names, in priority order this implemenents firmware versioning */ @@ -3868,11 +3870,12 @@ static int reset_atmel_card(struct net_device *dev) dev->name); strcpy(priv->firmware_id, "atmel_at76c502.bin"); } - if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) != 0) { + err = request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev); + if (err != 0) { printk(KERN_ALERT "%s: firmware %s is missing, cannot continue.\n", dev->name, priv->firmware_id); - return 0; + return err; } } else { int fw_index = 0; @@ -3901,7 +3904,7 @@ static int reset_atmel_card(struct net_device *dev) "%s: firmware %s is missing, cannot start.\n", dev->name, priv->firmware_id); priv->firmware_id[0] = '\0'; - return 0; + return -ENOENT; } } @@ -3926,8 +3929,9 @@ static int reset_atmel_card(struct net_device *dev) release_firmware(fw_entry); } - if (!atmel_wakeup_firmware(priv)) - return 0; + err = atmel_wakeup_firmware(priv); + if (err != 0) + return err; /* Check the version and set the correct flag for wpa stuff, old and new firmware is incompatible. @@ -3968,10 +3972,9 @@ static int reset_atmel_card(struct net_device *dev) if (!priv->radio_on_broken) { if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) == CMD_STATUS_REJECTED_RADIO_OFF) { - printk(KERN_INFO - "%s: cannot turn the radio on. (Hey radio, you're beautiful!)\n", + printk(KERN_INFO "%s: cannot turn the radio on.\n", dev->name); - return 0; + return -EIO; } } @@ -4006,7 +4009,7 @@ static int reset_atmel_card(struct net_device *dev) wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); } - return 1; + return 0; } static void atmel_send_command(struct atmel_private *priv, int command, -- cgit v1.1 From d0c2912fe8df81a8b723fb6ec4d4cdf523cbaff7 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 18 Aug 2008 15:32:41 -0400 Subject: atmel: try open system authentication too When the AP rejects a Shared Key authentication request, try Open System auth too. Signed-off-by: Dan Williams Signed-off-by: John W. Linville --- drivers/net/wireless/atmel.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index f23bcd0..bd65c48 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -3062,12 +3062,20 @@ static void authenticate(struct atmel_private *priv, u16 frame_len) } if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { - /* Do opensystem first, then try sharedkey */ + /* Flip back and forth between WEP auth modes until the max + * authentication tries has been exceeded. + */ if (system == WLAN_AUTH_OPEN) { priv->CurrentAuthentTransactionSeqNum = 0x001; priv->exclude_unencrypted = 1; send_authentication_request(priv, WLAN_AUTH_SHARED_KEY, NULL, 0); return; + } else if ( system == WLAN_AUTH_SHARED_KEY + && priv->wep_is_on) { + priv->CurrentAuthentTransactionSeqNum = 0x001; + priv->exclude_unencrypted = 0; + send_authentication_request(priv, WLAN_AUTH_OPEN, NULL, 0); + return; } else if (priv->connect_to_any_BSS) { int bss_index; -- cgit v1.1 From 004829730cb1b03abe7555e1c1faadec62cbcf6f Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 18 Aug 2008 21:45:27 +0200 Subject: Ath5k: lock beacons Beacons setup and config was racy with beacon send. Ensure that ISR and reset functions see consistent state of bbuf. Use also dev_kfree_skb_any in ath5k_txbuf_free since we call it from atomic now. Signed-off-by: Jiri Slaby Cc: Nick Kossifidis Cc: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 15 ++++++++++++--- drivers/net/wireless/ath5k/base.h | 1 + 2 files changed, 13 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index b20a45a..7bc012f 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -251,7 +251,7 @@ static inline void ath5k_txbuf_free(struct ath5k_softc *sc, return; pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb(bf->skb); + dev_kfree_skb_any(bf->skb); bf->skb = NULL; } @@ -466,6 +466,7 @@ ath5k_pci_probe(struct pci_dev *pdev, mutex_init(&sc->lock); spin_lock_init(&sc->rxbuflock); spin_lock_init(&sc->txbuflock); + spin_lock_init(&sc->block); /* Set private data */ pci_set_drvdata(pdev, hw); @@ -2179,8 +2180,11 @@ ath5k_beacon_config(struct ath5k_softc *sc) sc->imask |= AR5K_INT_SWBA; - if (ath5k_hw_hasveol(ah)) + if (ath5k_hw_hasveol(ah)) { + spin_lock(&sc->block); ath5k_beacon_send(sc); + spin_unlock(&sc->block); + } } /* TODO else AP */ @@ -2403,7 +2407,9 @@ ath5k_intr(int irq, void *dev_id) TSF_TO_TU(tsf), (unsigned long long) tsf); } else { + spin_lock(&sc->block); ath5k_beacon_send(sc); + spin_unlock(&sc->block); } } if (status & AR5K_INT_RXEOL) { @@ -3050,6 +3056,7 @@ static int ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) { struct ath5k_softc *sc = hw->priv; + unsigned long flags; int ret; ath5k_debug_dump_skb(sc, skb, "BC ", 1); @@ -3059,12 +3066,14 @@ ath5k_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) goto end; } + spin_lock_irqsave(&sc->block, flags); ath5k_txbuf_free(sc, sc->bbuf); sc->bbuf->skb = skb; ret = ath5k_beacon_setup(sc, sc->bbuf); if (ret) sc->bbuf->skb = NULL; - else { + spin_unlock_irqrestore(&sc->block, flags); + if (!ret) { ath5k_beacon_config(sc); mmiowb(); } diff --git a/drivers/net/wireless/ath5k/base.h b/drivers/net/wireless/ath5k/base.h index d7e03e6..7ec2f37 100644 --- a/drivers/net/wireless/ath5k/base.h +++ b/drivers/net/wireless/ath5k/base.h @@ -172,6 +172,7 @@ struct ath5k_softc { struct tasklet_struct txtq; /* tx intr tasklet */ struct ath5k_led tx_led; /* tx led */ + spinlock_t block; /* protects beacon */ struct ath5k_buf *bbuf; /* beacon buffer */ unsigned int bhalq, /* SW q for outgoing beacons */ bmisscount, /* missed beacon transmits */ -- cgit v1.1 From 67d2e2dfab31b4c0497ce8a84d63efc931f10bb7 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Mon, 18 Aug 2008 21:45:28 +0200 Subject: Ath5k: fix bintval setup bintval is set to the initial value at .config_interface which is too late, since it overwrites previously set value from .config. Move the initialization to the .add_interface. Signed-off-by: Jiri Slaby Cc: Nick Kossifidis Cc: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath5k/base.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 7bc012f..0676c6d 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c @@ -2751,6 +2751,11 @@ static int ath5k_add_interface(struct ieee80211_hw *hw, ret = -EOPNOTSUPP; goto end; } + + /* Set to a reasonable value. Note that this will + * be set to mac80211's value at ath5k_config(). */ + sc->bintval = 1000; + ret = 0; end: mutex_unlock(&sc->lock); @@ -2795,9 +2800,6 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ath5k_hw *ah = sc->ah; int ret; - /* Set to a reasonable value. Note that this will - * be set to mac80211's value at ath5k_config(). */ - sc->bintval = 1000; mutex_lock(&sc->lock); if (sc->vif != vif) { ret = -EIO; -- cgit v1.1 From 639f6571458948b5112be2cf00c0c2c04db2897d Mon Sep 17 00:00:00 2001 From: Bryan Wu Date: Wed, 27 Aug 2008 10:51:02 +0800 Subject: Blackfin arch: move include/asm-blackfin header files to arch/blackfin Signed-off-by: Bryan Wu --- drivers/input/keyboard/bf54x-keys.c | 2 +- drivers/serial/bfin_5xx.c | 2 +- drivers/video/bf54x-lq043fb.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index 6f227d3..e348cfc 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -43,7 +43,7 @@ #include #include -#include +#include #define DRV_NAME "bf54x-keys" #define TIME_SCALE 100 /* 100 ns */ diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index efcd443..4a0d30b 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c @@ -28,7 +28,7 @@ #endif #include -#include +#include #ifdef CONFIG_SERIAL_BFIN_DMA #include diff --git a/drivers/video/bf54x-lq043fb.c b/drivers/video/bf54x-lq043fb.c index 6d5aa80..7644ed2 100644 --- a/drivers/video/bf54x-lq043fb.c +++ b/drivers/video/bf54x-lq043fb.c @@ -58,7 +58,7 @@ #include #include -#include +#include #define NO_BL_SUPPORT -- cgit v1.1 From abf5439370491dd6fbb4fe1a7939680d2a9bc9d4 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 16 Aug 2008 14:10:05 +0900 Subject: block: move cmdfilter from gendisk to request_queue cmd_filter works only for the block layer SG_IO with SCSI block devices. It breaks scsi/sg.c, bsg, and the block layer SG_IO with SCSI character devices (such as st). We hit a kernel crash with them. The problem is that cmd_filter code accesses to gendisk (having struct blk_scsi_cmd_filter) via inode->i_bdev->bd_disk. It works for only SCSI block device files. With character device files, inode->i_bdev leads you to struct cdev. inode->i_bdev->bd_disk->blk_scsi_cmd_filter isn't safe. SCSI ULDs don't expose gendisk; they keep it private. bsg needs to be independent on any protocols. We shouldn't change ULDs to expose their gendisk. This patch moves struct blk_scsi_cmd_filter from gendisk to request_queue, a common object, which eveyone can access to. The user interface doesn't change; users can change the filters via /sys/block/. gendisk has a pointer to request_queue so the cmd_filter code accesses to struct blk_scsi_cmd_filter. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 3d36270..9d28b9f 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -641,6 +641,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, unsigned char cmnd[MAX_COMMAND_SIZE]; int timeout; unsigned long ul_timeout; + struct request_queue *q; if (count < SZ_SG_IO_HDR) return -EINVAL; @@ -689,7 +690,9 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, sg_remove_request(sfp, srp); return -EFAULT; } - if (read_only && !blk_verify_command(file, cmnd)) { + q = sfp->parentdp->device->request_queue; + if (read_only && blk_verify_command(&q->cmd_filter, cmnd, + file->f_mode & FMODE_WRITE)) { sg_remove_request(sfp, srp); return -EPERM; } @@ -793,6 +796,7 @@ sg_ioctl(struct inode *inode, struct file *filp, if ((!(sfp = (Sg_fd *) filp->private_data)) || (!(sdp = sfp->parentdp))) return -ENXIO; + SCSI_LOG_TIMEOUT(3, printk("sg_ioctl: %s, cmd=0x%x\n", sdp->disk->disk_name, (int) cmd_in)); read_only = (O_RDWR != (filp->f_flags & O_ACCMODE)); @@ -1057,11 +1061,14 @@ sg_ioctl(struct inode *inode, struct file *filp, return -ENODEV; if (read_only) { unsigned char opcode = WRITE_6; + struct request_queue *q = sdp->device->request_queue; Scsi_Ioctl_Command __user *siocp = p; if (copy_from_user(&opcode, siocp->data, 1)) return -EFAULT; - if (!blk_verify_command(filp, &opcode)) + if (blk_verify_command(&q->cmd_filter, + &opcode, + filp->f_mode & FMODE_WRITE)) return -EPERM; } return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p); -- cgit v1.1 From 14e507b852e7dcea142b98757181bfa785cb4c05 Mon Sep 17 00:00:00 2001 From: FUJITA Tomonori Date: Sat, 26 Jul 2008 18:03:24 +0900 Subject: sg: restore command permission for TYPE_SCANNER sg allowed any command for TYPE_SCANNER. The cmd_filter patchset doesn't. We can't change sg's permission since it might break the existing software. Signed-off-by: FUJITA Tomonori Signed-off-by: Jens Axboe --- drivers/scsi/sg.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index 9d28b9f..661f9f2 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c @@ -217,6 +217,18 @@ static int sg_last_dev(void); #define SZ_SG_IOVEC sizeof(sg_iovec_t) #define SZ_SG_REQ_INFO sizeof(sg_req_info_t) +static int sg_allow_access(struct file *filp, unsigned char *cmd) +{ + struct sg_fd *sfp = (struct sg_fd *)filp->private_data; + struct request_queue *q = sfp->parentdp->device->request_queue; + + if (sfp->parentdp->device->type == TYPE_SCANNER) + return 0; + + return blk_verify_command(&q->cmd_filter, + cmd, filp->f_mode & FMODE_WRITE); +} + static int sg_open(struct inode *inode, struct file *filp) { @@ -641,7 +653,6 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, unsigned char cmnd[MAX_COMMAND_SIZE]; int timeout; unsigned long ul_timeout; - struct request_queue *q; if (count < SZ_SG_IO_HDR) return -EINVAL; @@ -690,9 +701,7 @@ sg_new_write(Sg_fd *sfp, struct file *file, const char __user *buf, sg_remove_request(sfp, srp); return -EFAULT; } - q = sfp->parentdp->device->request_queue; - if (read_only && blk_verify_command(&q->cmd_filter, cmnd, - file->f_mode & FMODE_WRITE)) { + if (read_only && sg_allow_access(file, cmnd)) { sg_remove_request(sfp, srp); return -EPERM; } @@ -1061,14 +1070,11 @@ sg_ioctl(struct inode *inode, struct file *filp, return -ENODEV; if (read_only) { unsigned char opcode = WRITE_6; - struct request_queue *q = sdp->device->request_queue; Scsi_Ioctl_Command __user *siocp = p; if (copy_from_user(&opcode, siocp->data, 1)) return -EFAULT; - if (blk_verify_command(&q->cmd_filter, - &opcode, - filp->f_mode & FMODE_WRITE)) + if (sg_allow_access(filp, &opcode)) return -EPERM; } return sg_scsi_ioctl(filp, sdp->device->request_queue, NULL, p); -- cgit v1.1 From 736783b8528bdce7f090dfae66f57411be40c5f8 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Wed, 27 Aug 2008 11:47:57 +0800 Subject: Blackfin EMAC Driver: the BF526 also supports the MAC, so update things accordingly Signed-off-by: Mike Frysinger Signed-off-by: Bryan Wu Signed-off-by: Jeff Garzik --- drivers/net/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index a5c141c..4a11296 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -822,14 +822,14 @@ config ULTRA32 will be called smc-ultra32. config BFIN_MAC - tristate "Blackfin 527/536/537 on-chip mac support" - depends on NET_ETHERNET && (BF527 || BF537 || BF536) + tristate "Blackfin on-chip MAC support" + depends on NET_ETHERNET && (BF526 || BF527 || BF536 || BF537) select CRC32 select MII select PHYLIB select BFIN_MAC_USE_L1 if DMA_UNCACHED_NONE help - This is the driver for blackfin on-chip mac device. Say Y if you want it + This is the driver for Blackfin on-chip mac device. Say Y if you want it compiled into the kernel. This driver is also available as a module ( = code which can be inserted in and removed from the running kernel whenever you want). The module will be called bfin_mac. -- cgit v1.1 From 3d01625a4f30ec9db8e964b7fde1f902f522e992 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 26 Aug 2008 18:30:04 -0700 Subject: ixgbe: fix vlan filtering VLAN filtering is broken, due to reading the incorrect register for the VLAN filtering settings. Fixed by reading/writing the correct register. Signed-off-by: Alexander Duyck Signed-off-by: Jesse Brandeburg Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/ixgbe/ixgbe_main.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ixgbe/ixgbe_main.c b/drivers/net/ixgbe/ixgbe_main.c index 34bca16..53f41b6 100644 --- a/drivers/net/ixgbe/ixgbe_main.c +++ b/drivers/net/ixgbe/ixgbe_main.c @@ -1636,16 +1636,17 @@ static void ixgbe_set_multi(struct net_device *netdev) struct ixgbe_hw *hw = &adapter->hw; struct dev_mc_list *mc_ptr; u8 *mta_list; - u32 fctrl; + u32 fctrl, vlnctrl; int i; /* Check for Promiscuous and All Multicast modes */ fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL); + vlnctrl = IXGBE_READ_REG(hw, IXGBE_VLNCTRL); if (netdev->flags & IFF_PROMISC) { fctrl |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); - fctrl &= ~IXGBE_VLNCTRL_VFE; + vlnctrl &= ~IXGBE_VLNCTRL_VFE; } else { if (netdev->flags & IFF_ALLMULTI) { fctrl |= IXGBE_FCTRL_MPE; @@ -1653,10 +1654,11 @@ static void ixgbe_set_multi(struct net_device *netdev) } else { fctrl &= ~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); } - fctrl |= IXGBE_VLNCTRL_VFE; + vlnctrl |= IXGBE_VLNCTRL_VFE; } IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl); + IXGBE_WRITE_REG(hw, IXGBE_VLNCTRL, vlnctrl); if (netdev->mc_count) { mta_list = kcalloc(netdev->mc_count, ETH_ALEN, GFP_ATOMIC); -- cgit v1.1 From 0623807a18c4baa2effcdb298e8b31d90e3ef69f Mon Sep 17 00:00:00 2001 From: Brice Goglin Date: Tue, 26 Aug 2008 23:29:12 +0200 Subject: myri10ge: update version string to 1.4.3-1.358 Update myri10ge version string to 1.4.3-1.358. Signed-off-by: Brice Goglin Signed-off-by: Jeff Garzik --- drivers/net/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c index 5d76cd0..f684753 100644 --- a/drivers/net/myri10ge/myri10ge.c +++ b/drivers/net/myri10ge/myri10ge.c @@ -76,7 +76,7 @@ #include "myri10ge_mcp.h" #include "myri10ge_mcp_gen_header.h" -#define MYRI10GE_VERSION_STR "1.3.99-1.347" +#define MYRI10GE_VERSION_STR "1.4.3-1.358" MODULE_DESCRIPTION("Myricom 10G driver (10GbE)"); MODULE_AUTHOR("Maintainer: help@myri.com"); -- cgit v1.1 From a866bbf6aacf95f849810079442a20be118ce905 Mon Sep 17 00:00:00 2001 From: Francois Romieu Date: Tue, 26 Aug 2008 21:56:06 +0200 Subject: r8169: balance pci_map / pci_unmap pair MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The leak hurts with swiotlb and jumbo frames. Fix http://bugzilla.kernel.org/show_bug.cgi?id=9468. Heavily hinted by Ilpo Järvinen . Signed-off-by: Francois Romieu Tested-by: Alistair John Strachan Tested-by: Timothy J Fontaine Cc: Edward Hsu Signed-off-by: Jeff Garzik --- drivers/net/r8169.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index a3e3895..0f6f974 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -2792,7 +2792,7 @@ static int rtl8169_rx_interrupt(struct net_device *dev, pkt_size, PCI_DMA_FROMDEVICE); rtl8169_mark_to_asic(desc, tp->rx_buf_sz); } else { - pci_unmap_single(pdev, addr, pkt_size, + pci_unmap_single(pdev, addr, tp->rx_buf_sz, PCI_DMA_FROMDEVICE); tp->Rx_skbuff[entry] = NULL; } -- cgit v1.1 From 7a6ea550f2f7592742ac765e5a3b4b5d1461e0bd Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 26 Aug 2008 04:25:03 -0700 Subject: igb: force all queues to interrupt once every 2 seconds Set the EICS bit for each of the RX queues at least once every 2 seconds to prevent the rx queues from stalling. Signed-off-by: Jeff Kirsher Signed-off-by: Alexander Duyck Signed-off-by: Jeff Garzik --- drivers/net/igb/igb_main.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 8f66e15..465a810 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -2290,7 +2290,9 @@ static void igb_watchdog_task(struct work_struct *work) struct igb_ring *tx_ring = adapter->tx_ring; struct e1000_mac_info *mac = &adapter->hw.mac; u32 link; + u32 eics = 0; s32 ret_val; + int i; if ((netif_carrier_ok(netdev)) && (rd32(E1000_STATUS) & E1000_STATUS_LU)) @@ -2392,7 +2394,13 @@ link_up: } /* Cause software interrupt to ensure rx ring is cleaned */ - wr32(E1000_ICS, E1000_ICS_RXDMT0); + if (adapter->msix_entries) { + for (i = 0; i < adapter->num_rx_queues; i++) + eics |= adapter->rx_ring[i].eims_value; + wr32(E1000_EICS, eics); + } else { + wr32(E1000_ICS, E1000_ICS_RXDMT0); + } /* Force detection of hung controller every watchdog period */ tx_ring->detect_tx_hung = true; -- cgit v1.1 From fe59de38c58d3eedc025be61ff3055a41776bbd4 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 26 Aug 2008 04:25:05 -0700 Subject: igb: ethtool -d reads EICR which is incorrect as it is read on clear Ethtool -d is reading the EICR and ICR registers which is currently clearing these registers and masking off interrupts. To prevent this we read the EICS and ICS equivilents as they can be read without clearing or masking. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/igb/igb_ethtool.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 11aee13..3eb78a6 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -373,13 +373,17 @@ static void igb_get_regs(struct net_device *netdev, regs_buff[12] = rd32(E1000_EECD); /* Interrupt */ - regs_buff[13] = rd32(E1000_EICR); + /* Reading EICS for EICR because they read the + * same but EICS does not clear on read */ + regs_buff[13] = rd32(E1000_EICS); regs_buff[14] = rd32(E1000_EICS); regs_buff[15] = rd32(E1000_EIMS); regs_buff[16] = rd32(E1000_EIMC); regs_buff[17] = rd32(E1000_EIAC); regs_buff[18] = rd32(E1000_EIAM); - regs_buff[19] = rd32(E1000_ICR); + /* Reading ICS for ICR because they read the + * same but ICS does not clear on read */ + regs_buff[19] = rd32(E1000_ICS); regs_buff[20] = rd32(E1000_ICS); regs_buff[21] = rd32(E1000_IMS); regs_buff[22] = rd32(E1000_IMC); -- cgit v1.1 From 34a20e89739e9ac1cb89bdf430b694d2c946ebff Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Tue, 26 Aug 2008 04:25:13 -0700 Subject: igb: fix setting the number of tx queues The real_num_tx_queues was not being set when in MSI-X only mode. This patch corrects that path so all interrupt types are correctly configured. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/igb/igb_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index 465a810..e6eb13a 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -521,7 +521,7 @@ static void igb_set_interrupt_capability(struct igb_adapter *adapter) adapter->msix_entries, numvecs); if (err == 0) - return; + goto out; igb_reset_interrupt_capability(adapter); @@ -531,7 +531,7 @@ msi_only: adapter->num_tx_queues = 1; if (!pci_enable_msi(adapter->pdev)) adapter->flags |= IGB_FLAG_HAS_MSI; - +out: /* Notify the stack of the (possibly) reduced Tx Queue count. */ adapter->netdev->real_num_tx_queues = adapter->num_tx_queues; return; -- cgit v1.1 From f4f62301c6f42127b7462274abfcbc278f84d59a Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Mon, 25 Aug 2008 20:20:53 -0500 Subject: fs_enet: Fix SCC Ethernet on CPM2, and crash in fs_enet_rx_napi() Signed-off-by: Heiko Schocher Signed-off-by: Vitaly Bordug Signed-off-by: Kumar Gala Signed-off-by: Jeff Garzik --- drivers/net/fs_enet/fs_enet-main.c | 8 ++++++++ drivers/net/fs_enet/mac-scc.c | 8 +++++++- 2 files changed, 15 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/fs_enet/fs_enet-main.c b/drivers/net/fs_enet/fs_enet-main.c index 9a51ec8..9d46182 100644 --- a/drivers/net/fs_enet/fs_enet-main.c +++ b/drivers/net/fs_enet/fs_enet-main.c @@ -792,6 +792,10 @@ static int fs_enet_open(struct net_device *dev) int r; int err; + /* to initialize the fep->cur_rx,... */ + /* not doing this, will cause a crash in fs_enet_rx_napi */ + fs_init_bds(fep->ndev); + if (fep->fpi->use_napi) napi_enable(&fep->napi); @@ -1167,6 +1171,10 @@ static struct of_device_id fs_enet_match[] = { .compatible = "fsl,cpm1-scc-enet", .data = (void *)&fs_scc_ops, }, + { + .compatible = "fsl,cpm2-scc-enet", + .data = (void *)&fs_scc_ops, + }, #endif #ifdef CONFIG_FS_ENET_HAS_FCC { diff --git a/drivers/net/fs_enet/mac-scc.c b/drivers/net/fs_enet/mac-scc.c index 029b3c7e..22f50dd 100644 --- a/drivers/net/fs_enet/mac-scc.c +++ b/drivers/net/fs_enet/mac-scc.c @@ -47,7 +47,6 @@ #include "fs_enet.h" /*************************************************/ - #if defined(CONFIG_CPM1) /* for a 8xx __raw_xxx's are sufficient */ #define __fs_out32(addr, x) __raw_writel(x, addr) @@ -62,6 +61,8 @@ #define __fs_out16(addr, x) out_be16(addr, x) #define __fs_in32(addr) in_be32(addr) #define __fs_in16(addr) in_be16(addr) +#define __fs_out8(addr, x) out_8(addr, x) +#define __fs_in8(addr) in_8(addr) #endif /* write, read, set bits, clear bits */ @@ -262,8 +263,13 @@ static void restart(struct net_device *dev) /* Initialize function code registers for big-endian. */ +#ifndef CONFIG_NOT_COHERENT_CACHE + W8(ep, sen_genscc.scc_rfcr, SCC_EB | SCC_GBL); + W8(ep, sen_genscc.scc_tfcr, SCC_EB | SCC_GBL); +#else W8(ep, sen_genscc.scc_rfcr, SCC_EB); W8(ep, sen_genscc.scc_tfcr, SCC_EB); +#endif /* Set maximum bytes per receive buffer. * This appears to be an Ethernet frame size, not the buffer -- cgit v1.1 From d3d7b53d1ae46534cd73e1073a5c29e3b61a0552 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Fri, 22 Aug 2008 19:24:15 +0100 Subject: [netdrvr] fix build issue: undefined reference to `NS8390p_init' Signed-off-by: Alan 'pass the paper bags' Cox Signed-off-by: Jeff Garzik --- drivers/net/wd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/wd.c b/drivers/net/wd.c index 6f9aa16..fa14255 100644 --- a/drivers/net/wd.c +++ b/drivers/net/wd.c @@ -337,7 +337,7 @@ static int __init wd_probe1(struct net_device *dev, int ioaddr) #ifdef CONFIG_NET_POLL_CONTROLLER dev->poll_controller = ei_poll; #endif - NS8390p_init(dev, 0); + NS8390_init(dev, 0); #if 1 /* Enable interrupt generation on softconfig cards -- M.U */ -- cgit v1.1 From 2b356b463933031374c373f70d9a3b14ec707161 Mon Sep 17 00:00:00 2001 From: Martin Schwidefsky Date: Thu, 21 Aug 2008 17:10:22 +0200 Subject: claw: fix memory leak in claw_probe. probe_error() frees memory only, if cgdev->dev.driver_data refers to the claw_privbk structure. Move forward its setting in claw_probe() to ensure proper freeing of claw_privbk allocations. Cc: Daniel Signed-off-by: Martin Schwidefsky Signed-off-by: Ursula Braun Signed-off-by: Jeff Garzik --- drivers/s390/net/claw.c | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index a08b168..cc5697d 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -271,6 +271,7 @@ claw_probe(struct ccwgroup_device *cgdev) if (!get_device(&cgdev->dev)) return -ENODEV; privptr = kzalloc(sizeof(struct claw_privbk), GFP_KERNEL); + cgdev->dev.driver_data = privptr; if (privptr == NULL) { probe_error(cgdev); put_device(&cgdev->dev); @@ -305,7 +306,6 @@ claw_probe(struct ccwgroup_device *cgdev) privptr->p_env->p_priv = privptr; cgdev->cdev[0]->handler = claw_irq_handler; cgdev->cdev[1]->handler = claw_irq_handler; - cgdev->dev.driver_data = privptr; CLAW_DBF_TEXT(2, setup, "prbext 0"); return 0; @@ -1960,19 +1960,16 @@ init_ccw_bk(struct net_device *dev) static void probe_error( struct ccwgroup_device *cgdev) { - struct claw_privbk *privptr; + struct claw_privbk *privptr; CLAW_DBF_TEXT(4, trace, "proberr"); - privptr=(struct claw_privbk *)cgdev->dev.driver_data; - if (privptr!=NULL) { + privptr = (struct claw_privbk *) cgdev->dev.driver_data; + if (privptr != NULL) { + cgdev->dev.driver_data = NULL; kfree(privptr->p_env); - privptr->p_env=NULL; - kfree(privptr->p_mtc_envelope); - privptr->p_mtc_envelope=NULL; - kfree(privptr); - privptr=NULL; - } - return; + kfree(privptr->p_mtc_envelope); + kfree(privptr); + } } /* probe_error */ /*-------------------------------------------------------------------* -- cgit v1.1 From 6951df34d50330f1b117fd8371d7f7df39f43f6a Mon Sep 17 00:00:00 2001 From: Peter Tiedemann Date: Thu, 21 Aug 2008 17:10:23 +0200 Subject: claw: netdev->priv vs. netdev->ml_priv Use netdev->ml_priv instead of netdev->priv Signed-off-by: Peter Tiedemann Signed-off-by: Ursula Braun Signed-off-by: Jeff Garzik --- drivers/s390/net/claw.c | 60 ++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index cc5697d..e10ac9a 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c @@ -133,14 +133,14 @@ claw_register_debug_facility(void) static inline void claw_set_busy(struct net_device *dev) { - ((struct claw_privbk *) dev->priv)->tbusy=1; + ((struct claw_privbk *)dev->ml_priv)->tbusy = 1; eieio(); } static inline void claw_clear_busy(struct net_device *dev) { - clear_bit(0, &(((struct claw_privbk *) dev->priv)->tbusy)); + clear_bit(0, &(((struct claw_privbk *) dev->ml_priv)->tbusy)); netif_wake_queue(dev); eieio(); } @@ -149,20 +149,20 @@ static inline int claw_check_busy(struct net_device *dev) { eieio(); - return ((struct claw_privbk *) dev->priv)->tbusy; + return ((struct claw_privbk *) dev->ml_priv)->tbusy; } static inline void claw_setbit_busy(int nr,struct net_device *dev) { netif_stop_queue(dev); - set_bit(nr, (void *)&(((struct claw_privbk *)dev->priv)->tbusy)); + set_bit(nr, (void *)&(((struct claw_privbk *)dev->ml_priv)->tbusy)); } static inline void claw_clearbit_busy(int nr,struct net_device *dev) { - clear_bit(nr,(void *)&(((struct claw_privbk *)dev->priv)->tbusy)); + clear_bit(nr, (void *)&(((struct claw_privbk *)dev->ml_priv)->tbusy)); netif_wake_queue(dev); } @@ -171,7 +171,7 @@ claw_test_and_setbit_busy(int nr,struct net_device *dev) { netif_stop_queue(dev); return test_and_set_bit(nr, - (void *)&(((struct claw_privbk *) dev->priv)->tbusy)); + (void *)&(((struct claw_privbk *) dev->ml_priv)->tbusy)); } @@ -319,7 +319,7 @@ static int claw_tx(struct sk_buff *skb, struct net_device *dev) { int rc; - struct claw_privbk *privptr=dev->priv; + struct claw_privbk *privptr = dev->ml_priv; unsigned long saveflags; struct chbk *p_ch; @@ -404,7 +404,7 @@ claw_pack_skb(struct claw_privbk *privptr) static int claw_change_mtu(struct net_device *dev, int new_mtu) { - struct claw_privbk *privptr=dev->priv; + struct claw_privbk *privptr = dev->ml_priv; int buff_size; CLAW_DBF_TEXT(4, trace, "setmtu"); buff_size = privptr->p_env->write_size; @@ -434,7 +434,7 @@ claw_open(struct net_device *dev) struct ccwbk *p_buf; CLAW_DBF_TEXT(4, trace, "open"); - privptr = (struct claw_privbk *)dev->priv; + privptr = (struct claw_privbk *)dev->ml_priv; /* allocate and initialize CCW blocks */ if (privptr->buffs_alloc == 0) { rc=init_ccw_bk(dev); @@ -780,7 +780,7 @@ claw_irq_tasklet ( unsigned long data ) p_ch = (struct chbk *) data; dev = (struct net_device *)p_ch->ndev; CLAW_DBF_TEXT(4, trace, "IRQtask"); - privptr = (struct claw_privbk *) dev->priv; + privptr = (struct claw_privbk *)dev->ml_priv; unpack_read(dev); clear_bit(CLAW_BH_ACTIVE, (void *)&p_ch->flag_a); CLAW_DBF_TEXT(4, trace, "TskletXt"); @@ -805,7 +805,7 @@ claw_release(struct net_device *dev) if (!dev) return 0; - privptr = (struct claw_privbk *) dev->priv; + privptr = (struct claw_privbk *)dev->ml_priv; if (!privptr) return 0; CLAW_DBF_TEXT(4, trace, "release"); @@ -960,7 +960,7 @@ claw_write_next ( struct chbk * p_ch ) if (p_ch->claw_state == CLAW_STOP) return; dev = (struct net_device *) p_ch->ndev; - privptr = (struct claw_privbk *) dev->priv; + privptr = (struct claw_privbk *) dev->ml_priv; claw_free_wrt_buf( dev ); if ((privptr->write_free_count > 0) && !skb_queue_empty(&p_ch->collect_queue)) { @@ -1042,7 +1042,7 @@ add_claw_reads(struct net_device *dev, struct ccwbk* p_first, struct ccw1 temp_ccw; struct endccw * p_end; CLAW_DBF_TEXT(4, trace, "addreads"); - privptr = dev->priv; + privptr = dev->ml_priv; p_end = privptr->p_end_ccw; /* first CCW and last CCW contains a new set of read channel programs @@ -1212,7 +1212,7 @@ find_link(struct net_device *dev, char *host_name, char *ws_name ) int rc=0; CLAW_DBF_TEXT(2, setup, "findlink"); - privptr=dev->priv; + privptr = dev->ml_priv; p_env=privptr->p_env; switch (p_env->packing) { @@ -1264,7 +1264,7 @@ claw_hw_tx(struct sk_buff *skb, struct net_device *dev, long linkid) struct chbk *ch; CLAW_DBF_TEXT(4, trace, "hw_tx"); - privptr = (struct claw_privbk *) (dev->priv); + privptr = (struct claw_privbk *)(dev->ml_priv); p_ch=(struct chbk *)&privptr->channel[WRITE]; p_env =privptr->p_env; claw_free_wrt_buf(dev); /* Clean up free chain if posible */ @@ -1483,8 +1483,8 @@ init_ccw_bk(struct net_device *dev) struct ccwbk*p_last_CCWB; struct ccwbk*p_first_CCWB; struct endccw *p_endccw=NULL; - addr_t real_address; - struct claw_privbk *privptr=dev->priv; + addr_t real_address; + struct claw_privbk *privptr = dev->ml_priv; struct clawh *pClawH=NULL; addr_t real_TIC_address; int i,j; @@ -1997,7 +1997,7 @@ claw_process_control( struct net_device *dev, struct ccwbk * p_ccw) CLAW_DBF_TEXT(2, setup, "clw_cntl"); udelay(1000); /* Wait a ms for the control packets to *catch up to each other */ - privptr=dev->priv; + privptr = dev->ml_priv; p_env=privptr->p_env; tdev = &privptr->channel[READ].cdev->dev; memcpy( &temp_host_name, p_env->host_name, 8); @@ -2275,7 +2275,7 @@ claw_send_control(struct net_device *dev, __u8 type, __u8 link, struct sk_buff *skb; CLAW_DBF_TEXT(2, setup, "sndcntl"); - privptr=dev->priv; + privptr = dev->ml_priv; p_ctl=(struct clawctl *)&privptr->ctl_bk; p_ctl->command=type; @@ -2345,7 +2345,7 @@ static int claw_snd_conn_req(struct net_device *dev, __u8 link) { int rc; - struct claw_privbk *privptr=dev->priv; + struct claw_privbk *privptr = dev->ml_priv; struct clawctl *p_ctl; CLAW_DBF_TEXT(2, setup, "snd_conn"); @@ -2405,7 +2405,7 @@ claw_snd_sys_validate_rsp(struct net_device *dev, int rc; CLAW_DBF_TEXT(2, setup, "chkresp"); - privptr = dev->priv; + privptr = dev->ml_priv; p_env=privptr->p_env; rc=claw_send_control(dev, SYSTEM_VALIDATE_RESPONSE, p_ctl->linkid, @@ -2443,7 +2443,7 @@ net_device_stats *claw_stats(struct net_device *dev) struct claw_privbk *privptr; CLAW_DBF_TEXT(4, trace, "stats"); - privptr = dev->priv; + privptr = dev->ml_priv; return &privptr->stats; } /* end of claw_stats */ @@ -2479,7 +2479,7 @@ unpack_read(struct net_device *dev ) p_last_ccw=NULL; p_packh=NULL; p_packd=NULL; - privptr=dev->priv; + privptr = dev->ml_priv; p_dev = &privptr->channel[READ].cdev->dev; p_env = privptr->p_env; @@ -2648,7 +2648,7 @@ claw_strt_read (struct net_device *dev, int lock ) int rc = 0; __u32 parm; unsigned long saveflags = 0; - struct claw_privbk *privptr=dev->priv; + struct claw_privbk *privptr = dev->ml_priv; struct ccwbk*p_ccwbk; struct chbk *p_ch; struct clawh *p_clawh; @@ -2705,7 +2705,7 @@ claw_strt_out_IO( struct net_device *dev ) if (!dev) { return; } - privptr=(struct claw_privbk *)dev->priv; + privptr = (struct claw_privbk *)dev->ml_priv; p_ch=&privptr->channel[WRITE]; CLAW_DBF_TEXT(4, trace, "strt_io"); @@ -2738,7 +2738,7 @@ static void claw_free_wrt_buf( struct net_device *dev ) { - struct claw_privbk *privptr=(struct claw_privbk *)dev->priv; + struct claw_privbk *privptr = (struct claw_privbk *)dev->ml_priv; struct ccwbk*p_first_ccw; struct ccwbk*p_last_ccw; struct ccwbk*p_this_ccw; @@ -2795,13 +2795,13 @@ claw_free_netdevice(struct net_device * dev, int free_dev) if (!dev) return; CLAW_DBF_TEXT_(2, setup, "%s", dev->name); - privptr = dev->priv; + privptr = dev->ml_priv; if (dev->flags & IFF_RUNNING) claw_release(dev); if (privptr) { privptr->channel[READ].ndev = NULL; /* say it's free */ } - dev->priv=NULL; + dev->ml_priv = NULL; #ifdef MODULE if (free_dev) { free_netdev(dev); @@ -2918,7 +2918,7 @@ claw_new_device(struct ccwgroup_device *cgdev) printk(KERN_WARNING "%s:alloc_netdev failed\n",__func__); goto out; } - dev->priv = privptr; + dev->ml_priv = privptr; cgdev->dev.driver_data = privptr; cgdev->cdev[READ]->dev.driver_data = privptr; cgdev->cdev[WRITE]->dev.driver_data = privptr; @@ -2999,7 +2999,7 @@ claw_shutdown_device(struct ccwgroup_device *cgdev) ret = claw_release(ndev); ndev->flags &=~IFF_RUNNING; unregister_netdev(ndev); - ndev->priv = NULL; /* cgdev data, not ndev's to free */ + ndev->ml_priv = NULL; /* cgdev data, not ndev's to free */ claw_free_netdevice(ndev, 1); priv->channel[READ].ndev = NULL; priv->channel[WRITE].ndev = NULL; -- cgit v1.1 From 261893d30b0ddb5587f9143df18a6efed39a7ed6 Mon Sep 17 00:00:00 2001 From: Peter Tiedemann Date: Thu, 21 Aug 2008 17:10:24 +0200 Subject: ctcm: netdev->priv vs. netdev->ml_priv Use netdev->ml_priv instead of netdev->priv Signed-off-by: Peter Tiedemann Signed-off-by: Ursula Braun Signed-off-by: Jeff Garzik --- drivers/s390/net/ctcm_fsms.c | 56 ++++++++++++++++++++++---------------------- drivers/s390/net/ctcm_main.c | 24 +++++++++---------- drivers/s390/net/ctcm_main.h | 9 +++---- drivers/s390/net/ctcm_mpc.c | 46 ++++++++++++++++++------------------ 4 files changed, 68 insertions(+), 67 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/ctcm_fsms.c b/drivers/s390/net/ctcm_fsms.c index 0b4e625..4277655 100644 --- a/drivers/s390/net/ctcm_fsms.c +++ b/drivers/s390/net/ctcm_fsms.c @@ -245,7 +245,7 @@ static void chx_txdone(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct sk_buff *skb; int first = 1; int i; @@ -336,7 +336,7 @@ void ctcm_chx_txidle(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; CTCM_PR_DEBUG("%s(%s): %s\n", __func__, ch->id, dev->name); @@ -357,7 +357,7 @@ static void chx_rx(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; int len = ch->max_bufsize - ch->irb->scsw.cmd.count; struct sk_buff *skb = ch->trans_skb; __u16 block_len = *((__u16 *)skb->data); @@ -459,7 +459,7 @@ static void chx_firstio(fsm_instance *fi, int event, void *arg) chx_rxidle(fi, event, arg); } else { struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; fsm_newstate(fi, CTC_STATE_TXIDLE); fsm_event(priv->fsm, DEV_EVENT_TXUP, dev); } @@ -496,7 +496,7 @@ static void chx_firstio(fsm_instance *fi, int event, void *arg) if ((CHANNEL_DIRECTION(ch->flags) == READ) && (ch->protocol == CTCM_PROTO_S390)) { struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; fsm_event(priv->fsm, DEV_EVENT_RXUP, dev); } } @@ -514,7 +514,7 @@ static void chx_rxidle(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; __u16 buflen; int rc; @@ -699,7 +699,7 @@ static void ctcm_chx_cleanup(fsm_instance *fi, int state, struct channel *ch) { struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; CTCM_DBF_TEXT_(SETUP, CTC_DBF_NOTICE, "%s(%s): %s[%d]\n", @@ -784,7 +784,7 @@ static void ctcm_chx_setuperr(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; /* * Special case: Got UC_RCRESET on setmode. @@ -874,7 +874,7 @@ static void ctcm_chx_rxiniterr(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; if (event == CTC_EVENT_TIMER) { if (!IS_MPCDEV(dev)) @@ -902,7 +902,7 @@ static void ctcm_chx_rxinitfail(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, "%s(%s): RX %s busy, init. fail", @@ -923,7 +923,7 @@ static void ctcm_chx_rxdisc(fsm_instance *fi, int event, void *arg) struct channel *ch = arg; struct channel *ch2; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; CTCM_DBF_TEXT_(TRACE, CTC_DBF_NOTICE, "%s: %s: remote disconnect - re-init ...", @@ -954,7 +954,7 @@ static void ctcm_chx_txiniterr(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; if (event == CTC_EVENT_TIMER) { fsm_deltimer(&ch->timer); @@ -984,7 +984,7 @@ static void ctcm_chx_txretry(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct sk_buff *skb; CTCM_PR_DEBUG("Enter: %s: cp=%i ch=0x%p id=%s\n", @@ -1057,7 +1057,7 @@ static void ctcm_chx_iofatal(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; int rd = CHANNEL_DIRECTION(ch->flags); fsm_deltimer(&ch->timer); @@ -1207,7 +1207,7 @@ static void ctcmpc_chx_txdone(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; struct sk_buff *skb; int first = 1; @@ -1368,7 +1368,7 @@ static void ctcmpc_chx_rx(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; struct sk_buff *skb = ch->trans_skb; struct sk_buff *new_skb; @@ -1471,7 +1471,7 @@ static void ctcmpc_chx_firstio(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *gptr = priv->mpcg; CTCM_PR_DEBUG("Enter %s: id=%s, ch=0x%p\n", @@ -1525,7 +1525,7 @@ void ctcmpc_chx_rxidle(fsm_instance *fi, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; int rc; unsigned long saveflags = 0; /* avoids compiler warning */ @@ -1580,7 +1580,7 @@ static void ctcmpc_chx_attn(fsm_instance *fsm, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; CTCM_PR_DEBUG("%s(%s): %s(ch=0x%p), cp=%i, ChStat:%s, GrpStat:%s\n", @@ -1639,7 +1639,7 @@ static void ctcmpc_chx_attnbusy(fsm_instance *fsm, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; CTCM_PR_DEBUG("%s(%s): %s\n ChState:%s GrpState:%s\n", @@ -1724,7 +1724,7 @@ static void ctcmpc_chx_resend(fsm_instance *fsm, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; fsm_event(grp->fsm, MPCG_EVENT_XID0DO, ch); @@ -1740,7 +1740,7 @@ static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg) { struct channel *ach = arg; struct net_device *dev = ach->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; struct channel *wch = priv->channel[WRITE]; struct channel *rch = priv->channel[READ]; @@ -2050,7 +2050,7 @@ int mpc_ch_fsm_len = ARRAY_SIZE(ctcmpc_ch_fsm); static void dev_action_start(fsm_instance *fi, int event, void *arg) { struct net_device *dev = arg; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; int direction; CTCMY_DBF_DEV_NAME(SETUP, dev, ""); @@ -2076,7 +2076,7 @@ static void dev_action_stop(fsm_instance *fi, int event, void *arg) { int direction; struct net_device *dev = arg; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; CTCMY_DBF_DEV_NAME(SETUP, dev, ""); @@ -2096,7 +2096,7 @@ static void dev_action_restart(fsm_instance *fi, int event, void *arg) { int restart_timer; struct net_device *dev = arg; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; CTCMY_DBF_DEV_NAME(TRACE, dev, ""); @@ -2133,12 +2133,12 @@ static void dev_action_restart(fsm_instance *fi, int event, void *arg) static void dev_action_chup(fsm_instance *fi, int event, void *arg) { struct net_device *dev = arg; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; int dev_stat = fsm_getstate(fi); CTCM_DBF_TEXT_(SETUP, CTC_DBF_NOTICE, "%s(%s): priv = %p [%d,%d]\n ", CTCM_FUNTAIL, - dev->name, dev->priv, dev_stat, event); + dev->name, dev->ml_priv, dev_stat, event); switch (fsm_getstate(fi)) { case DEV_STATE_STARTWAIT_RXTX: @@ -2195,7 +2195,7 @@ static void dev_action_chdown(fsm_instance *fi, int event, void *arg) { struct net_device *dev = arg; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; CTCMY_DBF_DEV_NAME(SETUP, dev, ""); diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 126a3eb..b11fec2 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c @@ -69,7 +69,7 @@ struct channel *channels; void ctcm_unpack_skb(struct channel *ch, struct sk_buff *pskb) { struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; __u16 len = *((__u16 *) pskb->data); skb_put(pskb, 2 + LL_HEADER_LENGTH); @@ -414,7 +414,7 @@ int ctcm_ch_alloc_buffer(struct channel *ch) */ int ctcm_open(struct net_device *dev) { - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; CTCMY_DBF_DEV_NAME(SETUP, dev, ""); if (!IS_MPC(priv)) @@ -432,7 +432,7 @@ int ctcm_open(struct net_device *dev) */ int ctcm_close(struct net_device *dev) { - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; CTCMY_DBF_DEV_NAME(SETUP, dev, ""); if (!IS_MPC(priv)) @@ -573,7 +573,7 @@ static int ctcm_transmit_skb(struct channel *ch, struct sk_buff *skb) skb_pull(skb, LL_HEADER_LENGTH + 2); } else if (ccw_idx == 0) { struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; priv->stats.tx_packets++; priv->stats.tx_bytes += skb->len - LL_HEADER_LENGTH; } @@ -592,7 +592,7 @@ static void ctcmpc_send_sweep_req(struct channel *rch) struct channel *ch; /* int rc = 0; */ - priv = dev->priv; + priv = dev->ml_priv; grp = priv->mpcg; ch = priv->channel[WRITE]; @@ -652,7 +652,7 @@ static int ctcmpc_transmit_skb(struct channel *ch, struct sk_buff *skb) { struct pdu *p_header; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; struct th_header *header; struct sk_buff *nskb; @@ -867,7 +867,7 @@ done: /* first merge version - leaving both functions separated */ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) { - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; if (skb == NULL) { CTCM_DBF_TEXT_(ERROR, CTC_DBF_ERROR, @@ -911,7 +911,7 @@ static int ctcm_tx(struct sk_buff *skb, struct net_device *dev) static int ctcmpc_tx(struct sk_buff *skb, struct net_device *dev) { int len = 0; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; struct sk_buff *newskb = NULL; @@ -1025,7 +1025,7 @@ static int ctcm_change_mtu(struct net_device *dev, int new_mtu) if (new_mtu < 576 || new_mtu > 65527) return -EINVAL; - priv = dev->priv; + priv = dev->ml_priv; max_bufsize = priv->channel[READ]->max_bufsize; if (IS_MPC(priv)) { @@ -1050,7 +1050,7 @@ static int ctcm_change_mtu(struct net_device *dev, int new_mtu) */ static struct net_device_stats *ctcm_stats(struct net_device *dev) { - return &((struct ctcm_priv *)dev->priv)->stats; + return &((struct ctcm_priv *)dev->ml_priv)->stats; } static void ctcm_free_netdevice(struct net_device *dev) @@ -1060,7 +1060,7 @@ static void ctcm_free_netdevice(struct net_device *dev) CTCM_DBF_TEXT_(SETUP, CTC_DBF_INFO, "%s(%s)", CTCM_FUNTAIL, dev->name); - priv = dev->priv; + priv = dev->ml_priv; if (priv) { grp = priv->mpcg; if (grp) { @@ -1125,7 +1125,7 @@ static struct net_device *ctcm_init_netdevice(struct ctcm_priv *priv) CTCM_FUNTAIL); return NULL; } - dev->priv = priv; + dev->ml_priv = priv; priv->fsm = init_fsm("ctcmdev", dev_state_names, dev_event_names, CTCM_NR_DEV_STATES, CTCM_NR_DEV_EVENTS, dev_fsm, dev_fsm_len, GFP_KERNEL); diff --git a/drivers/s390/net/ctcm_main.h b/drivers/s390/net/ctcm_main.h index a72e0fe..8e10ee8 100644 --- a/drivers/s390/net/ctcm_main.h +++ b/drivers/s390/net/ctcm_main.h @@ -229,14 +229,14 @@ void ctcm_remove_files(struct device *dev); */ static inline void ctcm_clear_busy_do(struct net_device *dev) { - clear_bit(0, &(((struct ctcm_priv *)dev->priv)->tbusy)); + clear_bit(0, &(((struct ctcm_priv *)dev->ml_priv)->tbusy)); netif_wake_queue(dev); } static inline void ctcm_clear_busy(struct net_device *dev) { struct mpc_group *grp; - grp = ((struct ctcm_priv *)dev->priv)->mpcg; + grp = ((struct ctcm_priv *)dev->ml_priv)->mpcg; if (!(grp && grp->in_sweep)) ctcm_clear_busy_do(dev); @@ -246,7 +246,8 @@ static inline void ctcm_clear_busy(struct net_device *dev) static inline int ctcm_test_and_set_busy(struct net_device *dev) { netif_stop_queue(dev); - return test_and_set_bit(0, &(((struct ctcm_priv *)dev->priv)->tbusy)); + return test_and_set_bit(0, + &(((struct ctcm_priv *)dev->ml_priv)->tbusy)); } extern int loglevel; @@ -292,7 +293,7 @@ struct mpc_group *ctcmpc_init_mpc_group(struct ctcm_priv *priv); #define IS_MPC(p) ((p)->protocol == CTCM_PROTO_MPC) /* test if struct ctcm_priv of struct net_device has MPC protocol setting */ -#define IS_MPCDEV(d) IS_MPC((struct ctcm_priv *)d->priv) +#define IS_MPCDEV(dev) IS_MPC((struct ctcm_priv *)dev->ml_priv) static inline gfp_t gfp_type(void) { diff --git a/drivers/s390/net/ctcm_mpc.c b/drivers/s390/net/ctcm_mpc.c index 49ae1cd..407f816 100644 --- a/drivers/s390/net/ctcm_mpc.c +++ b/drivers/s390/net/ctcm_mpc.c @@ -313,10 +313,10 @@ static struct net_device *ctcmpc_get_dev(int port_num) CTCM_FUNTAIL, device); return NULL; } - priv = dev->priv; + priv = dev->ml_priv; if (priv == NULL) { CTCM_DBF_TEXT_(MPC_ERROR, CTC_DBF_ERROR, - "%s(%s): dev->priv is NULL", + "%s(%s): dev->ml_priv is NULL", CTCM_FUNTAIL, device); return NULL; } @@ -345,7 +345,7 @@ int ctc_mpc_alloc_channel(int port_num, void (*callback)(int, int)) dev = ctcmpc_get_dev(port_num); if (dev == NULL) return 1; - priv = dev->priv; + priv = dev->ml_priv; grp = priv->mpcg; grp->allochanfunc = callback; @@ -417,7 +417,7 @@ void ctc_mpc_establish_connectivity(int port_num, dev = ctcmpc_get_dev(port_num); if (dev == NULL) return; - priv = dev->priv; + priv = dev->ml_priv; grp = priv->mpcg; rch = priv->channel[READ]; wch = priv->channel[WRITE]; @@ -535,7 +535,7 @@ void ctc_mpc_dealloc_ch(int port_num) dev = ctcmpc_get_dev(port_num); if (dev == NULL) return; - priv = dev->priv; + priv = dev->ml_priv; grp = priv->mpcg; CTCM_DBF_TEXT_(MPC_SETUP, CTC_DBF_DEBUG, @@ -571,7 +571,7 @@ void ctc_mpc_flow_control(int port_num, int flowc) dev = ctcmpc_get_dev(port_num); if (dev == NULL) return; - priv = dev->priv; + priv = dev->ml_priv; grp = priv->mpcg; CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_DEBUG, @@ -620,7 +620,7 @@ static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo) { struct channel *rch = mpcginfo->ch; struct net_device *dev = rch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; struct channel *ch = priv->channel[WRITE]; @@ -651,7 +651,7 @@ static void mpc_rcvd_sweep_resp(struct mpcg_info *mpcginfo) static void ctcmpc_send_sweep_resp(struct channel *rch) { struct net_device *dev = rch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; int rc = 0; struct th_sweep *header; @@ -713,7 +713,7 @@ static void mpc_rcvd_sweep_req(struct mpcg_info *mpcginfo) { struct channel *rch = mpcginfo->ch; struct net_device *dev = rch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; struct channel *ch = priv->channel[WRITE]; @@ -847,7 +847,7 @@ static int mpcg_fsm_len = ARRAY_SIZE(mpcg_fsm); static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg) { struct net_device *dev = arg; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; if (grp == NULL) { @@ -891,7 +891,7 @@ static void mpc_action_go_ready(fsm_instance *fsm, int event, void *arg) void mpc_group_ready(unsigned long adev) { struct net_device *dev = (struct net_device *)adev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; struct channel *ch = NULL; @@ -947,7 +947,7 @@ void mpc_group_ready(unsigned long adev) void mpc_channel_action(struct channel *ch, int direction, int action) { struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; if (grp == NULL) { @@ -1057,7 +1057,7 @@ done: static void ctcmpc_unpack_skb(struct channel *ch, struct sk_buff *pskb) { struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; struct pdu *curr_pdu; struct mpcg_info *mpcginfo; @@ -1255,7 +1255,7 @@ void ctcmpc_bh(unsigned long thischan) struct channel *ch = (struct channel *)thischan; struct sk_buff *skb; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; CTCM_PR_DEBUG("%s cp:%i enter: %s() %s\n", @@ -1377,7 +1377,7 @@ static void mpc_action_go_inop(fsm_instance *fi, int event, void *arg) BUG_ON(dev == NULL); CTCM_PR_DEBUG("Enter %s: %s\n", __func__, dev->name); - priv = dev->priv; + priv = dev->ml_priv; grp = priv->mpcg; grp->flow_off_called = 0; fsm_deltimer(&grp->timer); @@ -1483,7 +1483,7 @@ static void mpc_action_timeout(fsm_instance *fi, int event, void *arg) BUG_ON(dev == NULL); - priv = dev->priv; + priv = dev->ml_priv; grp = priv->mpcg; wch = priv->channel[WRITE]; rch = priv->channel[READ]; @@ -1521,7 +1521,7 @@ void mpc_action_discontact(fsm_instance *fi, int event, void *arg) if (ch) { dev = ch->netdev; if (dev) { - priv = dev->priv; + priv = dev->ml_priv; if (priv) { CTCM_DBF_TEXT_(MPC_TRACE, CTC_DBF_NOTICE, "%s: %s: %s\n", @@ -1569,7 +1569,7 @@ static int mpc_validate_xid(struct mpcg_info *mpcginfo) { struct channel *ch = mpcginfo->ch; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; struct xid2 *xid = mpcginfo->xid; int rc = 0; @@ -1866,7 +1866,7 @@ static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg) { struct channel *ch = arg; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n", @@ -1906,7 +1906,7 @@ static void mpc_action_doxid0(fsm_instance *fsm, int event, void *arg) static void mpc_action_doxid7(fsm_instance *fsm, int event, void *arg) { struct net_device *dev = arg; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = NULL; int direction; int send = 0; @@ -1983,7 +1983,7 @@ static void mpc_action_rcvd_xid0(fsm_instance *fsm, int event, void *arg) struct mpcg_info *mpcginfo = arg; struct channel *ch = mpcginfo->ch; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; CTCM_PR_DEBUG("%s: ch-id:%s xid2:%i xid7:%i xidt_p2:%i \n", @@ -2045,7 +2045,7 @@ static void mpc_action_rcvd_xid7(fsm_instance *fsm, int event, void *arg) struct mpcg_info *mpcginfo = arg; struct channel *ch = mpcginfo->ch; struct net_device *dev = ch->netdev; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; CTCM_PR_DEBUG("Enter %s: cp=%i ch=0x%p id=%s\n", @@ -2097,7 +2097,7 @@ static int mpc_send_qllc_discontact(struct net_device *dev) __u32 new_len = 0; struct sk_buff *skb; struct qllc *qllcptr; - struct ctcm_priv *priv = dev->priv; + struct ctcm_priv *priv = dev->ml_priv; struct mpc_group *grp = priv->mpcg; CTCM_PR_DEBUG("%s: GROUP STATE: %s\n", -- cgit v1.1 From 9b3b9ab6a7a43851ccb4633149d01239f99f275f Mon Sep 17 00:00:00 2001 From: "Klaus-D. Wacker" Date: Thu, 21 Aug 2008 17:10:25 +0200 Subject: LCS recovery dumps when cable reconnect LCS recovery dumps in irq routine when CCW address in Subchannel Status Word (SCSW) is zero. This occurs when recovery is driven after cable reconnect. Signed-off-by: Klaus-D. Wacker Signed-off-by: Ursula Braun Signed-off-by: Jeff Garzik --- drivers/s390/net/lcs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 6de2838..9bcfa04 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c @@ -1412,7 +1412,8 @@ lcs_irq(struct ccw_device *cdev, unsigned long intparm, struct irb *irb) } /* How far in the ccw chain have we processed? */ if ((channel->state != LCS_CH_STATE_INIT) && - (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC)) { + (irb->scsw.cmd.fctl & SCSW_FCTL_START_FUNC) && + (irb->scsw.cmd.cpa != 0)) { index = (struct ccw1 *) __va((addr_t) irb->scsw.cmd.cpa) - channel->ccws; if ((irb->scsw.cmd.actl & SCSW_ACTL_SUSPENDED) || -- cgit v1.1 From c22ce6d849423639b4b80d1b28edd383cb3048a9 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Aug 2008 16:34:35 -0700 Subject: drivers/net/skfp/ess.c: fix compile warnings CC [M] drivers/net/skfp/ess.o drivers/net/skfp/ess.c: In function 'ess_send_response': drivers/net/skfp/ess.c:513: warning: cast from pointer to integer of different size drivers/net/skfp/ess.c: In function 'ess_send_alc_req': drivers/net/skfp/ess.c:609: warning: cast from pointer to integer of different size drivers/net/skfp/ess.c:639: warning: cast from pointer to integer of different size Signed-off-by: Takashi Iwai Cc: Jeff Garzik Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/skfp/ess.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/skfp/ess.c b/drivers/net/skfp/ess.c index 889f987..a85efcf 100644 --- a/drivers/net/skfp/ess.c +++ b/drivers/net/skfp/ess.c @@ -510,7 +510,7 @@ static void ess_send_response(struct s_smc *smc, struct smt_header *sm, chg->path.para.p_type = SMT_P320B ; chg->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ; chg->path.mib_index = SBAPATHINDEX ; - chg->path.path_pad = (u_short)NULL ; + chg->path.path_pad = 0; chg->path.path_index = PRIMARY_RING ; /* set P320F */ @@ -606,7 +606,7 @@ static void ess_send_alc_req(struct s_smc *smc) req->path.para.p_type = SMT_P320B ; req->path.para.p_len = sizeof(struct smt_p_320b) - PARA_LEN ; req->path.mib_index = SBAPATHINDEX ; - req->path.path_pad = (u_short)NULL ; + req->path.path_pad = 0; req->path.path_index = PRIMARY_RING ; /* set P0017 */ @@ -636,7 +636,7 @@ static void ess_send_alc_req(struct s_smc *smc) /* set P19 */ req->a_addr.para.p_type = SMT_P0019 ; req->a_addr.para.p_len = sizeof(struct smt_p_0019) - PARA_LEN ; - req->a_addr.sba_pad = (u_short)NULL ; + req->a_addr.sba_pad = 0; req->a_addr.alloc_addr = null_addr ; /* set P1A */ -- cgit v1.1 From 17fc7004a3f552b52274b6b2fbbebd7ff76dc1d5 Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Fri, 8 Aug 2008 16:51:26 -0700 Subject: igb: remove 82576 quad adapter Disable support for device 8086:10E8. Currently the result of loading the driver with the device present causes system instability. Signed-off-by: Alexander Duyck Signed-off-by: Jeff Kirsher Signed-off-by: Jeff Garzik --- drivers/net/igb/e1000_82575.c | 1 - drivers/net/igb/e1000_hw.h | 1 - drivers/net/igb/igb_ethtool.c | 9 --------- drivers/net/igb/igb_main.c | 11 ----------- 4 files changed, 22 deletions(-) (limited to 'drivers') diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c index bb823ac..f5e2e72 100644 --- a/drivers/net/igb/e1000_82575.c +++ b/drivers/net/igb/e1000_82575.c @@ -87,7 +87,6 @@ static s32 igb_get_invariants_82575(struct e1000_hw *hw) case E1000_DEV_ID_82576: case E1000_DEV_ID_82576_FIBER: case E1000_DEV_ID_82576_SERDES: - case E1000_DEV_ID_82576_QUAD_COPPER: mac->type = e1000_82576; break; default: diff --git a/drivers/net/igb/e1000_hw.h b/drivers/net/igb/e1000_hw.h index a65ccc3..99504a6 100644 --- a/drivers/net/igb/e1000_hw.h +++ b/drivers/net/igb/e1000_hw.h @@ -41,7 +41,6 @@ struct e1000_hw; #define E1000_DEV_ID_82576 0x10C9 #define E1000_DEV_ID_82576_FIBER 0x10E6 #define E1000_DEV_ID_82576_SERDES 0x10E7 -#define E1000_DEV_ID_82576_QUAD_COPPER 0x10E8 #define E1000_DEV_ID_82575EB_COPPER 0x10A7 #define E1000_DEV_ID_82575EB_FIBER_SERDES 0x10A9 #define E1000_DEV_ID_82575GB_QUAD_COPPER 0x10D6 diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c index 3eb78a6..58906c9 100644 --- a/drivers/net/igb/igb_ethtool.c +++ b/drivers/net/igb/igb_ethtool.c @@ -1750,15 +1750,6 @@ static int igb_wol_exclusion(struct igb_adapter *adapter, /* return success for non excluded adapter ports */ retval = 0; break; - case E1000_DEV_ID_82576_QUAD_COPPER: - /* quad port adapters only support WoL on port A */ - if (!(adapter->flags & IGB_FLAG_QUAD_PORT_A)) { - wol->supported = 0; - break; - } - /* return success for non excluded adapter ports */ - retval = 0; - break; default: /* dual port cards only support WoL on port A from now on * unless it was enabled in the eeprom for port B diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c index e6eb13a..634c4c9 100644 --- a/drivers/net/igb/igb_main.c +++ b/drivers/net/igb/igb_main.c @@ -61,7 +61,6 @@ static struct pci_device_id igb_pci_tbl[] = { { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_FIBER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_SERDES), board_82575 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82576_QUAD_COPPER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_COPPER), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575EB_FIBER_SERDES), board_82575 }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_82575GB_QUAD_COPPER), board_82575 }, @@ -1217,16 +1216,6 @@ static int __devinit igb_probe(struct pci_dev *pdev, if (rd32(E1000_STATUS) & E1000_STATUS_FUNC_1) adapter->eeprom_wol = 0; break; - case E1000_DEV_ID_82576_QUAD_COPPER: - /* if quad port adapter, disable WoL on all but port A */ - if (global_quad_port_a != 0) - adapter->eeprom_wol = 0; - else - adapter->flags |= IGB_FLAG_QUAD_PORT_A; - /* Reset for multiple quad port adapters */ - if (++global_quad_port_a == 4) - global_quad_port_a = 0; - break; } /* initialize the wol settings based on the eeprom settings */ -- cgit v1.1 From 50f684b900de431729d6f77e69c941560936f275 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ilpo=20J=C3=A4rvinen?= Date: Tue, 19 Aug 2008 10:32:06 +0300 Subject: atl1e: multistatement if missing braces MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Doesn't cause problems (yet) because err gets zeroed earlier. Signed-off-by: Ilpo Järvinen Signed-off-by: Jeff Garzik --- drivers/net/atl1e/atl1e_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index 82d7be1..7685b99 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c @@ -2232,10 +2232,11 @@ static int atl1e_resume(struct pci_dev *pdev) AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); - if (netif_running(netdev)) + if (netif_running(netdev)) { err = atl1e_request_irq(adapter); if (err) return err; + } atl1e_reset_hw(&adapter->hw); -- cgit v1.1 From 82c26a9d117f0178b8c1b33429014b6d99c470f6 Mon Sep 17 00:00:00 2001 From: Jay Cliburn Date: Mon, 18 Aug 2008 19:28:13 -0500 Subject: atl1: disable TSO by default The atl1 driver is causing stalled connections and file corruption whenever TSO is enabled. Two examples are here: http://lkml.org/lkml/2008/7/15/325 http://lkml.org/lkml/2008/8/18/543 Disable TSO by default until we can determine the source of the problem. Signed-off-by: Jay Cliburn cc: stable@kernel.org Signed-off-by: Jeff Garzik --- drivers/net/atlx/atl1.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index e6a7bb7..e23ce77 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c @@ -3022,7 +3022,6 @@ static int __devinit atl1_probe(struct pci_dev *pdev, netdev->features = NETIF_F_HW_CSUM; netdev->features |= NETIF_F_SG; netdev->features |= (NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX); - netdev->features |= NETIF_F_TSO; netdev->features |= NETIF_F_LLTX; /* -- cgit v1.1 From 95eacee870a521d2647f42c4f670cd65a145a6bd Mon Sep 17 00:00:00 2001 From: Denis Joseph Barrow Date: Tue, 19 Aug 2008 18:07:52 -0700 Subject: [netdrvr] hso: icon 322 detection fix Fixes Icon-322 detection. Signed-off-by: Denis Joseph Barrow Cc: Jeff Garzik Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jeff Garzik --- drivers/net/usb/hso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 1b7cac7..1131e10 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -397,7 +397,7 @@ static const struct usb_device_id hso_ids[] = { {default_port_device(0x0af0, 0xc031)}, /* Icon-Edge */ {icon321_port_device(0x0af0, 0xd013)}, /* Module HSxPA */ {icon321_port_device(0x0af0, 0xd031)}, /* Icon-321 */ - {default_port_device(0x0af0, 0xd033)}, /* Icon-322 */ + {icon321_port_device(0x0af0, 0xd033)}, /* Icon-322 */ {USB_DEVICE(0x0af0, 0x7301)}, /* GE40x */ {USB_DEVICE(0x0af0, 0x7361)}, /* GE40x */ {USB_DEVICE(0x0af0, 0x7401)}, /* GI 0401 */ -- cgit v1.1 From c213f286f2cf6590f83f541f66a625ee8d20c6f4 Mon Sep 17 00:00:00 2001 From: Denis Joseph Barrow Date: Tue, 19 Aug 2008 18:07:55 -0700 Subject: [netdrvr] hso: dev_kfree_skb crash fix Fixes dev_kfree_skb happening too many times when hso_start_net_device is called from hso_resume. Signed-off-by: Denis Joseph Barrow Cc: Jeff Garzik Signed-off-by: Greg Kroah-Hartman Signed-off-by: Jeff Garzik --- drivers/net/usb/hso.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 1131e10..6e42b5a 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -2613,6 +2613,7 @@ static int hso_resume(struct usb_interface *iface) "Transmitting lingering data\n"); hso_net_start_xmit(hso_net->skb_tx_buf, hso_net->net); + hso_net->skb_tx_buf = NULL; } result = hso_start_net_device(network_table[i]); if (result) -- cgit v1.1 From 45e15bb734e4e559ab32f26196e44d5cf1417f10 Mon Sep 17 00:00:00 2001 From: Santiago Leon Date: Wed, 20 Aug 2008 13:09:19 -0600 Subject: ibmveth: fix bad UDP checksums This patch fixes a ibmveth bug where bad UDP checksums are being transmitted when checksum offloading is enabled. The hypervisor does checksum offloading only on TCP packets, so ibmveth calls skb_checksum_help() for any other protocol. The bug happens because the packet is being modified after the DMA map, so we would need a memory barrier before making the hypervisor call. Reordering the code so that the DMA map happens after skb_checksum_help() has the additional advantage of fixing a DMA map leak if skb_checksum_help() where to fail. Signed-off-by: Santiago Leon Signed-off-by: Jeff Garzik --- drivers/net/ibmveth.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ibmveth.c b/drivers/net/ibmveth.c index a03fe1f..c2d57f8 100644 --- a/drivers/net/ibmveth.c +++ b/drivers/net/ibmveth.c @@ -904,8 +904,6 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) unsigned long data_dma_addr; desc.fields.flags_len = IBMVETH_BUF_VALID | skb->len; - data_dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, - skb->len, DMA_TO_DEVICE); if (skb->ip_summed == CHECKSUM_PARTIAL && ip_hdr(skb)->protocol != IPPROTO_TCP && skb_checksum_help(skb)) { @@ -924,6 +922,8 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) buf[1] = 0; } + data_dma_addr = dma_map_single(&adapter->vdev->dev, skb->data, + skb->len, DMA_TO_DEVICE); if (dma_mapping_error(&adapter->vdev->dev, data_dma_addr)) { if (!firmware_has_feature(FW_FEATURE_CMO)) ibmveth_error_printk("tx: unable to map xmit buffer\n"); @@ -932,6 +932,7 @@ static int ibmveth_start_xmit(struct sk_buff *skb, struct net_device *netdev) desc.fields.address = adapter->bounce_buffer_dma; tx_map_failed++; used_bounce = 1; + wmb(); } else desc.fields.address = data_dma_addr; -- cgit v1.1 From 6fc30db563c57e383ca2ec836d8c9208c52d265a Mon Sep 17 00:00:00 2001 From: Jeff Garzik Date: Wed, 27 Aug 2008 05:54:30 -0400 Subject: [netdrvr] smc91x: fix resource removal (null ptr deref) Properly handle resource cleanup on unplug/exit. Spotted by Jonathan Cameron Signed-off-by: Jeff Garzik --- drivers/net/smc91x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/smc91x.c b/drivers/net/smc91x.c index 2040965..24768c1 100644 --- a/drivers/net/smc91x.c +++ b/drivers/net/smc91x.c @@ -2255,7 +2255,7 @@ static int smc_drv_remove(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "smc91x-regs"); if (!res) - platform_get_resource(pdev, IORESOURCE_MEM, 0); + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); release_mem_region(res->start, SMC_IO_EXTENT); free_netdev(ndev); -- cgit v1.1 From 8382cc1c2d0eb8918d3b71bf6cb8ac2e883f3e33 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sat, 23 Aug 2008 22:02:23 +0200 Subject: net/usb/mcs7830: new device IDs This adds USB device IDs for MosChip 7730 and Sitecom LN030 to the mcs7830 driver. The IDs have been reported to work without further modifications. Signed-off-by: Arnd Bergmann Acked-by: David Brownell Cc: Viktor Horvath Cc: Robbert Wethmar Cc: Bart van der Klip Signed-off-by: Jeff Garzik --- drivers/net/usb/mcs7830.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index c3d119f..ebf1332 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -46,6 +46,10 @@ #define MCS7830_VENDOR_ID 0x9710 #define MCS7830_PRODUCT_ID 0x7830 +#define MCS7730_PRODUCT_ID 0x7730 + +#define SITECOM_VENDOR_ID 0x0DF6 +#define LN_030_PRODUCT_ID 0x0021 #define MCS7830_MII_ADVERTISE (ADVERTISE_PAUSE_CAP | ADVERTISE_100FULL | \ ADVERTISE_100HALF | ADVERTISE_10FULL | \ @@ -491,7 +495,16 @@ static int mcs7830_rx_fixup(struct usbnet *dev, struct sk_buff *skb) } static const struct driver_info moschip_info = { - .description = "MOSCHIP 7830 usb-NET adapter", + .description = "MOSCHIP 7830/7730 usb-NET adapter", + .bind = mcs7830_bind, + .rx_fixup = mcs7830_rx_fixup, + .flags = FLAG_ETHER, + .in = 1, + .out = 2, +}; + +static const struct driver_info sitecom_info = { + .description = "Sitecom LN-30 usb-NET adapter", .bind = mcs7830_bind, .rx_fixup = mcs7830_rx_fixup, .flags = FLAG_ETHER, @@ -504,6 +517,14 @@ static const struct usb_device_id products[] = { USB_DEVICE(MCS7830_VENDOR_ID, MCS7830_PRODUCT_ID), .driver_info = (unsigned long) &moschip_info, }, + { + USB_DEVICE(MCS7830_VENDOR_ID, MCS7730_PRODUCT_ID), + .driver_info = (unsigned long) &moschip_info, + }, + { + USB_DEVICE(SITECOM_VENDOR_ID, LN_030_PRODUCT_ID), + .driver_info = (unsigned long) &sitecom_info, + }, {}, }; MODULE_DEVICE_TABLE(usb, products); -- cgit v1.1 From 1025433147e635af9cd150676a097396cf666ddb Mon Sep 17 00:00:00 2001 From: Oliver Martin Date: Sat, 23 Aug 2008 22:08:47 +0200 Subject: net/usb/mcs7830: add set_mac_address Implement set_mac_address for mcs7830. This enables me to use it with my cable modem. Signed-off-by: Oliver Martin Signed-off-by: Arnd Bergmann Signed-off-by: Jeff Garzik --- drivers/net/usb/mcs7830.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/net/usb/mcs7830.c b/drivers/net/usb/mcs7830.c index ebf1332..ca9d00c 100644 --- a/drivers/net/usb/mcs7830.c +++ b/drivers/net/usb/mcs7830.c @@ -446,6 +446,29 @@ static struct ethtool_ops mcs7830_ethtool_ops = { .nway_reset = usbnet_nway_reset, }; +static int mcs7830_set_mac_address(struct net_device *netdev, void *p) +{ + int ret; + struct usbnet *dev = netdev_priv(netdev); + struct sockaddr *addr = p; + + if (netif_running(netdev)) + return -EBUSY; + + if (!is_valid_ether_addr(addr->sa_data)) + return -EINVAL; + + memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); + + ret = mcs7830_set_reg(dev, HIF_REG_ETHERNET_ADDR, ETH_ALEN, + netdev->dev_addr); + + if (ret < 0) + return ret; + + return 0; +} + static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev) { struct net_device *net = dev->net; @@ -459,6 +482,7 @@ static int mcs7830_bind(struct usbnet *dev, struct usb_interface *udev) net->ethtool_ops = &mcs7830_ethtool_ops; net->set_multicast_list = mcs7830_set_multicast; mcs7830_set_multicast(net); + net->set_mac_address = mcs7830_set_mac_address; /* reserve space for the status byte on rx */ dev->rx_urb_size = ETH_FRAME_LEN + 1; -- cgit v1.1 From edcfe5f7e307846e578fb88d69fa27051fded0ab Mon Sep 17 00:00:00 2001 From: Ayaz Abdulla Date: Wed, 20 Aug 2008 16:34:37 -0700 Subject: forcedeth: fix checksum flag Fix the checksum feature advertised in device flags. The hardware support TCP/UDP over IPv4 and TCP/UDP over IPv6 (without IPv6 extension headers). However, the kernel feature flags do not distinguish IPv6 with/without extension headers. Therefore, the driver needs to use NETIF_F_IP_CSUM instead of NETIF_F_HW_CSUM since the latter includes all IPv6 packets. A future patch can be created to check for extension headers and perform software checksum calculation. Signed-off-by: Ayaz Abdulla Cc: Jeff Garzik Cc: Manfred Spraul [2.6.25.x, 2.6.26.x] Signed-off-by: Andrew Morton Signed-off-by: Jeff Garzik --- drivers/net/forcedeth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 053971e..331b86b 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c @@ -5522,7 +5522,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i if (id->driver_data & DEV_HAS_CHECKSUM) { np->rx_csum = 1; np->txrxctl_bits |= NVREG_TXRXCTL_RXCHECK; - dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; + dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG; dev->features |= NETIF_F_TSO; } @@ -5835,7 +5835,7 @@ static int __devinit nv_probe(struct pci_dev *pci_dev, const struct pci_device_i dev_printk(KERN_INFO, &pci_dev->dev, "%s%s%s%s%s%s%s%s%s%sdesc-v%u\n", dev->features & NETIF_F_HIGHDMA ? "highdma " : "", - dev->features & (NETIF_F_HW_CSUM | NETIF_F_SG) ? + dev->features & (NETIF_F_IP_CSUM | NETIF_F_SG) ? "csum " : "", dev->features & (NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_TX) ? "vlan " : "", -- cgit v1.1 From ab9399059bb85a94758f42fb25607e440e926cc6 Mon Sep 17 00:00:00 2001 From: Sebastian Siewior Date: Tue, 19 Aug 2008 21:12:45 +0200 Subject: net: don't grab a mutex within a timer context in gianfar I got the following backtrace while network was unavailble: |NETDEV WATCHDOG: eth0: transmit timed out |BUG: sleeping function called from invalid context at /home/bigeasy/git/linux-2.6-powerpc/kernel/mutex.c:87 |in_atomic():1, irqs_disabled():0 |Call Trace: |[c0383d90] [c0006dd8] show_stack+0x48/0x184 (unreliable) |[c0383db0] [c001e938] __might_sleep+0xe0/0xf4 |[c0383dc0] [c025a43c] mutex_lock+0x24/0x3c |[c0383de0] [c019005c] phy_stop+0x20/0x70 |[c0383df0] [c018d4ec] stop_gfar+0x28/0xf4 |[c0383e10] [c018e8c4] gfar_timeout+0x30/0x60 |[c0383e20] [c01fe7c0] dev_watchdog+0xa8/0x144 |[c0383e30] [c002f93c] run_timer_softirq+0x148/0x1c8 |[c0383e60] [c002b084] __do_softirq+0x5c/0xc4 |[c0383e80] [c00046fc] do_softirq+0x3c/0x54 |[c0383e90] [c002ac60] irq_exit+0x3c/0x5c |[c0383ea0] [c000b378] timer_interrupt+0xe0/0xf8 |[c0383ec0] [c000e5ac] ret_from_except+0x0/0x18 |[c0383f80] [c000804c] cpu_idle+0xcc/0xdc |[c0383fa0] [c025c07c] etext+0x7c/0x90 |[c0383fc0] [c0338960] start_kernel+0x294/0x2a8 |[c0383ff0] [c00003dc] skpinv+0x304/0x340 |------------[ cut here ]------------ The phylock was once a spinlock but got changed into a mutex via commit 35b5f6b1a aka [PHYLIB: Locking fixes for PHY I/O potentially sleeping] Signed-off-by: Sebastian Siewior Signed-off-by: Jeff Garzik --- drivers/net/gianfar.c | 22 ++++++++++++++++++---- drivers/net/gianfar.h | 1 + 2 files changed, 19 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 999d691..4320a98 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -105,6 +105,7 @@ const char gfar_driver_version[] = "1.3"; static int gfar_enet_open(struct net_device *dev); static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev); +static void gfar_reset_task(struct work_struct *work); static void gfar_timeout(struct net_device *dev); static int gfar_close(struct net_device *dev); struct sk_buff *gfar_new_skb(struct net_device *dev); @@ -209,6 +210,7 @@ static int gfar_probe(struct platform_device *pdev) spin_lock_init(&priv->txlock); spin_lock_init(&priv->rxlock); spin_lock_init(&priv->bflock); + INIT_WORK(&priv->reset_task, gfar_reset_task); platform_set_drvdata(pdev, dev); @@ -1212,6 +1214,7 @@ static int gfar_close(struct net_device *dev) napi_disable(&priv->napi); + cancel_work_sync(&priv->reset_task); stop_gfar(dev); /* Disconnect from the PHY */ @@ -1326,13 +1329,16 @@ static int gfar_change_mtu(struct net_device *dev, int new_mtu) return 0; } -/* gfar_timeout gets called when a packet has not been +/* gfar_reset_task gets scheduled when a packet has not been * transmitted after a set amount of time. * For now, assume that clearing out all the structures, and - * starting over will fix the problem. */ -static void gfar_timeout(struct net_device *dev) + * starting over will fix the problem. + */ +static void gfar_reset_task(struct work_struct *work) { - dev->stats.tx_errors++; + struct gfar_private *priv = container_of(work, struct gfar_private, + reset_task); + struct net_device *dev = priv->dev; if (dev->flags & IFF_UP) { stop_gfar(dev); @@ -1342,6 +1348,14 @@ static void gfar_timeout(struct net_device *dev) netif_tx_schedule_all(dev); } +static void gfar_timeout(struct net_device *dev) +{ + struct gfar_private *priv = netdev_priv(dev); + + dev->stats.tx_errors++; + schedule_work(&priv->reset_task); +} + /* Interrupt Handler for Transmit complete */ static int gfar_clean_tx_ring(struct net_device *dev) { diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index d59df98..f46e9b6 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h @@ -756,6 +756,7 @@ struct gfar_private { uint32_t msg_enable; + struct work_struct reset_task; /* Network Statistics */ struct gfar_extra_stats extra_stats; }; -- cgit v1.1 From e8296582783a9f3bf75dbeb98dfdae15fd45c008 Mon Sep 17 00:00:00 2001 From: Benjamin Herrenschmidt Date: Mon, 18 Aug 2008 07:29:23 +1000 Subject: ibm_newemac: Don't call dev_mc_add() before device is registered We must not call dev_mc_add() from within our HW configure which happens before we initialize and register the netdev. Do it in open() instead. Thanks to Sebastian Siewior for tracking it down. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Jeff Garzik --- drivers/net/ibm_newemac/core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/net/ibm_newemac/core.c b/drivers/net/ibm_newemac/core.c index 2e720f2..ccd9d90 100644 --- a/drivers/net/ibm_newemac/core.c +++ b/drivers/net/ibm_newemac/core.c @@ -663,9 +663,6 @@ static int emac_configure(struct emac_instance *dev) if (emac_phy_gpcs(dev->phy.mode)) emac_mii_reset_phy(&dev->phy); - /* Required for Pause packet support in EMAC */ - dev_mc_add(ndev, default_mcast_addr, sizeof(default_mcast_addr), 1); - return 0; } @@ -1150,6 +1147,9 @@ static int emac_open(struct net_device *ndev) } else netif_carrier_on(dev->ndev); + /* Required for Pause packet support in EMAC */ + dev_mc_add(ndev, default_mcast_addr, sizeof(default_mcast_addr), 1); + emac_configure(dev); mal_poll_add(dev->mal, &dev->commac); mal_enable_tx_channel(dev->mal, dev->mal_tx_chan); -- cgit v1.1 From 211cd45ac71dcd40d473fddf9a49cb1085173cb1 Mon Sep 17 00:00:00 2001 From: Ursula Braun Date: Fri, 15 Aug 2008 08:02:58 +0200 Subject: qeth: use -EOPNOTSUPP instead of -ENOTSUPP. return value -ENOTSUPP is not valid in userspace context, use -EOPNOTSUPP instead. Signed-off-by: Ursula Braun Signed-off-by: Frank Blaschka Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_l3_sys.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index ac19937..210ddb6 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c @@ -136,7 +136,7 @@ static ssize_t qeth_l3_dev_route6_store(struct device *dev, return -EINVAL; if (!qeth_is_supported(card, IPA_IPV6)) { - return -ENOTSUPP; + return -EOPNOTSUPP; } return qeth_l3_dev_route_store(card, &card->options.route6, -- cgit v1.1 From 7db2266a374d66f5ac85334c922cb37d76939cc5 Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Fri, 15 Aug 2008 08:02:59 +0200 Subject: qeth: l2 write unicast list to hardware In case the netdev unicast list contains additional entries we have to register/deregister them. Signed-off-by: Frank Blaschka Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_core.h | 1 + drivers/s390/net/qeth_l2_main.c | 27 ++++++++++++++++++++++----- 2 files changed, 23 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index 80971c2..bf8a75c 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -689,6 +689,7 @@ struct qeth_mc_mac { struct list_head list; __u8 mc_addr[MAX_ADDR_LEN]; unsigned char mc_addrlen; + int is_vmac; }; struct qeth_card { diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index b3cee03..3ac3cc1 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -177,9 +177,10 @@ static int qeth_l2_send_delgroupmac(struct qeth_card *card, __u8 *mac) qeth_l2_send_delgroupmac_cb); } -static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac) +static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac, int vmac) { struct qeth_mc_mac *mc; + int rc; mc = kmalloc(sizeof(struct qeth_mc_mac), GFP_ATOMIC); @@ -188,8 +189,16 @@ static void qeth_l2_add_mc(struct qeth_card *card, __u8 *mac) memcpy(mc->mc_addr, mac, OSA_ADDR_LEN); mc->mc_addrlen = OSA_ADDR_LEN; + mc->is_vmac = vmac; + + if (vmac) { + rc = qeth_l2_send_setdelmac(card, mac, IPA_CMD_SETVMAC, + NULL); + } else { + rc = qeth_l2_send_setgroupmac(card, mac); + } - if (!qeth_l2_send_setgroupmac(card, mac)) + if (!rc) list_add_tail(&mc->list, &card->mc_list); else kfree(mc); @@ -201,7 +210,11 @@ static void qeth_l2_del_all_mc(struct qeth_card *card) spin_lock_bh(&card->mclock); list_for_each_entry_safe(mc, tmp, &card->mc_list, list) { - qeth_l2_send_delgroupmac(card, mc->mc_addr); + if (mc->is_vmac) + qeth_l2_send_setdelmac(card, mc->mc_addr, + IPA_CMD_DELVMAC, NULL); + else + qeth_l2_send_delgroupmac(card, mc->mc_addr); list_del(&mc->list); kfree(mc); } @@ -590,7 +603,7 @@ static int qeth_l2_set_mac_address(struct net_device *dev, void *p) static void qeth_l2_set_multicast_list(struct net_device *dev) { struct qeth_card *card = dev->ml_priv; - struct dev_mc_list *dm; + struct dev_addr_list *dm; if (card->info.type == QETH_CARD_TYPE_OSN) return ; @@ -599,7 +612,11 @@ static void qeth_l2_set_multicast_list(struct net_device *dev) qeth_l2_del_all_mc(card); spin_lock_bh(&card->mclock); for (dm = dev->mc_list; dm; dm = dm->next) - qeth_l2_add_mc(card, dm->dmi_addr); + qeth_l2_add_mc(card, dm->da_addr, 0); + + for (dm = dev->uc_list; dm; dm = dm->next) + qeth_l2_add_mc(card, dm->da_addr, 1); + spin_unlock_bh(&card->mclock); if (!qeth_adp_supported(card, IPA_SETADP_SET_PROMISC_MODE)) return; -- cgit v1.1 From bd8774c841aa5162d1d6837b3d21f4dcee71f36a Mon Sep 17 00:00:00 2001 From: Frank Blaschka Date: Fri, 15 Aug 2008 08:03:00 +0200 Subject: qeth: preallocated header account offset When a preallocated header qdio buffer is filled we have to account the offset for the data length. Signed-off-by: Frank Blaschka Signed-off-by: Jeff Garzik --- drivers/s390/net/qeth_core_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index bd420d1..c7ab1b8 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -3024,7 +3024,7 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb, struct qdio_buffer *buffer, int is_tso, int *next_element_to_fill, int offset) { - int length = skb->len; + int length = skb->len - offset; int length_here; int element; char *data; -- cgit v1.1 From 17393dd67c06c3912ff47b31268b648929715336 Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Thu, 14 Aug 2008 18:27:23 +0200 Subject: e100, fix iomap read There were 2 omitted readb's used on an iomap space. eliminate them by using ioread8 instead. Signed-off-by: Jiri Slaby Cc: Jeff Kirsher Cc: Jesse Brandeburg Cc: Bruce Allan Cc: PJ Waskiewicz Cc: John Ronciak Signed-off-by: Jeff Garzik --- drivers/net/e100.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e100.c b/drivers/net/e100.c index 19d32a2..453115a 100644 --- a/drivers/net/e100.c +++ b/drivers/net/e100.c @@ -1838,7 +1838,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, if ((le16_to_cpu(rfd->command) & cb_el) && (RU_RUNNING == nic->ru_running)) - if (readb(&nic->csr->scb.status) & rus_no_res) + if (ioread8(&nic->csr->scb.status) & rus_no_res) nic->ru_running = RU_SUSPENDED; return -ENODATA; } @@ -1861,7 +1861,7 @@ static int e100_rx_indicate(struct nic *nic, struct rx *rx, if ((le16_to_cpu(rfd->command) & cb_el) && (RU_RUNNING == nic->ru_running)) { - if (readb(&nic->csr->scb.status) & rus_no_res) + if (ioread8(&nic->csr->scb.status) & rus_no_res) nic->ru_running = RU_SUSPENDED; } -- cgit v1.1 From f2455eb176ac87081bbfc9a44b21c7cd2bc1967e Mon Sep 17 00:00:00 2001 From: Eugene Teo Date: Wed, 27 Aug 2008 04:50:30 -0700 Subject: wan: Missing capability checks in sbni_ioctl() There are missing capability checks in the following code: 1300 static int 1301 sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd) 1302 { [...] 1319 case SIOCDEVRESINSTATS : 1320 if( current->euid != 0 ) /* root only */ 1321 return -EPERM; [...] 1336 case SIOCDEVSHWSTATE : 1337 if( current->euid != 0 ) /* root only */ 1338 return -EPERM; [...] 1357 case SIOCDEVENSLAVE : 1358 if( current->euid != 0 ) /* root only */ 1359 return -EPERM; [...] 1372 case SIOCDEVEMANSIPATE : 1373 if( current->euid != 0 ) /* root only */ 1374 return -EPERM; Here's my proposed fix: Missing capability checks. Signed-off-by: Eugene Teo Signed-off-by: David S. Miller --- drivers/net/wan/sbni.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/net/wan/sbni.c b/drivers/net/wan/sbni.c index e59255a..6596cd0 100644 --- a/drivers/net/wan/sbni.c +++ b/drivers/net/wan/sbni.c @@ -1317,7 +1317,7 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) break; case SIOCDEVRESINSTATS : - if( current->euid != 0 ) /* root only */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; memset( &nl->in_stats, 0, sizeof(struct sbni_in_stats) ); break; @@ -1334,7 +1334,7 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) break; case SIOCDEVSHWSTATE : - if( current->euid != 0 ) /* root only */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; spin_lock( &nl->lock ); @@ -1355,7 +1355,7 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) #ifdef CONFIG_SBNI_MULTILINE case SIOCDEVENSLAVE : - if( current->euid != 0 ) /* root only */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; if (copy_from_user( slave_name, ifr->ifr_data, sizeof slave_name )) @@ -1370,7 +1370,7 @@ sbni_ioctl( struct net_device *dev, struct ifreq *ifr, int cmd ) return enslave( dev, slave_dev ); case SIOCDEVEMANSIPATE : - if( current->euid != 0 ) /* root only */ + if (!capable(CAP_NET_ADMIN)) return -EPERM; return emancipate( dev ); -- cgit v1.1 From 8560c650f340565b720fd57d1f9c99ab216d99d0 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 27 Aug 2008 13:35:31 -0700 Subject: Revert "pktcdvd: push BKL down into driver" This reverts commit 5b6155ee70e9c4d2ad7e6f514c8eee06e2711c3a, because the block device ioctl's really aren't ready for it. In particular, the "struct file *" and the "struct inode *" arguments do not necessarily match, which means that the unlocked version of the ioctl (that only gets a "struct file *") isn't actually able to handle the cases it needs to handle. This fixes bugzilla http://bugzilla.kernel.org/show_bug.cgi?id=11401 Reported-and-bisected-by: Laurent Riffard Acked-by: Peter Osterlund Cc: Alan Cox Cc: Andrew Morton Cc: Jens Axboe Signed-off-by: Linus Torvalds --- drivers/block/pktcdvd.c | 35 ++++++++++------------------------- 1 file changed, 10 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index 158eed4..29b7a64 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include @@ -2798,14 +2797,9 @@ out_mem: return ret; } -static long pkt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) +static int pkt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - struct inode *inode = file->f_path.dentry->d_inode; - struct pktcdvd_device *pd; - long ret; - - lock_kernel(); - pd = inode->i_bdev->bd_disk->private_data; + struct pktcdvd_device *pd = inode->i_bdev->bd_disk->private_data; VPRINTK("pkt_ioctl: cmd %x, dev %d:%d\n", cmd, imajor(inode), iminor(inode)); @@ -2818,8 +2812,7 @@ static long pkt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) case CDROM_LAST_WRITTEN: case CDROM_SEND_PACKET: case SCSI_IOCTL_SEND_COMMAND: - ret = blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); - break; + return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); case CDROMEJECT: /* @@ -2828,15 +2821,14 @@ static long pkt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) */ if (pd->refcnt == 1) pkt_lock_door(pd, 0); - ret = blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); - break; + return blkdev_ioctl(pd->bdev->bd_inode, file, cmd, arg); default: VPRINTK(DRIVER_NAME": Unknown ioctl for %s (%x)\n", pd->name, cmd); - ret = -ENOTTY; + return -ENOTTY; } - unlock_kernel(); - return ret; + + return 0; } static int pkt_media_changed(struct gendisk *disk) @@ -2858,7 +2850,7 @@ static struct block_device_operations pktcdvd_ops = { .owner = THIS_MODULE, .open = pkt_open, .release = pkt_close, - .unlocked_ioctl = pkt_ioctl, + .ioctl = pkt_ioctl, .media_changed = pkt_media_changed, }; @@ -3023,8 +3015,7 @@ static void pkt_get_status(struct pkt_ctrl_command *ctrl_cmd) mutex_unlock(&ctl_mutex); } -static long pkt_ctl_ioctl(struct file *file, unsigned int cmd, - unsigned long arg) +static int pkt_ctl_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { void __user *argp = (void __user *)arg; struct pkt_ctrl_command ctrl_cmd; @@ -3041,22 +3032,16 @@ static long pkt_ctl_ioctl(struct file *file, unsigned int cmd, case PKT_CTRL_CMD_SETUP: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - lock_kernel(); ret = pkt_setup_dev(new_decode_dev(ctrl_cmd.dev), &pkt_dev); ctrl_cmd.pkt_dev = new_encode_dev(pkt_dev); - unlock_kernel(); break; case PKT_CTRL_CMD_TEARDOWN: if (!capable(CAP_SYS_ADMIN)) return -EPERM; - lock_kernel(); ret = pkt_remove_dev(new_decode_dev(ctrl_cmd.pkt_dev)); - unlock_kernel(); break; case PKT_CTRL_CMD_STATUS: - lock_kernel(); pkt_get_status(&ctrl_cmd); - unlock_kernel(); break; default: return -ENOTTY; @@ -3069,7 +3054,7 @@ static long pkt_ctl_ioctl(struct file *file, unsigned int cmd, static const struct file_operations pkt_ctl_fops = { - .unlocked_ioctl = pkt_ctl_ioctl, + .ioctl = pkt_ctl_ioctl, .owner = THIS_MODULE, }; -- cgit v1.1 From 16ecf85a5ca7345efbcbb2de76607db0f7ec9049 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Wed, 27 Aug 2008 01:14:46 -0700 Subject: e1000: fix stack size Here's the patch. It shrinks the stack from 1152 bytes to 192 bytes (the first version, that only did the e1000_option part, got it down to 600 bytes). About half comes from not using multiple "e1000_option" structures, the other half comes from turning the "e1000_opt_list[]" arrays into "static const" instead, so that gcc doesn't copy them onto the stack. Signed-off-by: Linus Torvalds Reveiewed-by: Auke Kok Tested-by: Emil Tantilov Signed-off-by: Jeff Kirsher Signed-off-by: Linus Torvalds --- drivers/net/e1000/e1000_param.c | 81 +++++++++++++++++++++++------------------ 1 file changed, 45 insertions(+), 36 deletions(-) (limited to 'drivers') diff --git a/drivers/net/e1000/e1000_param.c b/drivers/net/e1000/e1000_param.c index b9f90a5..213437d 100644 --- a/drivers/net/e1000/e1000_param.c +++ b/drivers/net/e1000/e1000_param.c @@ -208,7 +208,7 @@ struct e1000_option { } r; struct { /* list_option info */ int nr; - struct e1000_opt_list { int i; char *str; } *p; + const struct e1000_opt_list { int i; char *str; } *p; } l; } arg; }; @@ -242,7 +242,7 @@ static int __devinit e1000_validate_option(unsigned int *value, break; case list_option: { int i; - struct e1000_opt_list *ent; + const struct e1000_opt_list *ent; for (i = 0; i < opt->arg.l.nr; i++) { ent = &opt->arg.l.p[i]; @@ -279,7 +279,9 @@ static void e1000_check_copper_options(struct e1000_adapter *adapter); void __devinit e1000_check_options(struct e1000_adapter *adapter) { + struct e1000_option opt; int bd = adapter->bd_number; + if (bd >= E1000_MAX_NIC) { DPRINTK(PROBE, NOTICE, "Warning: no configuration for board #%i\n", bd); @@ -287,19 +289,21 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } { /* Transmit Descriptor Count */ - struct e1000_option opt = { + struct e1000_tx_ring *tx_ring = adapter->tx_ring; + int i; + e1000_mac_type mac_type = adapter->hw.mac_type; + + opt = (struct e1000_option) { .type = range_option, .name = "Transmit Descriptors", .err = "using default of " __MODULE_STRING(E1000_DEFAULT_TXD), .def = E1000_DEFAULT_TXD, - .arg = { .r = { .min = E1000_MIN_TXD }} + .arg = { .r = { + .min = E1000_MIN_TXD, + .max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD + }} }; - struct e1000_tx_ring *tx_ring = adapter->tx_ring; - int i; - e1000_mac_type mac_type = adapter->hw.mac_type; - opt.arg.r.max = mac_type < e1000_82544 ? - E1000_MAX_TXD : E1000_MAX_82544_TXD; if (num_TxDescriptors > bd) { tx_ring->count = TxDescriptors[bd]; @@ -313,19 +317,21 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) tx_ring[i].count = tx_ring->count; } { /* Receive Descriptor Count */ - struct e1000_option opt = { + struct e1000_rx_ring *rx_ring = adapter->rx_ring; + int i; + e1000_mac_type mac_type = adapter->hw.mac_type; + + opt = (struct e1000_option) { .type = range_option, .name = "Receive Descriptors", .err = "using default of " __MODULE_STRING(E1000_DEFAULT_RXD), .def = E1000_DEFAULT_RXD, - .arg = { .r = { .min = E1000_MIN_RXD }} + .arg = { .r = { + .min = E1000_MIN_RXD, + .max = mac_type < e1000_82544 ? E1000_MAX_RXD : E1000_MAX_82544_RXD + }} }; - struct e1000_rx_ring *rx_ring = adapter->rx_ring; - int i; - e1000_mac_type mac_type = adapter->hw.mac_type; - opt.arg.r.max = mac_type < e1000_82544 ? E1000_MAX_RXD : - E1000_MAX_82544_RXD; if (num_RxDescriptors > bd) { rx_ring->count = RxDescriptors[bd]; @@ -339,7 +345,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) rx_ring[i].count = rx_ring->count; } { /* Checksum Offload Enable/Disable */ - struct e1000_option opt = { + opt = (struct e1000_option) { .type = enable_option, .name = "Checksum Offload", .err = "defaulting to Enabled", @@ -363,7 +369,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) { E1000_FC_FULL, "Flow Control Enabled" }, { E1000_FC_DEFAULT, "Flow Control Hardware Default" }}; - struct e1000_option opt = { + opt = (struct e1000_option) { .type = list_option, .name = "Flow Control", .err = "reading default settings from EEPROM", @@ -381,7 +387,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Transmit Interrupt Delay */ - struct e1000_option opt = { + opt = (struct e1000_option) { .type = range_option, .name = "Transmit Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_TIDV), @@ -399,7 +405,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Transmit Absolute Interrupt Delay */ - struct e1000_option opt = { + opt = (struct e1000_option) { .type = range_option, .name = "Transmit Absolute Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_TADV), @@ -417,7 +423,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Receive Interrupt Delay */ - struct e1000_option opt = { + opt = (struct e1000_option) { .type = range_option, .name = "Receive Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_RDTR), @@ -435,7 +441,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Receive Absolute Interrupt Delay */ - struct e1000_option opt = { + opt = (struct e1000_option) { .type = range_option, .name = "Receive Absolute Interrupt Delay", .err = "using default of " __MODULE_STRING(DEFAULT_RADV), @@ -453,7 +459,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Interrupt Throttling Rate */ - struct e1000_option opt = { + opt = (struct e1000_option) { .type = range_option, .name = "Interrupt Throttling Rate (ints/sec)", .err = "using default of " __MODULE_STRING(DEFAULT_ITR), @@ -497,7 +503,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Smart Power Down */ - struct e1000_option opt = { + opt = (struct e1000_option) { .type = enable_option, .name = "PHY Smart Power Down", .err = "defaulting to Disabled", @@ -513,7 +519,7 @@ void __devinit e1000_check_options(struct e1000_adapter *adapter) } } { /* Kumeran Lock Loss Workaround */ - struct e1000_option opt = { + opt = (struct e1000_option) { .type = enable_option, .name = "Kumeran Lock Loss Workaround", .err = "defaulting to Enabled", @@ -578,16 +584,18 @@ static void __devinit e1000_check_fiber_options(struct e1000_adapter *adapter) static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) { + struct e1000_option opt; unsigned int speed, dplx, an; int bd = adapter->bd_number; { /* Speed */ - struct e1000_opt_list speed_list[] = {{ 0, "" }, - { SPEED_10, "" }, - { SPEED_100, "" }, - { SPEED_1000, "" }}; + static const struct e1000_opt_list speed_list[] = { + { 0, "" }, + { SPEED_10, "" }, + { SPEED_100, "" }, + { SPEED_1000, "" }}; - struct e1000_option opt = { + opt = (struct e1000_option) { .type = list_option, .name = "Speed", .err = "parameter ignored", @@ -604,11 +612,12 @@ static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) } } { /* Duplex */ - struct e1000_opt_list dplx_list[] = {{ 0, "" }, - { HALF_DUPLEX, "" }, - { FULL_DUPLEX, "" }}; + static const struct e1000_opt_list dplx_list[] = { + { 0, "" }, + { HALF_DUPLEX, "" }, + { FULL_DUPLEX, "" }}; - struct e1000_option opt = { + opt = (struct e1000_option) { .type = list_option, .name = "Duplex", .err = "parameter ignored", @@ -637,7 +646,7 @@ static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) "parameter ignored\n"); adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT; } else { /* Autoneg */ - struct e1000_opt_list an_list[] = + static const struct e1000_opt_list an_list[] = #define AA "AutoNeg advertising " {{ 0x01, AA "10/HD" }, { 0x02, AA "10/FD" }, @@ -671,7 +680,7 @@ static void __devinit e1000_check_copper_options(struct e1000_adapter *adapter) { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" }, { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }}; - struct e1000_option opt = { + opt = (struct e1000_option) { .type = list_option, .name = "AutoNeg", .err = "parameter ignored", -- cgit v1.1 From f753f3272b4d2108d1e4b121ddcde504737a8693 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 26 Aug 2008 19:52:47 +0100 Subject: tty: TIOCGSOFTCAR/SSOFTCAR on pty is wron The termios settings ioctls on a pty should affect the bound tty side not the pty. The SOFTCAR ioctls use the wrong device file. Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/tty_ioctl.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index ea9fc5d..bf34e45 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c @@ -937,12 +937,14 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, return 0; #endif case TIOCGSOFTCAR: - return put_user(C_CLOCAL(tty) ? 1 : 0, + /* FIXME: for correctness we may need to take the termios + lock here - review */ + return put_user(C_CLOCAL(real_tty) ? 1 : 0, (int __user *)arg); case TIOCSSOFTCAR: if (get_user(arg, (unsigned int __user *) arg)) return -EFAULT; - return tty_change_softcar(tty, arg); + return tty_change_softcar(real_tty, arg); default: return -ENOIOCTLCMD; } -- cgit v1.1 From a152db71d962f405f7e9be5c818bddf6d1be50a7 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Tue, 26 Aug 2008 19:55:58 +0100 Subject: tty: Fix termios tty window resize race with pty/tty pair Kanru Chen posted a patch versus the old code which deals with the case where you resize the pty side of a pty/tty pair. In that situation the termios data is updated for both pty and tty but the locks are not held for the right side. This implements the fix differently against the updated tty code. Patch by self but the hard bit (noticing and fixing the bug) is thanks to Kanru Chen. Signed-off-by: Alan Cox Signed-off-by: Linus Torvalds --- drivers/char/tty_io.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index a27160b..daeb8f7 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -2498,7 +2498,7 @@ static int tiocgwinsz(struct tty_struct *tty, struct winsize __user *arg) /** * tty_do_resize - resize event * @tty: tty being resized - * @real_tty: real tty (if using a pty/tty pair) + * @real_tty: real tty (not the same as tty if using a pty/tty pair) * @rows: rows (character) * @cols: cols (character) * @@ -2512,7 +2512,8 @@ int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, struct pid *pgrp, *rpgrp; unsigned long flags; - mutex_lock(&tty->termios_mutex); + /* For a PTY we need to lock the tty side */ + mutex_lock(&real_tty->termios_mutex); if (!memcmp(ws, &tty->winsize, sizeof(*ws))) goto done; /* Get the PID values and reference them so we can @@ -2533,7 +2534,7 @@ int tty_do_resize(struct tty_struct *tty, struct tty_struct *real_tty, tty->winsize = *ws; real_tty->winsize = *ws; done: - mutex_unlock(&tty->termios_mutex); + mutex_unlock(&real_tty->termios_mutex); return 0; } -- cgit v1.1 From 4c246edd2550304df5b766cc841584b2bb058843 Mon Sep 17 00:00:00 2001 From: Vladimir Sokolovsky Date: Wed, 27 Aug 2008 14:29:57 -0700 Subject: IB/mlx4: Actually return L_Key and R_Key for fast register MRs Initialize the L_Key and R_Key for memory regions returned from mlx4_ib_alloc_fast_reg_mr(). Otherwise callers just get garbage for the memory keys and can't do anything useful with these MRs. Signed-off-by: Vladimir Sokolovsky Signed-off-by: Roland Dreier Signed-off-by: Linus Torvalds --- drivers/infiniband/hw/mlx4/mr.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'drivers') diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index a4cdb46..87f5c5a 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c @@ -204,6 +204,8 @@ struct ib_mr *mlx4_ib_alloc_fast_reg_mr(struct ib_pd *pd, if (err) goto err_mr; + mr->ibmr.rkey = mr->ibmr.lkey = mr->mmr.key; + return &mr->ibmr; err_mr: -- cgit v1.1 From ee35425c8eb11556a4cb7b1c7543f1bfb88f911c Mon Sep 17 00:00:00 2001 From: Marc Pignat Date: Thu, 28 Aug 2008 08:33:22 +0200 Subject: i2c: Fix device_init_wakeup place device_init_wakeup must be called after device_register. Signed-off-by: Marc Pignat Acked-by: David Brownell Signed-off-by: Jean Delvare --- drivers/i2c/i2c-core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 550853f..4ac33670 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -108,6 +108,9 @@ static int i2c_device_probe(struct device *dev) if (!driver->probe || !driver->id_table) return -ENODEV; client->driver = driver; + if (!device_can_wakeup(&client->dev)) + device_init_wakeup(&client->dev, + client->flags & I2C_CLIENT_WAKE); dev_dbg(dev, "probe\n"); status = driver->probe(client, i2c_match_id(driver->id_table, client)); @@ -262,9 +265,8 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->adapter = adap; client->dev.platform_data = info->platform_data; - device_init_wakeup(&client->dev, info->flags & I2C_CLIENT_WAKE); - client->flags = info->flags & ~I2C_CLIENT_WAKE; + client->flags = info->flags; client->addr = info->addr; client->irq = info->irq; -- cgit v1.1 From 4329cf8613b0c7cdc020005f0e1ea7378681f1d8 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Thu, 28 Aug 2008 08:33:23 +0200 Subject: i2c: Prevent log spam on some DVB adapters Some DVB adapters do not support the special I2C transaction that we use for probing purposes. There's no point in logging this event, as there's nothing the user can do and in general there is no actual problem. So, degrade one of these messages to a debug message, and move the other one around so that it is only printed on bogus drivers. Signed-off-by: Jean Delvare Acked-by: Uwe Bugla --- drivers/i2c/i2c-core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 4ac33670..b346a68 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1190,8 +1190,8 @@ int i2c_probe(struct i2c_adapter *adapter, && address_data->normal_i2c[0] == I2C_CLIENT_END) return 0; - dev_warn(&adapter->dev, "SMBus Quick command not supported, " - "can't probe for chips\n"); + dev_dbg(&adapter->dev, "SMBus Quick command not supported, " + "can't probe for chips\n"); return -EOPNOTSUPP; } @@ -1352,6 +1352,10 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) } } + /* Stop here if the classes do not match */ + if (!(adapter->class & driver->class)) + goto exit_free; + /* Stop here if we can't use SMBUS_QUICK */ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) { if (address_data->probe[0] == I2C_CLIENT_END @@ -1364,10 +1368,6 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) goto exit_free; } - /* Stop here if the classes do not match */ - if (!(adapter->class & driver->class)) - goto exit_free; - /* Probe entries are done second, and are not affected by ignore entries either */ for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) { -- cgit v1.1