diff options
author | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-03-15 15:27:06 +0100 |
---|---|---|
committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2010-03-15 15:27:06 +0100 |
commit | 2d3b5fa3a39d16c880bda3cf2bd9dd6ed5a01f74 (patch) | |
tree | e20283fe2ed46aa35c8ca5fc1724ba067cd2e2f8 /drivers | |
parent | Video: ARM CLCD: Better fix for swapped IENB and CNTL registers (diff) | |
parent | video: enable sh_mobile_lcdc on SH-Mobile ARM (diff) | |
download | linux-2d3b5fa3a39d16c880bda3cf2bd9dd6ed5a01f74.tar.xz linux-2d3b5fa3a39d16c880bda3cf2bd9dd6ed5a01f74.zip |
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/genesis-2.6
Diffstat (limited to 'drivers')
116 files changed, 1627 insertions, 802 deletions
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index 2fb3a480f6b0..4b66c69eaf57 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -57,7 +57,7 @@ config AGP_AMD config AGP_AMD64 tristate "AMD Opteron/Athlon64 on-CPU GART support" - depends on AGP && X86 + depends on AGP && X86 && K8_NB help This option gives you AGP support for the GLX component of X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 79d9edd0bdfa..7a0d2e4661a1 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -68,22 +68,25 @@ static const struct { #define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ &max, EV_KEY, (c)) -static inline int match_scancode(int code, int scancode) +static inline int match_scancode(unsigned int code, unsigned int scancode) { if (scancode == 0) return 1; - return ((code & (HID_USAGE_PAGE | HID_USAGE)) == scancode); + + return (code & (HID_USAGE_PAGE | HID_USAGE)) == scancode; } -static inline int match_keycode(int code, int keycode) +static inline int match_keycode(unsigned int code, unsigned int keycode) { if (keycode == 0) return 1; - return (code == keycode); + + return code == keycode; } static struct hid_usage *hidinput_find_key(struct hid_device *hid, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { int i, j, k; struct hid_report *report; @@ -105,8 +108,8 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid, return NULL; } -static int hidinput_getkeycode(struct input_dev *dev, int scancode, - int *keycode) +static int hidinput_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct hid_device *hid = input_get_drvdata(dev); struct hid_usage *usage; @@ -119,16 +122,13 @@ static int hidinput_getkeycode(struct input_dev *dev, int scancode, return -EINVAL; } -static int hidinput_setkeycode(struct input_dev *dev, int scancode, - int keycode) +static int hidinput_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct hid_device *hid = input_get_drvdata(dev); struct hid_usage *usage; int old_keycode; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - usage = hidinput_find_key(hid, scancode, 0); if (usage) { old_keycode = usage->code; diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 02ce9cff5fcf..d06083fdffbb 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -73,7 +73,6 @@ config I2C_SMBUS source drivers/i2c/algos/Kconfig source drivers/i2c/busses/Kconfig -source drivers/i2c/chips/Kconfig config I2C_DEBUG_CORE bool "I2C Core debugging messages" @@ -98,12 +97,4 @@ config I2C_DEBUG_BUS a problem with I2C support and want to see more of what is going on. -config I2C_DEBUG_CHIP - bool "I2C Chip debugging messages" - help - Say Y here if you want the I2C chip drivers to produce a bunch of - debug messages to the system log. Select this if you are having - a problem with I2C support and want to see more of what is going - on. - endif # I2C diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile index acd0250c16a0..a7d9b4be9bb3 100644 --- a/drivers/i2c/Makefile +++ b/drivers/i2c/Makefile @@ -6,7 +6,7 @@ obj-$(CONFIG_I2C_BOARDINFO) += i2c-boardinfo.o obj-$(CONFIG_I2C) += i2c-core.o obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o -obj-y += busses/ chips/ algos/ +obj-y += algos/ busses/ ifeq ($(CONFIG_I2C_DEBUG_CORE),y) EXTRA_CFLAGS += -DDEBUG diff --git a/drivers/i2c/algos/i2c-algo-bit.c b/drivers/i2c/algos/i2c-algo-bit.c index e25e13980af3..e8d568c3fb09 100644 --- a/drivers/i2c/algos/i2c-algo-bit.c +++ b/drivers/i2c/algos/i2c-algo-bit.c @@ -522,6 +522,12 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, int i, ret; unsigned short nak_ok; + if (adap->pre_xfer) { + ret = adap->pre_xfer(i2c_adap); + if (ret < 0) + return ret; + } + bit_dbg(3, &i2c_adap->dev, "emitting start condition\n"); i2c_start(adap); for (i = 0; i < num; i++) { @@ -570,6 +576,9 @@ static int bit_xfer(struct i2c_adapter *i2c_adap, bailout: bit_dbg(3, &i2c_adap->dev, "emitting stop condition\n"); i2c_stop(adap); + + if (adap->post_xfer) + adap->post_xfer(i2c_adap); return ret; } diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c index 9da5b05cdb52..299b918455a3 100644 --- a/drivers/i2c/busses/i2c-i801.c +++ b/drivers/i2c/busses/i2c-i801.c @@ -416,9 +416,11 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write, data->block[0] = 32; /* max for SMBus block reads */ } + /* Experience has shown that the block buffer can only be used for + SMBus (not I2C) block transactions, even though the datasheet + doesn't mention this limitation. */ if ((i801_features & FEATURE_BLOCK_BUFFER) - && !(command == I2C_SMBUS_I2C_BLOCK_DATA - && read_write == I2C_SMBUS_READ) + && command != I2C_SMBUS_I2C_BLOCK_DATA && i801_set_block_buffer_mode() == 0) result = i801_block_transaction_by_block(data, read_write, hwpec); diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c index 1c440a70ec61..b289ec99eeba 100644 --- a/drivers/i2c/busses/i2c-powermac.c +++ b/drivers/i2c/busses/i2c-powermac.c @@ -122,9 +122,14 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap, rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len); if (rc) { - dev_err(&adap->dev, - "I2C transfer at 0x%02x failed, size %d, err %d\n", - addrdir >> 1, size, rc); + if (rc == -ENXIO) + dev_dbg(&adap->dev, + "I2C transfer at 0x%02x failed, size %d, " + "err %d\n", addrdir >> 1, size, rc); + else + dev_err(&adap->dev, + "I2C transfer at 0x%02x failed, size %d, " + "err %d\n", addrdir >> 1, size, rc); goto bail; } @@ -175,10 +180,16 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap, goto bail; } rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len); - if (rc < 0) - dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n", - addrdir & 1 ? "read from" : "write to", addrdir >> 1, - rc); + if (rc < 0) { + if (rc == -ENXIO) + dev_dbg(&adap->dev, "I2C %s 0x%02x failed, err %d\n", + addrdir & 1 ? "read from" : "write to", + addrdir >> 1, rc); + else + dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n", + addrdir & 1 ? "read from" : "write to", + addrdir >> 1, rc); + } bail: pmac_i2c_close(bus); return rc < 0 ? rc : 1; diff --git a/drivers/i2c/busses/i2c-xiic.c b/drivers/i2c/busses/i2c-xiic.c index eece39a5a30e..f0ef8da6c554 100644 --- a/drivers/i2c/busses/i2c-xiic.c +++ b/drivers/i2c/busses/i2c-xiic.c @@ -32,6 +32,7 @@ #include <linux/module.h> #include <linux/init.h> #include <linux/errno.h> +#include <linux/delay.h> #include <linux/platform_device.h> #include <linux/i2c.h> #include <linux/interrupt.h> diff --git a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig deleted file mode 100644 index ae4539d99bef..000000000000 --- a/drivers/i2c/chips/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -# -# Miscellaneous I2C chip drivers configuration -# -# *** DEPRECATED! Do not add new entries! See Makefile *** -# - -menu "Miscellaneous I2C Chip support" - -config SENSORS_TSL2550 - tristate "Taos TSL2550 ambient light sensor" - depends on EXPERIMENTAL - help - If you say yes here you get support for the Taos TSL2550 - ambient light sensor. - - This driver can also be built as a module. If so, the module - will be called tsl2550. - -endmenu diff --git a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile deleted file mode 100644 index fe0af0f81f2d..000000000000 --- a/drivers/i2c/chips/Makefile +++ /dev/null @@ -1,18 +0,0 @@ -# -# Makefile for miscellaneous I2C chip drivers. -# -# Do not add new drivers to this directory! It is DEPRECATED. -# -# Device drivers are better grouped according to the functionality they -# implement rather than to the bus they are connected to. In particular: -# * Hardware monitoring chip drivers go to drivers/hwmon -# * RTC chip drivers go to drivers/rtc -# * I/O expander drivers go to drivers/gpio -# - -obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o - -ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) -EXTRA_CFLAGS += -DDEBUG -endif - diff --git a/drivers/i2c/i2c-smbus.c b/drivers/i2c/i2c-smbus.c index 421278221243..7a8201ed2181 100644 --- a/drivers/i2c/i2c-smbus.c +++ b/drivers/i2c/i2c-smbus.c @@ -22,7 +22,6 @@ #include <linux/kernel.h> #include <linux/module.h> #include <linux/device.h> -#include <linux/semaphore.h> #include <linux/interrupt.h> #include <linux/workqueue.h> #include <linux/i2c.h> @@ -55,7 +54,7 @@ static int smbus_do_alert(struct device *dev, void *addrp) * Drivers should either disable alerts, or provide at least * a minimal handler. Lock so client->driver won't change. */ - down(&dev->sem); + device_lock(dev); if (client->driver) { if (client->driver->alert) client->driver->alert(client, data->flag); @@ -63,7 +62,7 @@ static int smbus_do_alert(struct device *dev, void *addrp) dev_warn(&client->dev, "no driver alert()!\n"); } else dev_dbg(&client->dev, "alert with no driver\n"); - up(&dev->sem); + device_unlock(dev); /* Stop iterating after we find the device */ return -EBUSY; diff --git a/drivers/infiniband/core/mad.c b/drivers/infiniband/core/mad.c index 58463da814d1..e351b1548535 100644 --- a/drivers/infiniband/core/mad.c +++ b/drivers/infiniband/core/mad.c @@ -2953,6 +2953,9 @@ static void ib_mad_remove_device(struct ib_device *device) { int i, num_ports, cur_port; + if (rdma_node_get_transport(device->node_type) != RDMA_TRANSPORT_IB) + return; + if (device->node_type == RDMA_NODE_IB_SWITCH) { num_ports = 1; cur_port = 0; diff --git a/drivers/infiniband/hw/cxgb3/iwch.c b/drivers/infiniband/hw/cxgb3/iwch.c index ee1d8b4d4541..63f975f3e30f 100644 --- a/drivers/infiniband/hw/cxgb3/iwch.c +++ b/drivers/infiniband/hw/cxgb3/iwch.c @@ -189,6 +189,7 @@ static void close_rnic_dev(struct t3cdev *tdev) list_for_each_entry_safe(dev, tmp, &dev_list, entry) { if (dev->rdev.t3cdev_p == tdev) { dev->rdev.flags = CXIO_ERROR_FATAL; + synchronize_net(); cancel_delayed_work_sync(&dev->db_drop_task); list_del(&dev->entry); iwch_unregister_device(dev); @@ -217,6 +218,7 @@ static void iwch_event_handler(struct t3cdev *tdev, u32 evt, u32 port_id) switch (evt) { case OFFLOAD_STATUS_DOWN: { rdev->flags = CXIO_ERROR_FATAL; + synchronize_net(); event.event = IB_EVENT_DEVICE_FATAL; dispatch = 1; break; diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c index ce7f53833577..925075557dc2 100644 --- a/drivers/infiniband/hw/nes/nes_hw.c +++ b/drivers/infiniband/hw/nes/nes_hw.c @@ -1899,9 +1899,14 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic) u16 wqe_fragment_index; u64 wqe_frag; u32 cqp_head; + u32 wqm_cfg0; unsigned long flags; int ret; + /* clear wqe stall before destroying NIC QP */ + wqm_cfg0 = nes_read_indexed(nesdev, NES_IDX_WQM_CONFIG0); + nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0 & 0xFFFF7FFF); + /* Free remaining NIC receive buffers */ while (nesvnic->nic.rq_head != nesvnic->nic.rq_tail) { nic_rqe = &nesvnic->nic.rq_vbase[nesvnic->nic.rq_tail]; @@ -2020,6 +2025,9 @@ void nes_destroy_nic_qp(struct nes_vnic *nesvnic) pci_free_consistent(nesdev->pcidev, nesvnic->nic_mem_size, nesvnic->nic_vbase, nesvnic->nic_pbase); + + /* restore old wqm_cfg0 value */ + nes_write_indexed(nesdev, NES_IDX_WQM_CONFIG0, wqm_cfg0); } /** diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h index 9b1e7f869d83..bbbfe9fc5a5a 100644 --- a/drivers/infiniband/hw/nes/nes_hw.h +++ b/drivers/infiniband/hw/nes/nes_hw.h @@ -160,6 +160,7 @@ enum indexed_regs { NES_IDX_ENDNODE0_NSTAT_TX_OCTETS_HI = 0x7004, NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_LO = 0x7008, NES_IDX_ENDNODE0_NSTAT_TX_FRAMES_HI = 0x700c, + NES_IDX_WQM_CONFIG0 = 0x5000, NES_IDX_WQM_CONFIG1 = 0x5004, NES_IDX_CM_CONFIG = 0x5100, NES_IDX_NIC_LOGPORT_TO_PHYPORT = 0x6000, diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c index a1d79b6856ac..91fdde382e82 100644 --- a/drivers/infiniband/hw/nes/nes_nic.c +++ b/drivers/infiniband/hw/nes/nes_nic.c @@ -1595,7 +1595,6 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, struct nes_vnic *nesvnic; struct net_device *netdev; struct nic_qp_map *curr_qp_map; - u32 u32temp; u8 phy_type = nesdev->nesadapter->phy_type[nesdev->mac_index]; netdev = alloc_etherdev(sizeof(struct nes_vnic)); @@ -1707,6 +1706,10 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, ((phy_type == NES_PHY_TYPE_PUMA_1G) && (((PCI_FUNC(nesdev->pcidev->devfn) == 1) && (nesdev->mac_index == 2)) || ((PCI_FUNC(nesdev->pcidev->devfn) == 2) && (nesdev->mac_index == 1)))))) { + u32 u32temp; + u32 link_mask; + u32 link_val; + u32temp = nes_read_indexed(nesdev, NES_IDX_PHY_PCS_CONTROL_STATUS0 + (0x200 * (nesdev->mac_index & 1))); if (phy_type != NES_PHY_TYPE_PUMA_1G) { @@ -1715,13 +1718,36 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev, (0x200 * (nesdev->mac_index & 1)), u32temp); } + /* Check and set linkup here. This is for back to back */ + /* configuration where second port won't get link interrupt */ + switch (phy_type) { + case NES_PHY_TYPE_PUMA_1G: + if (nesdev->mac_index < 2) { + link_mask = 0x01010000; + link_val = 0x01010000; + } else { + link_mask = 0x02020000; + link_val = 0x02020000; + } + break; + default: + link_mask = 0x0f1f0000; + link_val = 0x0f0f0000; + break; + } + + u32temp = nes_read_indexed(nesdev, + NES_IDX_PHY_PCS_CONTROL_STATUS0 + + (0x200 * (nesdev->mac_index & 1))); + if ((u32temp & link_mask) == link_val) + nesvnic->linkup = 1; + /* clear the MAC interrupt status, assumes direct logical to physical mapping */ u32temp = nes_read_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index)); nes_debug(NES_DBG_INIT, "Phy interrupt status = 0x%X.\n", u32temp); nes_write_indexed(nesdev, NES_IDX_MAC_INT_STATUS + (0x200 * nesdev->mac_index), u32temp); nes_init_phy(nesdev); - } return netdev; diff --git a/drivers/infiniband/hw/nes/nes_verbs.c b/drivers/infiniband/hw/nes/nes_verbs.c index 815725f886c4..69928296d74b 100644 --- a/drivers/infiniband/hw/nes/nes_verbs.c +++ b/drivers/infiniband/hw/nes/nes_verbs.c @@ -1323,6 +1323,7 @@ static struct ib_qp *nes_create_qp(struct ib_pd *ibpd, nesqp->nesqp_context->aeq_token_low = cpu_to_le32((u32)((unsigned long)(nesqp))); nesqp->nesqp_context->aeq_token_high = cpu_to_le32((u32)(upper_32_bits((unsigned long)(nesqp)))); nesqp->nesqp_context->ird_ord_sizes = cpu_to_le32(NES_QPCONTEXT_ORDIRD_ALSMM | + NES_QPCONTEXT_ORDIRD_AAH | ((((u32)nesadapter->max_irrq_wr) << NES_QPCONTEXT_ORDIRD_IRDSIZE_SHIFT) & NES_QPCONTEXT_ORDIRD_IRDSIZE_MASK)); if (disable_mpa_crc) { diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 83a7751c38d6..bc658373ad55 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c @@ -708,6 +708,7 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_cm_tx_buf *tx_req; u64 addr; + int rc; if (unlikely(skb->len > tx->mtu)) { ipoib_warn(priv, "packet len %d (> %d) too long to send, dropping\n", @@ -739,9 +740,10 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ tx_req->mapping = addr; - if (unlikely(post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), - addr, skb->len))) { - ipoib_warn(priv, "post_send failed\n"); + rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), + addr, skb->len); + if (unlikely(rc)) { + ipoib_warn(priv, "post_send failed, error %d\n", rc); ++dev->stats.tx_errors; ib_dma_unmap_single(priv->ca, addr, skb->len, DMA_TO_DEVICE); dev_kfree_skb_any(skb); @@ -752,6 +754,8 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ if (++priv->tx_outstanding == ipoib_sendq_size) { ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n", tx->qp->qp_num); + if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP)) + ipoib_warn(priv, "request notify on send CQ failed\n"); netif_stop_queue(dev); } } diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index 8c91d9f37ada..5df40b128f81 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c @@ -529,7 +529,7 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_tx_buf *tx_req; - int hlen; + int hlen, rc; void *phead; if (skb_is_gso(skb)) { @@ -585,9 +585,10 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, netif_stop_queue(dev); } - if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), - address->ah, qpn, tx_req, phead, hlen))) { - ipoib_warn(priv, "post_send failed\n"); + rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), + address->ah, qpn, tx_req, phead, hlen); + if (unlikely(rc)) { + ipoib_warn(priv, "post_send failed, error %d\n", rc); ++dev->stats.tx_errors; --priv->tx_outstanding; ipoib_dma_unmap_tx(priv->ca, tx_req); diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 9f9816baeb97..2ee6c7a68bdc 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c @@ -515,7 +515,7 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, struct input_absinfo abs; struct ff_effect effect; int __user *ip = (int __user *)p; - int i, t, u, v; + unsigned int i, t, u, v; int error; switch (cmd) { diff --git a/drivers/input/input.c b/drivers/input/input.c index 41168d5f8c17..e2aad0a51826 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c @@ -582,7 +582,8 @@ static int input_fetch_keycode(struct input_dev *dev, int scancode) } static int input_default_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, + unsigned int *keycode) { if (!dev->keycodesize) return -EINVAL; @@ -596,7 +597,8 @@ static int input_default_getkeycode(struct input_dev *dev, } static int input_default_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { int old_keycode; int i; @@ -654,11 +656,9 @@ static int input_default_setkeycode(struct input_dev *dev, * This function should be called by anyone interested in retrieving current * keymap. Presently keyboard and evdev handlers use it. */ -int input_get_keycode(struct input_dev *dev, int scancode, int *keycode) +int input_get_keycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { - if (scancode < 0) - return -EINVAL; - return dev->getkeycode(dev, scancode, keycode); } EXPORT_SYMBOL(input_get_keycode); @@ -672,16 +672,14 @@ EXPORT_SYMBOL(input_get_keycode); * This function should be called by anyone needing to update current * keymap. Presently keyboard and evdev handlers use it. */ -int input_set_keycode(struct input_dev *dev, int scancode, int keycode) +int input_set_keycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { unsigned long flags; int old_keycode; int retval; - if (scancode < 0) - return -EINVAL; - - if (keycode < 0 || keycode > KEY_MAX) + if (keycode > KEY_MAX) return -EINVAL; spin_lock_irqsave(&dev->event_lock, flags); @@ -1881,35 +1879,37 @@ static int input_open_file(struct inode *inode, struct file *file) const struct file_operations *old_fops, *new_fops = NULL; int err; - lock_kernel(); + err = mutex_lock_interruptible(&input_mutex); + if (err) + return err; + /* No load-on-demand here? */ handler = input_table[iminor(inode) >> 5]; - if (!handler || !(new_fops = fops_get(handler->fops))) { - err = -ENODEV; - goto out; - } + if (handler) + new_fops = fops_get(handler->fops); + + mutex_unlock(&input_mutex); /* * That's _really_ odd. Usually NULL ->open means "nothing special", * not "no device". Oh, well... */ - if (!new_fops->open) { + if (!new_fops || !new_fops->open) { fops_put(new_fops); err = -ENODEV; goto out; } + old_fops = file->f_op; file->f_op = new_fops; err = new_fops->open(inode, file); - if (err) { fops_put(file->f_op); file->f_op = fops_get(old_fops); } fops_put(old_fops); out: - unlock_kernel(); return err; } diff --git a/drivers/input/joystick/gamecon.c b/drivers/input/joystick/gamecon.c index ae998d99a5ae..7a55714a1486 100644 --- a/drivers/input/joystick/gamecon.c +++ b/drivers/input/joystick/gamecon.c @@ -819,7 +819,7 @@ static int __init gc_setup_pad(struct gc *gc, int idx, int pad_type) int i; int err; - if (pad_type < 1 || pad_type > GC_MAX) { + if (pad_type < 1 || pad_type >= GC_MAX) { pr_err("Pad type %d unknown\n", pad_type); return -EINVAL; } diff --git a/drivers/input/keyboard/bf54x-keys.c b/drivers/input/keyboard/bf54x-keys.c index fe376a27fe57..593c052416b9 100644 --- a/drivers/input/keyboard/bf54x-keys.c +++ b/drivers/input/keyboard/bf54x-keys.c @@ -162,7 +162,7 @@ static irqreturn_t bfin_kpad_isr(int irq, void *dev_id) input_sync(input); if (bfin_kpad_get_keypressed(bf54x_kpad)) { - disable_irq(bf54x_kpad->irq); + disable_irq_nosync(bf54x_kpad->irq); bf54x_kpad->lastkey = key; mod_timer(&bf54x_kpad->timer, jiffies + bf54x_kpad->keyup_test_jiffies); diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig index 7097bfe581d7..23140a3bb8e0 100644 --- a/drivers/input/misc/Kconfig +++ b/drivers/input/misc/Kconfig @@ -214,6 +214,17 @@ config INPUT_TWL4030_PWRBUTTON To compile this driver as a module, choose M here. The module will be called twl4030_pwrbutton. +config INPUT_TWL4030_VIBRA + tristate "Support for TWL4030 Vibrator" + depends on TWL4030_CORE + select TWL4030_CODEC + select INPUT_FF_MEMLESS + help + This option enables support for TWL4030 Vibrator Driver. + + To compile this driver as a module, choose M here. The module will + be called twl4030_vibra. + config INPUT_UINPUT tristate "User level driver support" help diff --git a/drivers/input/misc/Makefile b/drivers/input/misc/Makefile index b611615e24ad..7e95a5d474dc 100644 --- a/drivers/input/misc/Makefile +++ b/drivers/input/misc/Makefile @@ -26,6 +26,7 @@ obj-$(CONFIG_INPUT_GPIO_ROTARY_ENCODER) += rotary_encoder.o obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o obj-$(CONFIG_INPUT_SPARCSPKR) += sparcspkr.o obj-$(CONFIG_INPUT_TWL4030_PWRBUTTON) += twl4030-pwrbutton.o +obj-$(CONFIG_INPUT_TWL4030_VIBRA) += twl4030-vibra.o obj-$(CONFIG_INPUT_UINPUT) += uinput.o obj-$(CONFIG_INPUT_WINBOND_CIR) += winbond-cir.o obj-$(CONFIG_INPUT_WISTRON_BTNS) += wistron_btns.o diff --git a/drivers/input/misc/ati_remote2.c b/drivers/input/misc/ati_remote2.c index 0501f0e65157..15be5430bc6d 100644 --- a/drivers/input/misc/ati_remote2.c +++ b/drivers/input/misc/ati_remote2.c @@ -474,10 +474,11 @@ static void ati_remote2_complete_key(struct urb *urb) } static int ati_remote2_getkeycode(struct input_dev *idev, - int scancode, int *keycode) + unsigned int scancode, unsigned int *keycode) { struct ati_remote2 *ar2 = input_get_drvdata(idev); - int index, mode; + unsigned int mode; + int index; mode = scancode >> 8; if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) @@ -491,10 +492,12 @@ static int ati_remote2_getkeycode(struct input_dev *idev, return 0; } -static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keycode) +static int ati_remote2_setkeycode(struct input_dev *idev, + unsigned int scancode, unsigned int keycode) { struct ati_remote2 *ar2 = input_get_drvdata(idev); - int index, mode, old_keycode; + unsigned int mode, old_keycode; + int index; mode = scancode >> 8; if (mode > ATI_REMOTE2_PC || !((1 << mode) & ar2->mode_mask)) @@ -504,9 +507,6 @@ static int ati_remote2_setkeycode(struct input_dev *idev, int scancode, int keyc if (index < 0) return -EINVAL; - if (keycode < KEY_RESERVED || keycode > KEY_MAX) - return -EINVAL; - old_keycode = ar2->keycode[mode][index]; ar2->keycode[mode][index] = keycode; __set_bit(keycode, idev->keybit); diff --git a/drivers/input/misc/twl4030-vibra.c b/drivers/input/misc/twl4030-vibra.c new file mode 100644 index 000000000000..2fb79e064da3 --- /dev/null +++ b/drivers/input/misc/twl4030-vibra.c @@ -0,0 +1,297 @@ +/* + * twl4030-vibra.c - TWL4030 Vibrator driver + * + * Copyright (C) 2008-2010 Nokia Corporation + * + * Written by Henrik Saari <henrik.saari@nokia.com> + * Updates by Felipe Balbi <felipe.balbi@nokia.com> + * Input by Jari Vanhala <ext-jari.vanhala@nokia.com> + * + * 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 + * + */ + +#include <linux/module.h> +#include <linux/jiffies.h> +#include <linux/platform_device.h> +#include <linux/workqueue.h> +#include <linux/i2c/twl.h> +#include <linux/mfd/twl4030-codec.h> +#include <linux/input.h> + +/* MODULE ID2 */ +#define LEDEN 0x00 + +/* ForceFeedback */ +#define EFFECT_DIR_180_DEG 0x8000 /* range is 0 - 0xFFFF */ + +struct vibra_info { + struct device *dev; + struct input_dev *input_dev; + + struct workqueue_struct *workqueue; + struct work_struct play_work; + + bool enabled; + int speed; + int direction; + + bool coexist; +}; + +static void vibra_disable_leds(void) +{ + u8 reg; + + /* Disable LEDA & LEDB, cannot be used with vibra (PWM) */ + twl_i2c_read_u8(TWL4030_MODULE_LED, ®, LEDEN); + reg &= ~0x03; + twl_i2c_write_u8(TWL4030_MODULE_LED, LEDEN, reg); +} + +/* Powers H-Bridge and enables audio clk */ +static void vibra_enable(struct vibra_info *info) +{ + u8 reg; + + twl4030_codec_enable_resource(TWL4030_CODEC_RES_POWER); + + /* turn H-Bridge on */ + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + (reg | TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); + + twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL); + + info->enabled = true; +} + +static void vibra_disable(struct vibra_info *info) +{ + u8 reg; + + /* Power down H-Bridge */ + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + (reg & ~TWL4030_VIBRA_EN), TWL4030_REG_VIBRA_CTL); + + twl4030_codec_disable_resource(TWL4030_CODEC_RES_POWER); + twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); + + info->enabled = false; +} + +static void vibra_play_work(struct work_struct *work) +{ + struct vibra_info *info = container_of(work, + struct vibra_info, play_work); + int dir; + int pwm; + u8 reg; + + dir = info->direction; + pwm = info->speed; + + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + if (pwm && (!info->coexist || !(reg & TWL4030_VIBRA_SEL))) { + + if (!info->enabled) + vibra_enable(info); + + /* set vibra rotation direction */ + twl_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, + ®, TWL4030_REG_VIBRA_CTL); + reg = (dir) ? (reg | TWL4030_VIBRA_DIR) : + (reg & ~TWL4030_VIBRA_DIR); + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + reg, TWL4030_REG_VIBRA_CTL); + + /* set PWM, 1 = max, 255 = min */ + twl_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, + 256 - pwm, TWL4030_REG_VIBRA_SET); + } else { + if (info->enabled) + vibra_disable(info); + } +} + +/*** Input/ForceFeedback ***/ + +static int vibra_play(struct input_dev *input, void *data, + struct ff_effect *effect) +{ + struct vibra_info *info = input_get_drvdata(input); + + info->speed = effect->u.rumble.strong_magnitude >> 8; + if (!info->speed) + info->speed = effect->u.rumble.weak_magnitude >> 9; + info->direction = effect->direction < EFFECT_DIR_180_DEG ? 0 : 1; + queue_work(info->workqueue, &info->play_work); + return 0; +} + +static int twl4030_vibra_open(struct input_dev *input) +{ + struct vibra_info *info = input_get_drvdata(input); + + info->workqueue = create_singlethread_workqueue("vibra"); + if (info->workqueue == NULL) { + dev_err(&input->dev, "couldn't create workqueue\n"); + return -ENOMEM; + } + return 0; +} + +static void twl4030_vibra_close(struct input_dev *input) +{ + struct vibra_info *info = input_get_drvdata(input); + + cancel_work_sync(&info->play_work); + INIT_WORK(&info->play_work, vibra_play_work); /* cleanup */ + destroy_workqueue(info->workqueue); + info->workqueue = NULL; + + if (info->enabled) + vibra_disable(info); +} + +/*** Module ***/ +#if CONFIG_PM +static int twl4030_vibra_suspend(struct device *dev) +{ + struct platform_device *pdev = to_platform_device(dev); + struct vibra_info *info = platform_get_drvdata(pdev); + + if (info->enabled) + vibra_disable(info); + + return 0; +} + +static int twl4030_vibra_resume(struct device *dev) +{ + vibra_disable_leds(); + return 0; +} + +static SIMPLE_DEV_PM_OPS(twl4030_vibra_pm_ops, + twl4030_vibra_suspend, twl4030_vibra_resume); +#endif + +static int __devinit twl4030_vibra_probe(struct platform_device *pdev) +{ + struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data; + struct vibra_info *info; + int ret; + + if (!pdata) { + dev_dbg(&pdev->dev, "platform_data not available\n"); + return -EINVAL; + } + + info = kzalloc(sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + info->dev = &pdev->dev; + info->coexist = pdata->coexist; + INIT_WORK(&info->play_work, vibra_play_work); + + info->input_dev = input_allocate_device(); + if (info->input_dev == NULL) { + dev_err(&pdev->dev, "couldn't allocate input device\n"); + ret = -ENOMEM; + goto err_kzalloc; + } + + input_set_drvdata(info->input_dev, info); + + info->input_dev->name = "twl4030:vibrator"; + info->input_dev->id.version = 1; + info->input_dev->dev.parent = pdev->dev.parent; + info->input_dev->open = twl4030_vibra_open; + info->input_dev->close = twl4030_vibra_close; + __set_bit(FF_RUMBLE, info->input_dev->ffbit); + + ret = input_ff_create_memless(info->input_dev, NULL, vibra_play); + if (ret < 0) { + dev_dbg(&pdev->dev, "couldn't register vibrator to FF\n"); + goto err_ialloc; + } + + ret = input_register_device(info->input_dev); + if (ret < 0) { + dev_dbg(&pdev->dev, "couldn't register input device\n"); + goto err_iff; + } + + vibra_disable_leds(); + + platform_set_drvdata(pdev, info); + return 0; + +err_iff: + input_ff_destroy(info->input_dev); +err_ialloc: + input_free_device(info->input_dev); +err_kzalloc: + kfree(info); + return ret; +} + +static int __devexit twl4030_vibra_remove(struct platform_device *pdev) +{ + struct vibra_info *info = platform_get_drvdata(pdev); + + /* this also free ff-memless and calls close if needed */ + input_unregister_device(info->input_dev); + kfree(info); + platform_set_drvdata(pdev, NULL); + + return 0; +} + +static struct platform_driver twl4030_vibra_driver = { + .probe = twl4030_vibra_probe, + .remove = __devexit_p(twl4030_vibra_remove), + .driver = { + .name = "twl4030_codec_vibra", + .owner = THIS_MODULE, +#ifdef CONFIG_PM + .pm = &twl4030_vibra_pm_ops, +#endif + }, +}; + +static int __init twl4030_vibra_init(void) +{ + return platform_driver_register(&twl4030_vibra_driver); +} +module_init(twl4030_vibra_init); + +static void __exit twl4030_vibra_exit(void) +{ + platform_driver_unregister(&twl4030_vibra_driver); +} +module_exit(twl4030_vibra_exit); + +MODULE_ALIAS("platform:twl4030_codec_vibra"); + +MODULE_DESCRIPTION("TWL4030 Vibra driver"); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Nokia Corporation"); diff --git a/drivers/input/misc/winbond-cir.c b/drivers/input/misc/winbond-cir.c index cbec3dfdd42b..9c155a43abc2 100644 --- a/drivers/input/misc/winbond-cir.c +++ b/drivers/input/misc/winbond-cir.c @@ -385,26 +385,24 @@ wbcir_do_getkeycode(struct wbcir_data *data, u32 scancode) } static int -wbcir_getkeycode(struct input_dev *dev, int scancode, int *keycode) +wbcir_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct wbcir_data *data = input_get_drvdata(dev); - *keycode = (int)wbcir_do_getkeycode(data, (u32)scancode); + *keycode = wbcir_do_getkeycode(data, scancode); return 0; } static int -wbcir_setkeycode(struct input_dev *dev, int sscancode, int keycode) +wbcir_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct wbcir_data *data = input_get_drvdata(dev); struct wbcir_keyentry *keyentry; struct wbcir_keyentry *new_keyentry; unsigned long flags; unsigned int old_keycode = KEY_RESERVED; - u32 scancode = (u32)sscancode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; new_keyentry = kmalloc(sizeof(*new_keyentry), GFP_KERNEL); if (!new_keyentry) diff --git a/drivers/input/misc/wm831x-on.c b/drivers/input/misc/wm831x-on.c index ba4f5dd7c60e..1e54bce72db5 100644 --- a/drivers/input/misc/wm831x-on.c +++ b/drivers/input/misc/wm831x-on.c @@ -97,8 +97,9 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) wm831x_on->dev->phys = "wm831x_on/input0"; wm831x_on->dev->dev.parent = &pdev->dev; - ret = wm831x_request_irq(wm831x, irq, wm831x_on_irq, - IRQF_TRIGGER_RISING, "wm831x_on", wm831x_on); + ret = request_threaded_irq(irq, NULL, wm831x_on_irq, + IRQF_TRIGGER_RISING, "wm831x_on", + wm831x_on); if (ret < 0) { dev_err(&pdev->dev, "Unable to request IRQ: %d\n", ret); goto err_input_dev; @@ -114,7 +115,7 @@ static int __devinit wm831x_on_probe(struct platform_device *pdev) return 0; err_irq: - wm831x_free_irq(wm831x, irq, NULL); + free_irq(irq, wm831x_on); err_input_dev: input_free_device(wm831x_on->dev); err: @@ -127,7 +128,7 @@ static int __devexit wm831x_on_remove(struct platform_device *pdev) struct wm831x_on *wm831x_on = platform_get_drvdata(pdev); int irq = platform_get_irq(pdev, 0); - wm831x_free_irq(wm831x_on->wm831x, irq, wm831x_on); + free_irq(irq, wm831x_on); cancel_delayed_work_sync(&wm831x_on->work); input_unregister_device(wm831x_on->dev); kfree(wm831x_on); diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index f93c2c0daf1f..7490f1da4a53 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c @@ -63,6 +63,8 @@ static const struct alps_model_info alps_model_data[] = { { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ + { { 0x52, 0x01, 0x14 }, 0xff, 0xff, + ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ }; /* @@ -118,40 +120,27 @@ static void alps_report_buttons(struct psmouse *psmouse, struct input_dev *dev1, struct input_dev *dev2, int left, int right, int middle) { - struct alps_data *priv = psmouse->private; - const struct alps_model_info *model = priv->i; - - if (model->flags & ALPS_PS2_INTERLEAVED) { - struct input_dev *dev; + struct input_dev *dev; - /* - * If shared button has already been reported on the - * other device (dev2) then this event should be also - * sent through that device. - */ - dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_LEFT, left); + /* + * If shared button has already been reported on the + * other device (dev2) then this event should be also + * sent through that device. + */ + dev = test_bit(BTN_LEFT, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_LEFT, left); - dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_RIGHT, right); + dev = test_bit(BTN_RIGHT, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_RIGHT, right); - dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; - input_report_key(dev, BTN_MIDDLE, middle); + dev = test_bit(BTN_MIDDLE, dev2->key) ? dev2 : dev1; + input_report_key(dev, BTN_MIDDLE, middle); - /* - * Sync the _other_ device now, we'll do the first - * device later once we report the rest of the events. - */ - input_sync(dev2); - } else { - /* - * For devices with non-interleaved packets we know what - * device buttons belong to so we can simply report them. - */ - input_report_key(dev1, BTN_LEFT, left); - input_report_key(dev1, BTN_RIGHT, right); - input_report_key(dev1, BTN_MIDDLE, middle); - } + /* + * Sync the _other_ device now, we'll do the first + * device later once we report the rest of the events. + */ + input_sync(dev2); } static void alps_process_packet(struct psmouse *psmouse) diff --git a/drivers/input/mouse/appletouch.c b/drivers/input/mouse/appletouch.c index 908b5b44052f..53ec7ddd1826 100644 --- a/drivers/input/mouse/appletouch.c +++ b/drivers/input/mouse/appletouch.c @@ -205,8 +205,8 @@ struct atp { bool overflow_warned; int x_old; /* last reported x/y, */ int y_old; /* used for smoothing */ - signed char xy_cur[ATP_XSENSORS + ATP_YSENSORS]; - signed char xy_old[ATP_XSENSORS + ATP_YSENSORS]; + u8 xy_cur[ATP_XSENSORS + ATP_YSENSORS]; + u8 xy_old[ATP_XSENSORS + ATP_YSENSORS]; int xy_acc[ATP_XSENSORS + ATP_YSENSORS]; int idlecount; /* number of empty packets */ struct work_struct work; @@ -531,7 +531,7 @@ static void atp_complete_geyser_1_2(struct urb *urb) for (i = 0; i < ATP_XSENSORS + ATP_YSENSORS; i++) { /* accumulate the change */ - signed char change = dev->xy_old[i] - dev->xy_cur[i]; + int change = dev->xy_old[i] - dev->xy_cur[i]; dev->xy_acc[i] -= change; /* prevent down drifting */ diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c index a13d80f7da17..f34b22bce4ff 100644 --- a/drivers/input/mousedev.c +++ b/drivers/input/mousedev.c @@ -15,7 +15,6 @@ #include <linux/sched.h> #include <linux/slab.h> -#include <linux/smp_lock.h> #include <linux/poll.h> #include <linux/module.h> #include <linux/init.h> @@ -542,10 +541,8 @@ static int mousedev_open(struct inode *inode, struct file *file) if (i >= MOUSEDEV_MINORS) return -ENODEV; - lock_kernel(); error = mutex_lock_interruptible(&mousedev_table_mutex); if (error) { - unlock_kernel(); return error; } mousedev = mousedev_table[i]; @@ -554,7 +551,6 @@ static int mousedev_open(struct inode *inode, struct file *file) mutex_unlock(&mousedev_table_mutex); if (!mousedev) { - unlock_kernel(); return -ENODEV; } @@ -575,7 +571,6 @@ static int mousedev_open(struct inode *inode, struct file *file) goto err_free_client; file->private_data = client; - unlock_kernel(); return 0; err_free_client: @@ -583,7 +578,6 @@ static int mousedev_open(struct inode *inode, struct file *file) kfree(client); err_put_mousedev: put_device(&mousedev->dev); - unlock_kernel(); return error; } diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 2a5982e532f8..ead0494721d0 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -442,6 +442,13 @@ static const struct dmi_system_id __initconst i8042_dmi_reset_table[] = { }, }, { + /* Medion Akoya E1222 */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "MEDION"), + DMI_MATCH(DMI_PRODUCT_NAME, "E122X"), + }, + }, + { /* Mivvy M310 */ .matches = { DMI_MATCH(DMI_SYS_VENDOR, "VIOOO"), @@ -624,6 +631,9 @@ static int i8042_pnp_kbd_probe(struct pnp_dev *dev, const struct pnp_device_id * strlcat(i8042_pnp_kbd_name, pnp_dev_name(dev), sizeof(i8042_pnp_kbd_name)); } + /* Keyboard ports are always supposed to be wakeup-enabled */ + device_set_wakeup_enable(&dev->dev, true); + i8042_pnp_kbd_devices++; return 0; } diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index ff4d77c4de11..9302ba0e48f8 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -1386,6 +1386,8 @@ static int __init i8042_probe(struct platform_device *dev) { int error; + i8042_platform_device = dev; + error = i8042_controller_selftest(); if (error) return error; @@ -1421,6 +1423,7 @@ static int __init i8042_probe(struct platform_device *dev) i8042_free_aux_ports(); /* in case KBD failed but AUX not */ i8042_free_irqs(); i8042_controller_reset(); + i8042_platform_device = NULL; return error; } @@ -1430,6 +1433,7 @@ static int __devexit i8042_remove(struct platform_device *dev) i8042_unregister_ports(); i8042_free_irqs(); i8042_controller_reset(); + i8042_platform_device = NULL; return 0; } @@ -1448,6 +1452,7 @@ static struct platform_driver i8042_driver = { static int __init i8042_init(void) { + struct platform_device *pdev; int err; dbg_init(); @@ -1460,31 +1465,18 @@ static int __init i8042_init(void) if (err) goto err_platform_exit; - i8042_platform_device = platform_device_alloc("i8042", -1); - if (!i8042_platform_device) { - err = -ENOMEM; + pdev = platform_create_bundle(&i8042_driver, i8042_probe, NULL, 0, NULL, 0); + if (IS_ERR(pdev)) { + err = PTR_ERR(pdev); goto err_platform_exit; } - err = platform_device_add(i8042_platform_device); - if (err) - goto err_free_device; - - err = platform_driver_probe(&i8042_driver, i8042_probe); - if (err) - goto err_del_device; - panic_blink = i8042_panic_blink; return 0; - err_del_device: - platform_device_del(i8042_platform_device); - err_free_device: - platform_device_put(i8042_platform_device); err_platform_exit: i8042_platform_exit(); - return err; } diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c index 27fdaaffbb40..998664854440 100644 --- a/drivers/input/serio/serio_raw.c +++ b/drivers/input/serio/serio_raw.c @@ -81,12 +81,12 @@ static int serio_raw_open(struct inode *inode, struct file *file) struct serio_raw_list *list; int retval = 0; - lock_kernel(); retval = mutex_lock_interruptible(&serio_raw_mutex); if (retval) - goto out_bkl; + return retval; - if (!(serio_raw = serio_raw_locate(iminor(inode)))) { + serio_raw = serio_raw_locate(iminor(inode)); + if (!serio_raw) { retval = -ENODEV; goto out; } @@ -96,7 +96,8 @@ static int serio_raw_open(struct inode *inode, struct file *file) goto out; } - if (!(list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL))) { + list = kzalloc(sizeof(struct serio_raw_list), GFP_KERNEL); + if (!list) { retval = -ENOMEM; goto out; } @@ -109,8 +110,6 @@ static int serio_raw_open(struct inode *inode, struct file *file) out: mutex_unlock(&serio_raw_mutex); -out_bkl: - unlock_kernel(); return retval; } diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index fbd3987af57f..e6bde55e5203 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -64,7 +64,8 @@ struct key_entry *sparse_keymap_entry_from_keycode(struct input_dev *dev, EXPORT_SYMBOL(sparse_keymap_entry_from_keycode); static int sparse_keymap_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, + unsigned int *keycode) { const struct key_entry *key = sparse_keymap_entry_from_scancode(dev, scancode); @@ -78,7 +79,8 @@ static int sparse_keymap_getkeycode(struct input_dev *dev, } static int sparse_keymap_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, + unsigned int keycode) { struct key_entry *key; int old_keycode; diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index a1770e6feeec..8b5d2873f0c4 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c @@ -371,7 +371,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi } else if (pen) { /* penabled only accepts exact bytes of data */ if (features->type == TABLETPC2FG) - features->pktlen = WACOM_PKGLEN_PENABLED; + features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->x_max = wacom_le16_to_cpu(&report[i + 3]); @@ -410,7 +410,7 @@ static int wacom_parse_hid(struct usb_interface *intf, struct hid_descriptor *hi } else if (pen) { /* penabled only accepts exact bytes of data */ if (features->type == TABLETPC2FG) - features->pktlen = WACOM_PKGLEN_PENABLED; + features->pktlen = WACOM_PKGLEN_GRAPHIRE; features->device_type = BTN_TOOL_PEN; features->y_max = wacom_le16_to_cpu(&report[i + 3]); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 3d81443e683a..b3ba3437a2eb 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -155,19 +155,19 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; - int x, y, rw; - static int penData = 0; + int x, y, prox; + int rw = 0; + int retval = 0; if (data[0] != WACOM_REPORT_PENABLED) { dbg("wacom_graphire_irq: received unknown report #%d", data[0]); - return 0; + goto exit; } - if (data[1] & 0x80) { - /* in prox and not a pad data */ - penData = 1; - - switch ((data[1] >> 5) & 3) { + prox = data[1] & 0x80; + if (prox || wacom->id[0]) { + if (prox) { + switch ((data[1] >> 5) & 3) { case 0: /* Pen */ wacom->tool[0] = BTN_TOOL_PEN; @@ -181,23 +181,13 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) case 2: /* Mouse with wheel */ wacom_report_key(wcombo, BTN_MIDDLE, data[1] & 0x04); - if (features->type == WACOM_G4 || features->type == WACOM_MO) { - rw = data[7] & 0x04 ? (data[7] & 0x03)-4 : (data[7] & 0x03); - wacom_report_rel(wcombo, REL_WHEEL, -rw); - } else - wacom_report_rel(wcombo, REL_WHEEL, -(signed char) data[6]); /* fall through */ case 3: /* Mouse without wheel */ wacom->tool[0] = BTN_TOOL_MOUSE; wacom->id[0] = CURSOR_DEVICE_ID; - wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); - wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); - if (features->type == WACOM_G4 || features->type == WACOM_MO) - wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); - else - wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); break; + } } x = wacom_le16_to_cpu(&data[2]); y = wacom_le16_to_cpu(&data[4]); @@ -208,36 +198,32 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x01); wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x04); - } - wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ - wacom_report_key(wcombo, wacom->tool[0], 1); - } else if (wacom->id[0]) { - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - if (wacom->tool[0] == BTN_TOOL_MOUSE) { - wacom_report_key(wcombo, BTN_LEFT, 0); - wacom_report_key(wcombo, BTN_RIGHT, 0); - wacom_report_abs(wcombo, ABS_DISTANCE, 0); } else { - wacom_report_abs(wcombo, ABS_PRESSURE, 0); - wacom_report_key(wcombo, BTN_TOUCH, 0); - wacom_report_key(wcombo, BTN_STYLUS, 0); - wacom_report_key(wcombo, BTN_STYLUS2, 0); + wacom_report_key(wcombo, BTN_LEFT, data[1] & 0x01); + wacom_report_key(wcombo, BTN_RIGHT, data[1] & 0x02); + if (features->type == WACOM_G4 || + features->type == WACOM_MO) { + wacom_report_abs(wcombo, ABS_DISTANCE, data[6] & 0x3f); + rw = (signed)(data[7] & 0x04) - (data[7] & 0x03); + } else { + wacom_report_abs(wcombo, ABS_DISTANCE, data[7] & 0x3f); + rw = -(signed)data[6]; + } + wacom_report_rel(wcombo, REL_WHEEL, rw); } - wacom->id[0] = 0; - wacom_report_abs(wcombo, ABS_MISC, 0); /* reset tool id */ - wacom_report_key(wcombo, wacom->tool[0], 0); + + if (!prox) + wacom->id[0] = 0; + wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); /* report tool id */ + wacom_report_key(wcombo, wacom->tool[0], prox); + wacom_input_sync(wcombo); /* sync last event */ } /* send pad data */ switch (features->type) { case WACOM_G4: - if (data[7] & 0xf8) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } + prox = data[7] & 0xf8; + if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); @@ -245,29 +231,16 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_rel(wcombo, REL_WHEEL, rw); wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } else if (wacom->id[1]) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } - wacom->id[1] = 0; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x40)); - wacom_report_key(wcombo, BTN_4, (data[7] & 0x80)); - wacom_report_rel(wcombo, REL_WHEEL, 0); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); + if (!prox) + wacom->id[1] = 0; + wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); } + retval = 1; break; case WACOM_MO: - if ((data[7] & 0xf8) || (data[8] & 0xff)) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } + prox = (data[7] & 0xf8) || data[8]; + if (prox || wacom->id[1]) { wacom->id[1] = PAD_DEVICE_ID; wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); @@ -275,27 +248,16 @@ static int wacom_graphire_irq(struct wacom_wac *wacom, void *wcombo) wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); wacom_report_key(wcombo, BTN_TOOL_FINGER, 0xf0); + if (!prox) + wacom->id[1] = 0; wacom_report_abs(wcombo, ABS_MISC, wacom->id[1]); wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); - } else if (wacom->id[1]) { - if (penData) { - wacom_input_sync(wcombo); /* sync last event */ - if (!wacom->id[0]) - penData = 0; - } - wacom->id[1] = 0; - wacom_report_key(wcombo, BTN_0, (data[7] & 0x08)); - wacom_report_key(wcombo, BTN_1, (data[7] & 0x20)); - wacom_report_key(wcombo, BTN_4, (data[7] & 0x10)); - wacom_report_key(wcombo, BTN_5, (data[7] & 0x40)); - wacom_report_abs(wcombo, ABS_WHEEL, (data[8] & 0x7f)); - wacom_report_key(wcombo, BTN_TOOL_FINGER, 0); - wacom_report_abs(wcombo, ABS_MISC, 0); - wacom_input_event(wcombo, EV_MSC, MSC_SERIAL, 0xf0); } + retval = 1; break; } - return 1; +exit: + return retval; } static int wacom_intuos_inout(struct wacom_wac *wacom, void *wcombo) @@ -636,9 +598,9 @@ static int wacom_intuos_irq(struct wacom_wac *wacom, void *wcombo) static void wacom_tpc_finger_in(struct wacom_wac *wacom, void *wcombo, char *data, int idx) { wacom_report_abs(wcombo, ABS_X, - (data[2 + idx * 2] & 0xff) | ((data[3 + idx * 2] & 0x7f) << 8)); + data[2 + idx * 2] | ((data[3 + idx * 2] & 0x7f) << 8)); wacom_report_abs(wcombo, ABS_Y, - (data[6 + idx * 2] & 0xff) | ((data[7 + idx * 2] & 0x7f) << 8)); + data[6 + idx * 2] | ((data[7 + idx * 2] & 0x7f) << 8)); wacom_report_abs(wcombo, ABS_MISC, wacom->id[0]); wacom_report_key(wcombo, wacom->tool[idx], 1); if (idx) @@ -782,31 +744,24 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, void *wcombo) touchInProx = 0; - if (prox) { /* in prox */ - if (!wacom->id[0]) { - /* Going into proximity select tool */ - wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; - if (wacom->tool[0] == BTN_TOOL_PEN) - wacom->id[0] = STYLUS_DEVICE_ID; - else - wacom->id[0] = ERASER_DEVICE_ID; - } - wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); - wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); - wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); - wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); - pressure = ((data[7] & 0x01) << 8) | data[6]; - if (pressure < 0) - pressure = features->pressure_max + pressure + 1; - wacom_report_abs(wcombo, ABS_PRESSURE, pressure); - wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); - } else { - wacom_report_abs(wcombo, ABS_X, 0); - wacom_report_abs(wcombo, ABS_Y, 0); - wacom_report_abs(wcombo, ABS_PRESSURE, 0); - wacom_report_key(wcombo, BTN_STYLUS, 0); - wacom_report_key(wcombo, BTN_STYLUS2, 0); - wacom_report_key(wcombo, BTN_TOUCH, 0); + if (!wacom->id[0]) { /* first in prox */ + /* Going into proximity select tool */ + wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN; + if (wacom->tool[0] == BTN_TOOL_PEN) + wacom->id[0] = STYLUS_DEVICE_ID; + else + wacom->id[0] = ERASER_DEVICE_ID; + } + wacom_report_key(wcombo, BTN_STYLUS, data[1] & 0x02); + wacom_report_key(wcombo, BTN_STYLUS2, data[1] & 0x10); + wacom_report_abs(wcombo, ABS_X, wacom_le16_to_cpu(&data[2])); + wacom_report_abs(wcombo, ABS_Y, wacom_le16_to_cpu(&data[4])); + pressure = ((data[7] & 0x01) << 8) | data[6]; + if (pressure < 0) + pressure = features->pressure_max + pressure + 1; + wacom_report_abs(wcombo, ABS_PRESSURE, pressure); + wacom_report_key(wcombo, BTN_TOUCH, data[1] & 0x05); + if (!prox) { /* out-prox */ wacom->id[0] = 0; /* pen is out so touch can be enabled now */ touchInProx = 1; @@ -1028,7 +983,7 @@ static const struct wacom_features wacom_features_0x93 = static const struct wacom_features wacom_features_0x9A = { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; static const struct wacom_features wacom_features_0x9F = - { "Wacom ISDv4 9F", WACOM_PKGLEN_PENABLED, 26202, 16325, 255, 0, TABLETPC }; + { "Wacom ISDv4 9F", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; static const struct wacom_features wacom_features_0xE2 = { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; static const struct wacom_features wacom_features_0xE3 = diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 8590b1e8ec37..b50cf04e61a8 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -17,7 +17,6 @@ #define WACOM_PKGLEN_GRAPHIRE 8 #define WACOM_PKGLEN_BBFUN 9 #define WACOM_PKGLEN_INTUOS 10 -#define WACOM_PKGLEN_PENABLED 8 #define WACOM_PKGLEN_TPC1FG 5 #define WACOM_PKGLEN_TPC2FG 14 diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 7208654a94ae..8a8fa4d2d6a8 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig @@ -24,17 +24,18 @@ config TOUCHSCREEN_88PM860X module will be called 88pm860x-ts. config TOUCHSCREEN_ADS7846 - tristate "ADS7846/TSC2046 and ADS7843 based touchscreens" + tristate "ADS7846/TSC2046/AD7873 and AD(S)7843 based touchscreens" depends on SPI_MASTER depends on HWMON = n || HWMON help Say Y here if you have a touchscreen interface using the - ADS7846/TSC2046 or ADS7843 controller, and your board-specific - setup code includes that in its table of SPI devices. + ADS7846/TSC2046/AD7873 or ADS7843/AD7843 controller, + and your board-specific setup code includes that in its + table of SPI devices. If HWMON is selected, and the driver is told the reference voltage on your board, you will also get hwmon interfaces for the voltage - (and on ads7846/tsc2046, temperature) sensors of this chip. + (and on ads7846/tsc2046/ad7873, temperature) sensors of this chip. If unsure, say N (but it's safe to say "Y"). diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index eb83939c705e..e019d53d1ab4 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c @@ -46,7 +46,7 @@ #include <linux/spi/ad7877.h> #include <asm/irq.h> -#define TS_PEN_UP_TIMEOUT msecs_to_jiffies(50) +#define TS_PEN_UP_TIMEOUT msecs_to_jiffies(100) #define MAX_SPI_FREQ_HZ 20000000 #define MAX_12BIT ((1<<12)-1) diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 8b05d8e97543..532279cda0e4 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c @@ -36,6 +36,7 @@ * TSC2046 is just newer ads7846 silicon. * Support for ads7843 tested on Atmel at91sam926x-EK. * Support for ads7845 has only been stubbed in. + * Support for Analog Devices AD7873 and AD7843 tested. * * IRQ handling needs a workaround because of a shortcoming in handling * edge triggered IRQs on some platforms like the OMAP1/2. These @@ -821,6 +822,9 @@ static int ads7846_suspend(struct spi_device *spi, pm_message_t message) spin_unlock_irq(&ts->lock); + if (device_may_wakeup(&ts->spi->dev)) + enable_irq_wake(ts->spi->irq); + return 0; } @@ -829,6 +833,9 @@ static int ads7846_resume(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + if (device_may_wakeup(&ts->spi->dev)) + disable_irq_wake(ts->spi->irq); + spin_lock_irq(&ts->lock); ts->is_suspended = 0; @@ -984,6 +991,15 @@ static int __devinit ads7846_probe(struct spi_device *spi) vref = pdata->keep_vref_on; + if (ts->model == 7873) { + /* The AD7873 is almost identical to the ADS7846 + * keep VREF off during differential/ratiometric + * conversion modes + */ + ts->model = 7846; + vref = 0; + } + /* set up the transfers to read touchscreen state; this assumes we * use formula #2 for pressure, not #3. */ @@ -1191,6 +1207,8 @@ static int __devinit ads7846_probe(struct spi_device *spi) if (err) goto err_remove_attr_group; + device_init_wakeup(&spi->dev, pdata->wakeup); + return 0; err_remove_attr_group: @@ -1220,6 +1238,8 @@ static int __devexit ads7846_remove(struct spi_device *spi) { struct ads7846 *ts = dev_get_drvdata(&spi->dev); + device_init_wakeup(&spi->dev, false); + ads784x_hwmon_unregister(spi, ts); input_unregister_device(ts->input); diff --git a/drivers/media/IR/ir-keytable.c b/drivers/media/IR/ir-keytable.c index 0903f539bf68..0a3b4ed38e48 100644 --- a/drivers/media/IR/ir-keytable.c +++ b/drivers/media/IR/ir-keytable.c @@ -123,7 +123,7 @@ static int ir_copy_table(struct ir_scancode_table *destin, * If the key is not found, returns -EINVAL, otherwise, returns 0. */ static int ir_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, unsigned int *keycode) { int elem; struct ir_input_dev *ir_dev = input_get_drvdata(dev); @@ -291,7 +291,7 @@ static int ir_insert_key(struct ir_scancode_table *rc_tab, * If the key is not found, returns -EINVAL, otherwise, returns 0. */ static int ir_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, unsigned int keycode) { int rc = 0; struct ir_input_dev *ir_dev = input_get_drvdata(dev); diff --git a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c index a03ef7efec9a..852fe89539cf 100644 --- a/drivers/media/dvb/dvb-usb/dvb-usb-remote.c +++ b/drivers/media/dvb/dvb-usb/dvb-usb-remote.c @@ -9,7 +9,7 @@ #include <linux/usb/input.h> static int dvb_usb_getkeycode(struct input_dev *dev, - int scancode, int *keycode) + unsigned int scancode, unsigned int *keycode) { struct dvb_usb_device *d = input_get_drvdata(dev); @@ -39,7 +39,7 @@ static int dvb_usb_getkeycode(struct input_dev *dev, } static int dvb_usb_setkeycode(struct input_dev *dev, - int scancode, int keycode) + unsigned int scancode, unsigned int keycode) { struct dvb_usb_device *d = input_get_drvdata(dev); diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig index d16af6a423fb..2191c8d896a0 100644 --- a/drivers/misc/Kconfig +++ b/drivers/misc/Kconfig @@ -268,6 +268,16 @@ config ISL29003 This driver can also be built as a module. If so, the module will be called isl29003. +config SENSORS_TSL2550 + tristate "Taos TSL2550 ambient light sensor" + depends on I2C && SYSFS + help + If you say yes here you get support for the Taos TSL2550 + ambient light sensor. + + This driver can also be built as a module. If so, the module + will be called tsl2550. + config EP93XX_PWM tristate "EP93xx PWM support" depends on ARCH_EP93XX diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 049ff2482f30..27c484355414 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -21,6 +21,7 @@ obj-$(CONFIG_SGI_GRU) += sgi-gru/ obj-$(CONFIG_CS5535_MFGPT) += cs5535-mfgpt.o obj-$(CONFIG_HP_ILO) += hpilo.o obj-$(CONFIG_ISL29003) += isl29003.o +obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o obj-$(CONFIG_DS1682) += ds1682.o obj-$(CONFIG_TI_DAC7512) += ti_dac7512.o diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c index 2cb2736d65aa..db7d0f21b65d 100644 --- a/drivers/misc/eeprom/at24.c +++ b/drivers/misc/eeprom/at24.c @@ -505,6 +505,7 @@ static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id) * Export the EEPROM bytes through sysfs, since that's convenient. * By default, only root should see the data (maybe passwords etc) */ + sysfs_bin_attr_init(&at24->bin); at24->bin.attr.name = "eeprom"; at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR; at24->bin.read = at24_bin_read; diff --git a/drivers/i2c/chips/tsl2550.c b/drivers/misc/tsl2550.c index a0702f36a72f..483ae5f7f68e 100644 --- a/drivers/i2c/chips/tsl2550.c +++ b/drivers/misc/tsl2550.c @@ -47,8 +47,8 @@ struct tsl2550_data { struct i2c_client *client; struct mutex update_lock; - unsigned int power_state : 1; - unsigned int operating_mode : 1; + unsigned int power_state:1; + unsigned int operating_mode:1; }; /* diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 1157d5679e66..42e5ea49e975 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -457,7 +457,7 @@ config MTD_NAND_NOMADIK config MTD_NAND_SH_FLCTL tristate "Support for NAND on Renesas SuperH FLCTL" - depends on MTD_NAND && SUPERH + depends on MTD_NAND && (SUPERH || ARCH_SHMOBILE) help Several Renesas SuperH CPU has FLCTL. This option enables support for NAND Flash using FLCTL. diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index 7029cd50c458..0ba5b8e50a7c 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -907,7 +907,7 @@ config SMC91X select CRC32 select MII depends on ARM || REDWOOD_5 || REDWOOD_6 || M32R || SUPERH || \ - MIPS || BLACKFIN || MN10300 + MIPS || BLACKFIN || MN10300 || COLDFIRE help This is a driver for SMC's 91x series of Ethernet chipsets, including the SMC91C94 and the SMC91C111. Say Y if you want it diff --git a/drivers/net/arm/ks8695net.c b/drivers/net/arm/ks8695net.c index 8ca639127dbc..a1d4188c430b 100644 --- a/drivers/net/arm/ks8695net.c +++ b/drivers/net/arm/ks8695net.c @@ -575,9 +575,9 @@ static int ks8695_poll(struct napi_struct *napi, int budget) if (work_done < budget) { unsigned long flags; spin_lock_irqsave(&ksp->rx_lock, flags); + __napi_complete(napi); /*enable rx interrupt*/ writel(isr | mask_bit, KS8695_IRQ_VA + KS8695_INTEN); - __napi_complete(napi); spin_unlock_irqrestore(&ksp->rx_lock, flags); } return work_done; diff --git a/drivers/net/benet/be.h b/drivers/net/benet/be.h index be81fb2d10f7..8f0752553681 100644 --- a/drivers/net/benet/be.h +++ b/drivers/net/benet/be.h @@ -290,11 +290,6 @@ extern const struct ethtool_ops be_ethtool_ops; #define drvr_stats(adapter) (&adapter->stats.drvr_stats) -static inline unsigned int be_pci_func(struct be_adapter *adapter) -{ - return PCI_FUNC(adapter->pdev->devfn); -} - #define BE_SET_NETDEV_OPS(netdev, ops) (netdev->netdev_ops = ops) #define PAGE_SHIFT_4K 12 diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c index 4b1f80519ca4..c59215361f4e 100644 --- a/drivers/net/benet/be_cmds.c +++ b/drivers/net/benet/be_cmds.c @@ -465,8 +465,6 @@ int be_cmd_eq_create(struct be_adapter *adapter, req->num_pages = cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size)); - AMAP_SET_BITS(struct amap_eq_context, func, req->context, - be_pci_func(adapter)); AMAP_SET_BITS(struct amap_eq_context, valid, req->context, 1); /* 4byte eqe*/ AMAP_SET_BITS(struct amap_eq_context, size, req->context, 0); @@ -629,7 +627,6 @@ int be_cmd_cq_create(struct be_adapter *adapter, AMAP_SET_BITS(struct amap_cq_context, eventable, ctxt, 1); AMAP_SET_BITS(struct amap_cq_context, eqid, ctxt, eq->id); AMAP_SET_BITS(struct amap_cq_context, armed, ctxt, 1); - AMAP_SET_BITS(struct amap_cq_context, func, ctxt, be_pci_func(adapter)); be_dws_cpu_to_le(ctxt, sizeof(req->context)); be_cmd_page_addrs_prepare(req->pages, ARRAY_SIZE(req->pages), q_mem); @@ -678,7 +675,6 @@ int be_cmd_mccq_create(struct be_adapter *adapter, req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size); - AMAP_SET_BITS(struct amap_mcc_context, fid, ctxt, be_pci_func(adapter)); AMAP_SET_BITS(struct amap_mcc_context, valid, ctxt, 1); AMAP_SET_BITS(struct amap_mcc_context, ring_size, ctxt, be_encoded_q_len(mccq->len)); @@ -727,8 +723,6 @@ int be_cmd_txq_create(struct be_adapter *adapter, AMAP_SET_BITS(struct amap_tx_context, tx_ring_size, ctxt, be_encoded_q_len(txq->len)); - AMAP_SET_BITS(struct amap_tx_context, pci_func_id, ctxt, - be_pci_func(adapter)); AMAP_SET_BITS(struct amap_tx_context, ctx_valid, ctxt, 1); AMAP_SET_BITS(struct amap_tx_context, cq_id_send, ctxt, cq->id); diff --git a/drivers/net/benet/be_hw.h b/drivers/net/benet/be_hw.h index 5ffb149181ad..2d4a4b827637 100644 --- a/drivers/net/benet/be_hw.h +++ b/drivers/net/benet/be_hw.h @@ -114,8 +114,7 @@ #define IMG_TYPE_ISCSI_BACKUP 9 #define IMG_TYPE_FCOE_FW_ACTIVE 10 #define IMG_TYPE_FCOE_FW_BACKUP 11 -#define IMG_TYPE_NCSI_BITFILE 13 -#define IMG_TYPE_NCSI_8051 14 +#define IMG_TYPE_NCSI_FW 13 #define FLASHROM_OPER_FLASH 1 #define FLASHROM_OPER_SAVE 2 @@ -127,6 +126,7 @@ #define FLASH_IMAGE_MAX_SIZE_g3 (2097152) /* Max fw image size */ #define FLASH_BIOS_IMAGE_MAX_SIZE_g3 (524288) /* Max OPTION ROM img sz */ #define FLASH_REDBOOT_IMAGE_MAX_SIZE_g3 (1048576) /* Max Redboot image sz */ +#define FLASH_NCSI_IMAGE_MAX_SIZE_g3 (262144) /* Max NSCI image sz */ #define FLASH_NCSI_MAGIC (0x16032009) #define FLASH_NCSI_DISABLED (0) @@ -144,6 +144,7 @@ #define FLASH_FCoE_BIOS_START_g2 (524288) #define FLASH_REDBOOT_START_g2 (0) +#define FLASH_NCSI_START_g3 (15990784) #define FLASH_iSCSI_PRIMARY_IMAGE_START_g3 (2097152) #define FLASH_iSCSI_BACKUP_IMAGE_START_g3 (4194304) #define FLASH_FCoE_PRIMARY_IMAGE_START_g3 (6291456) diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c index a703ed8e24fe..43e8032f9236 100644 --- a/drivers/net/benet/be_main.c +++ b/drivers/net/benet/be_main.c @@ -1382,7 +1382,7 @@ rx_eq_free: /* There are 8 evt ids per func. Retruns the evt id's bit number */ static inline int be_evt_bit_get(struct be_adapter *adapter, u32 eq_id) { - return eq_id - 8 * be_pci_func(adapter); + return eq_id % 8; } static irqreturn_t be_intx(int irq, void *dev) @@ -1880,8 +1880,9 @@ static int be_flash_data(struct be_adapter *adapter, const u8 *p = fw->data; struct be_cmd_write_flashrom *req = flash_cmd->va; struct flash_comp *pflashcomp; + int num_comp; - struct flash_comp gen3_flash_types[8] = { + struct flash_comp gen3_flash_types[9] = { { FLASH_iSCSI_PRIMARY_IMAGE_START_g3, IMG_TYPE_ISCSI_ACTIVE, FLASH_IMAGE_MAX_SIZE_g3}, { FLASH_REDBOOT_START_g3, IMG_TYPE_REDBOOT, @@ -1897,7 +1898,9 @@ static int be_flash_data(struct be_adapter *adapter, { FLASH_FCoE_PRIMARY_IMAGE_START_g3, IMG_TYPE_FCOE_FW_ACTIVE, FLASH_IMAGE_MAX_SIZE_g3}, { FLASH_FCoE_BACKUP_IMAGE_START_g3, IMG_TYPE_FCOE_FW_BACKUP, - FLASH_IMAGE_MAX_SIZE_g3} + FLASH_IMAGE_MAX_SIZE_g3}, + { FLASH_NCSI_START_g3, IMG_TYPE_NCSI_FW, + FLASH_NCSI_IMAGE_MAX_SIZE_g3} }; struct flash_comp gen2_flash_types[8] = { { FLASH_iSCSI_PRIMARY_IMAGE_START_g2, IMG_TYPE_ISCSI_ACTIVE, @@ -1921,11 +1924,16 @@ static int be_flash_data(struct be_adapter *adapter, if (adapter->generation == BE_GEN3) { pflashcomp = gen3_flash_types; filehdr_size = sizeof(struct flash_file_hdr_g3); + num_comp = 9; } else { pflashcomp = gen2_flash_types; filehdr_size = sizeof(struct flash_file_hdr_g2); + num_comp = 8; } - for (i = 0; i < 8; i++) { + for (i = 0; i < num_comp; i++) { + if ((pflashcomp[i].optype == IMG_TYPE_NCSI_FW) && + memcmp(adapter->fw_ver, "3.102.148.0", 11) < 0) + continue; if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) && (!be_flash_redboot(adapter, fw->data, pflashcomp[i].offset, pflashcomp[i].size, @@ -1985,16 +1993,7 @@ int be_load_fw(struct be_adapter *adapter, u8 *func) struct be_dma_mem flash_cmd; int status, i = 0; const u8 *p; - char fw_ver[FW_VER_LEN]; - char fw_cfg; - - status = be_cmd_get_fw_ver(adapter, fw_ver); - if (status) - return status; - fw_cfg = *(fw_ver + 2); - if (fw_cfg == '0') - fw_cfg = '1'; strcpy(fw_file, func); status = request_firmware(&fw, fw_file, &adapter->pdev->dev); diff --git a/drivers/net/can/bfin_can.c b/drivers/net/can/bfin_can.c index bf7f9ba2d903..866905fa4119 100644 --- a/drivers/net/can/bfin_can.c +++ b/drivers/net/can/bfin_can.c @@ -26,6 +26,7 @@ #define DRV_NAME "bfin_can" #define BFIN_CAN_TIMEOUT 100 +#define TX_ECHO_SKB_MAX 1 /* * transmit and receive channels @@ -593,7 +594,7 @@ struct net_device *alloc_bfin_candev(void) struct net_device *dev; struct bfin_can_priv *priv; - dev = alloc_candev(sizeof(*priv)); + dev = alloc_candev(sizeof(*priv), TX_ECHO_SKB_MAX); if (!dev) return NULL; diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c index 11c87840cc00..33451092b8e8 100644 --- a/drivers/net/can/usb/ems_usb.c +++ b/drivers/net/can/usb/ems_usb.c @@ -876,9 +876,7 @@ static netdev_tx_t ems_usb_start_xmit(struct sk_buff *skb, struct net_device *ne return NETDEV_TX_OK; nomem: - if (skb) - dev_kfree_skb(skb); - + dev_kfree_skb(skb); stats->tx_dropped++; return NETDEV_TX_OK; diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index 7cbcfb0ade1c..9bd155e4111c 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c @@ -5072,7 +5072,7 @@ static int __devinit cas_init_one(struct pci_dev *pdev, INIT_WORK(&cp->reset_task, cas_reset_task); /* Default link parameters */ - if (link_mode >= 0 && link_mode <= 6) + if (link_mode >= 0 && link_mode < 6) cp->link_cntl = link_modes[link_mode]; else cp->link_cntl = BMCR_ANENABLE; diff --git a/drivers/net/cpmac.c b/drivers/net/cpmac.c index b85c81f60d10..60777fd90b33 100644 --- a/drivers/net/cpmac.c +++ b/drivers/net/cpmac.c @@ -28,6 +28,7 @@ #include <linux/delay.h> #include <linux/netdevice.h> +#include <linux/if_vlan.h> #include <linux/etherdevice.h> #include <linux/ethtool.h> #include <linux/skbuff.h> @@ -55,9 +56,9 @@ module_param(dumb_switch, int, 0444); MODULE_PARM_DESC(debug_level, "Number of NETIF_MSG bits to enable"); MODULE_PARM_DESC(dumb_switch, "Assume switch is not connected to MDIO bus"); -#define CPMAC_VERSION "0.5.1" -/* frame size + 802.1q tag */ -#define CPMAC_SKB_SIZE (ETH_FRAME_LEN + 4) +#define CPMAC_VERSION "0.5.2" +/* frame size + 802.1q tag + FCS size */ +#define CPMAC_SKB_SIZE (ETH_FRAME_LEN + ETH_FCS_LEN + VLAN_HLEN) #define CPMAC_QUEUES 8 /* Ethernet registers */ @@ -1136,8 +1137,9 @@ static int __devinit cpmac_probe(struct platform_device *pdev) } if (phy_id == PHY_MAX_ADDR) { - dev_err(&pdev->dev, "no PHY present\n"); - return -ENODEV; + dev_err(&pdev->dev, "no PHY present, falling back to switch on MDIO bus 0\n"); + strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE); /* fixed phys bus */ + phy_id = pdev->id; } dev = alloc_etherdev_mq(sizeof(*priv), CPMAC_QUEUES); @@ -1290,8 +1292,8 @@ void __devexit cpmac_exit(void) { platform_driver_unregister(&cpmac_driver); mdiobus_unregister(cpmac_mii); - mdiobus_free(cpmac_mii); iounmap(cpmac_mii->priv); + mdiobus_free(cpmac_mii); } module_init(cpmac_init); diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 3e453e1d97e7..9e3e8750b46a 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c @@ -1294,6 +1294,7 @@ static void cxgb_down(struct adapter *adapter) free_irq_resources(adapter); quiesce_rx(adapter); + t3_sge_stop(adapter); flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */ } diff --git a/drivers/net/davinci_emac.c b/drivers/net/davinci_emac.c index 13f9869927e3..8bd086aee56d 100644 --- a/drivers/net/davinci_emac.c +++ b/drivers/net/davinci_emac.c @@ -2385,7 +2385,7 @@ static int emac_dev_open(struct net_device *ndev) struct emac_priv *priv = netdev_priv(ndev); netif_carrier_off(ndev); - for (cnt = 0; cnt <= ETH_ALEN; cnt++) + for (cnt = 0; cnt < ETH_ALEN; cnt++) ndev->dev_addr[cnt] = priv->mac_addr[cnt]; /* Configuration items */ diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h index db05ec355749..e301e26d6897 100644 --- a/drivers/net/e1000e/defines.h +++ b/drivers/net/e1000e/defines.h @@ -320,6 +320,8 @@ #define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ /* Header split receive */ +#define E1000_RFCTL_NFSW_DIS 0x00000040 +#define E1000_RFCTL_NFSR_DIS 0x00000080 #define E1000_RFCTL_ACK_DIS 0x00001000 #define E1000_RFCTL_EXTEN 0x00008000 #define E1000_RFCTL_IPV6_EX_DIS 0x00010000 diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 54d03a0ce3ce..8b5e157e9c87 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -2740,6 +2740,16 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) reg &= ~(1 << 31); ew32(STATUS, reg); } + + /* + * work-around descriptor data corruption issue during nfs v2 udp + * traffic, just disable the nfs filtering capability + */ + reg = er32(RFCTL); + reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); + ew32(RFCTL, reg); + + return; } /** diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 61a7b4351e78..b6715553cf17 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c @@ -2021,7 +2021,6 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) } /* setup the TxBD length and buffer pointer for the first BD */ - tx_queue->tx_skbuff[tx_queue->skb_curtx] = skb; txbdp_start->bufPtr = dma_map_single(&priv->ofdev->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE); @@ -2053,6 +2052,10 @@ static int gfar_start_xmit(struct sk_buff *skb, struct net_device *dev) txbdp_start->lstatus = lstatus; + eieio(); /* force lstatus write before tx_skbuff */ + + tx_queue->tx_skbuff[tx_queue->skb_curtx] = skb; + /* Update the current skb pointer to the next entry we will use * (wrapping if necessary) */ tx_queue->skb_curtx = (tx_queue->skb_curtx + 1) & diff --git a/drivers/net/irda/irda-usb.c b/drivers/net/irda/irda-usb.c index e8e33bb9d876..2c9b3af16612 100644 --- a/drivers/net/irda/irda-usb.c +++ b/drivers/net/irda/irda-usb.c @@ -1651,6 +1651,8 @@ static int irda_usb_probe(struct usb_interface *intf, self->rx_urb = kcalloc(self->max_rx_urb, sizeof(struct urb *), GFP_KERNEL); + if (!self->rx_urb) + goto err_free_net; for (i = 0; i < self->max_rx_urb; i++) { self->rx_urb[i] = usb_alloc_urb(0, GFP_KERNEL); @@ -1783,6 +1785,8 @@ err_out_2: err_out_1: for (i = 0; i < self->max_rx_urb; i++) usb_free_urb(self->rx_urb[i]); + kfree(self->rx_urb); +err_free_net: free_netdev(net); err_out: return ret; diff --git a/drivers/net/qlcnic/qlcnic.h b/drivers/net/qlcnic/qlcnic.h index b40a851ec7d1..0da94b208db1 100644 --- a/drivers/net/qlcnic/qlcnic.h +++ b/drivers/net/qlcnic/qlcnic.h @@ -423,6 +423,11 @@ struct qlcnic_adapter_stats { u64 lro_pkts; u64 rxbytes; u64 txbytes; + u64 lrobytes; + u64 lso_frames; + u64 xmit_on; + u64 xmit_off; + u64 skb_alloc_failure; }; /* @@ -1095,11 +1100,11 @@ struct qlcnic_brdinfo { static const struct qlcnic_brdinfo qlcnic_boards[] = { {0x1077, 0x8020, 0x1077, 0x203, - "8200 Series Single Port 10GbE Converged Network Adapter \ - (TCP/IP Networking)"}, + "8200 Series Single Port 10GbE Converged Network Adapter " + "(TCP/IP Networking)"}, {0x1077, 0x8020, 0x1077, 0x207, - "8200 Series Dual Port 10GbE Converged Network Adapter \ - (TCP/IP Networking)"}, + "8200 Series Dual Port 10GbE Converged Network Adapter " + "(TCP/IP Networking)"}, {0x1077, 0x8020, 0x1077, 0x20b, "3200 Series Dual Port 10Gb Intelligent Ethernet Adapter"}, {0x1077, 0x8020, 0x1077, 0x20c, diff --git a/drivers/net/qlcnic/qlcnic_ethtool.c b/drivers/net/qlcnic/qlcnic_ethtool.c index 8da6ec8c13b9..f83e15fe3e1b 100644 --- a/drivers/net/qlcnic/qlcnic_ethtool.c +++ b/drivers/net/qlcnic/qlcnic_ethtool.c @@ -59,6 +59,17 @@ static const struct qlcnic_stats qlcnic_gstrings_stats[] = { QLC_SIZEOF(stats.rxbytes), QLC_OFF(stats.rxbytes)}, {"tx_bytes", QLC_SIZEOF(stats.txbytes), QLC_OFF(stats.txbytes)}, + {"lrobytes", + QLC_SIZEOF(stats.lrobytes), QLC_OFF(stats.lrobytes)}, + {"lso_frames", + QLC_SIZEOF(stats.lso_frames), QLC_OFF(stats.lso_frames)}, + {"xmit_on", + QLC_SIZEOF(stats.xmit_on), QLC_OFF(stats.xmit_on)}, + {"xmit_off", + QLC_SIZEOF(stats.xmit_off), QLC_OFF(stats.xmit_off)}, + {"skb_alloc_failure", QLC_SIZEOF(stats.skb_alloc_failure), + QLC_OFF(stats.skb_alloc_failure)}, + }; #define QLCNIC_STATS_LEN ARRAY_SIZE(qlcnic_gstrings_stats) @@ -785,6 +796,11 @@ qlcnic_get_ethtool_stats(struct net_device *dev, } } +static u32 qlcnic_get_tx_csum(struct net_device *dev) +{ + return dev->features & NETIF_F_IP_CSUM; +} + static u32 qlcnic_get_rx_csum(struct net_device *dev) { struct qlcnic_adapter *adapter = netdev_priv(dev); @@ -995,6 +1011,7 @@ const struct ethtool_ops qlcnic_ethtool_ops = { .set_ringparam = qlcnic_set_ringparam, .get_pauseparam = qlcnic_get_pauseparam, .set_pauseparam = qlcnic_set_pauseparam, + .get_tx_csum = qlcnic_get_tx_csum, .set_tx_csum = ethtool_op_set_tx_csum, .set_sg = ethtool_op_set_sg, .get_tso = qlcnic_get_tso, diff --git a/drivers/net/qlcnic/qlcnic_hw.c b/drivers/net/qlcnic/qlcnic_hw.c index 99a4d1379d00..da00e162b6d3 100644 --- a/drivers/net/qlcnic/qlcnic_hw.c +++ b/drivers/net/qlcnic/qlcnic_hw.c @@ -349,6 +349,7 @@ qlcnic_send_cmd_descs(struct qlcnic_adapter *adapter, if (nr_desc >= qlcnic_tx_avail(tx_ring)) { netif_tx_stop_queue(tx_ring->txq); __netif_tx_unlock_bh(tx_ring->txq); + adapter->stats.xmit_off++; return -EBUSY; } @@ -397,20 +398,16 @@ qlcnic_sre_macaddr_change(struct qlcnic_adapter *adapter, u8 *addr, return qlcnic_send_cmd_descs(adapter, (struct cmd_desc_type0 *)&req, 1); } -static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, - u8 *addr, struct list_head *del_list) +static int qlcnic_nic_add_mac(struct qlcnic_adapter *adapter, u8 *addr) { struct list_head *head; struct qlcnic_mac_list_s *cur; /* look up if already exists */ - list_for_each(head, del_list) { + list_for_each(head, &adapter->mac_list) { cur = list_entry(head, struct qlcnic_mac_list_s, list); - - if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) { - list_move_tail(head, &adapter->mac_list); + if (memcmp(addr, cur->mac_addr, ETH_ALEN) == 0) return 0; - } } cur = kzalloc(sizeof(struct qlcnic_mac_list_s), GFP_ATOMIC); @@ -432,14 +429,9 @@ void qlcnic_set_multi(struct net_device *netdev) struct dev_mc_list *mc_ptr; u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; u32 mode = VPORT_MISS_MODE_DROP; - LIST_HEAD(del_list); - struct list_head *head; - struct qlcnic_mac_list_s *cur; - list_splice_tail_init(&adapter->mac_list, &del_list); - - qlcnic_nic_add_mac(adapter, adapter->mac_addr, &del_list); - qlcnic_nic_add_mac(adapter, bcast_addr, &del_list); + qlcnic_nic_add_mac(adapter, adapter->mac_addr); + qlcnic_nic_add_mac(adapter, bcast_addr); if (netdev->flags & IFF_PROMISC) { mode = VPORT_MISS_MODE_ACCEPT_ALL; @@ -454,22 +446,12 @@ void qlcnic_set_multi(struct net_device *netdev) if (!netdev_mc_empty(netdev)) { netdev_for_each_mc_addr(mc_ptr, netdev) { - qlcnic_nic_add_mac(adapter, mc_ptr->dmi_addr, - &del_list); + qlcnic_nic_add_mac(adapter, mc_ptr->dmi_addr); } } send_fw_cmd: qlcnic_nic_set_promisc(adapter, mode); - head = &del_list; - while (!list_empty(head)) { - cur = list_entry(head->next, struct qlcnic_mac_list_s, list); - - qlcnic_sre_macaddr_change(adapter, - cur->mac_addr, QLCNIC_MAC_DEL); - list_del(&cur->list); - kfree(cur); - } } int qlcnic_nic_set_promisc(struct qlcnic_adapter *adapter, u32 mode) diff --git a/drivers/net/qlcnic/qlcnic_init.c b/drivers/net/qlcnic/qlcnic_init.c index ea00ab4d4feb..7c34e4e29b3f 100644 --- a/drivers/net/qlcnic/qlcnic_init.c +++ b/drivers/net/qlcnic/qlcnic_init.c @@ -568,21 +568,123 @@ struct uni_table_desc *qlcnic_get_table_desc(const u8 *unirom, int section) return NULL; } +#define FILEHEADER_SIZE (14 * 4) + static int -qlcnic_set_product_offs(struct qlcnic_adapter *adapter) +qlcnic_validate_header(struct qlcnic_adapter *adapter) { - struct uni_table_desc *ptab_descr; const u8 *unirom = adapter->fw->data; - u32 i; + struct uni_table_desc *directory = (struct uni_table_desc *) &unirom[0]; + __le32 fw_file_size = adapter->fw->size; __le32 entries; + __le32 entry_size; + __le32 tab_size; + + if (fw_file_size < FILEHEADER_SIZE) + return -EINVAL; + + entries = cpu_to_le32(directory->num_entries); + entry_size = cpu_to_le32(directory->entry_size); + tab_size = cpu_to_le32(directory->findex) + (entries * entry_size); + + if (fw_file_size < tab_size) + return -EINVAL; + + return 0; +} + +static int +qlcnic_validate_bootld(struct qlcnic_adapter *adapter) +{ + struct uni_table_desc *tab_desc; + struct uni_data_desc *descr; + const u8 *unirom = adapter->fw->data; + int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + + QLCNIC_UNI_BOOTLD_IDX_OFF)); + __le32 offs; + __le32 tab_size; + __le32 data_size; + + tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_BOOTLD); + + if (!tab_desc) + return -EINVAL; + + tab_size = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size * (idx + 1))); + + if (adapter->fw->size < tab_size) + return -EINVAL; + + offs = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size) * (idx)); + descr = (struct uni_data_desc *)&unirom[offs]; + + data_size = descr->findex + cpu_to_le32(descr->size); + + if (adapter->fw->size < data_size) + return -EINVAL; + + return 0; +} + +static int +qlcnic_validate_fw(struct qlcnic_adapter *adapter) +{ + struct uni_table_desc *tab_desc; + struct uni_data_desc *descr; + const u8 *unirom = adapter->fw->data; + int idx = cpu_to_le32(*((int *)&unirom[adapter->file_prd_off] + + QLCNIC_UNI_FIRMWARE_IDX_OFF)); + __le32 offs; + __le32 tab_size; + __le32 data_size; + + tab_desc = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_FW); + + if (!tab_desc) + return -EINVAL; + + tab_size = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size * (idx + 1))); + + if (adapter->fw->size < tab_size) + return -EINVAL; + + offs = cpu_to_le32(tab_desc->findex) + + (cpu_to_le32(tab_desc->entry_size) * (idx)); + descr = (struct uni_data_desc *)&unirom[offs]; + data_size = descr->findex + cpu_to_le32(descr->size); + + if (adapter->fw->size < data_size) + return -EINVAL; + + return 0; +} + +static int +qlcnic_validate_product_offs(struct qlcnic_adapter *adapter) +{ + struct uni_table_desc *ptab_descr; + const u8 *unirom = adapter->fw->data; int mn_present = qlcnic_has_mn(adapter); + __le32 entries; + __le32 entry_size; + __le32 tab_size; + u32 i; ptab_descr = qlcnic_get_table_desc(unirom, QLCNIC_UNI_DIR_SECT_PRODUCT_TBL); - if (ptab_descr == NULL) - return -1; + if (!ptab_descr) + return -EINVAL; entries = cpu_to_le32(ptab_descr->num_entries); + entry_size = cpu_to_le32(ptab_descr->entry_size); + tab_size = cpu_to_le32(ptab_descr->findex) + (entries * entry_size); + + if (adapter->fw->size < tab_size) + return -EINVAL; + nomn: for (i = 0; i < entries; i++) { @@ -609,7 +711,37 @@ nomn: mn_present = 0; goto nomn; } - return -1; + return -EINVAL; +} + +static int +qlcnic_validate_unified_romimage(struct qlcnic_adapter *adapter) +{ + if (qlcnic_validate_header(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: header validation failed\n"); + return -EINVAL; + } + + if (qlcnic_validate_product_offs(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: product validation failed\n"); + return -EINVAL; + } + + if (qlcnic_validate_bootld(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: bootld validation failed\n"); + return -EINVAL; + } + + if (qlcnic_validate_fw(adapter)) { + dev_err(&adapter->pdev->dev, + "unified image: firmware validation failed\n"); + return -EINVAL; + } + + return 0; } static @@ -715,7 +847,7 @@ qlcnic_get_bios_version(struct qlcnic_adapter *adapter) bios_ver = cpu_to_le32(*((u32 *) (&fw->data[prd_off]) + QLCNIC_UNI_BIOS_VERSION_OFF)); - return (bios_ver << 24) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24); + return (bios_ver << 16) + ((bios_ver >> 8) & 0xff00) + (bios_ver >> 24); } int @@ -858,7 +990,7 @@ qlcnic_validate_firmware(struct qlcnic_adapter *adapter) u8 fw_type = adapter->fw_type; if (fw_type == QLCNIC_UNIFIED_ROMIMAGE) { - if (qlcnic_set_product_offs(adapter)) + if (qlcnic_validate_unified_romimage(adapter)) return -EINVAL; min_size = QLCNIC_UNI_FW_MIN_SIZE; @@ -1114,8 +1246,10 @@ qlcnic_alloc_rx_skb(struct qlcnic_adapter *adapter, struct pci_dev *pdev = adapter->pdev; buffer->skb = dev_alloc_skb(rds_ring->skb_size); - if (!buffer->skb) + if (!buffer->skb) { + adapter->stats.skb_alloc_failure++; return -ENOMEM; + } skb = buffer->skb; @@ -1289,7 +1423,7 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, netif_receive_skb(skb); adapter->stats.lro_pkts++; - adapter->stats.rxbytes += length; + adapter->stats.lrobytes += length; return buffer; } @@ -1505,6 +1639,8 @@ qlcnic_process_rcv_diag(struct qlcnic_adapter *adapter, adapter->diag_cnt++; dev_kfree_skb_any(skb); + adapter->stats.rx_pkts++; + adapter->stats.rxbytes += length; return buffer; } diff --git a/drivers/net/qlcnic/qlcnic_main.c b/drivers/net/qlcnic/qlcnic_main.c index 665e8e56b6a8..fc721564e69e 100644 --- a/drivers/net/qlcnic/qlcnic_main.c +++ b/drivers/net/qlcnic/qlcnic_main.c @@ -118,6 +118,7 @@ qlcnic_update_cmd_producer(struct qlcnic_adapter *adapter, if (qlcnic_tx_avail(tx_ring) <= TX_STOP_THRESH) { netif_stop_queue(adapter->netdev); smp_mb(); + adapter->stats.xmit_off++; } } @@ -1385,6 +1386,7 @@ qlcnic_tso_check(struct net_device *netdev, int copied, offset, copy_len, hdr_len = 0, tso = 0, vlan_oob = 0; struct cmd_desc_type0 *hwdesc; struct vlan_ethhdr *vh; + struct qlcnic_adapter *adapter = netdev_priv(netdev); if (protocol == cpu_to_be16(ETH_P_8021Q)) { @@ -1494,6 +1496,7 @@ qlcnic_tso_check(struct net_device *netdev, tx_ring->producer = producer; barrier(); + adapter->stats.lso_frames++; } static int @@ -1573,6 +1576,7 @@ qlcnic_xmit_frame(struct sk_buff *skb, struct net_device *netdev) if (unlikely(no_of_desc + 2 > qlcnic_tx_avail(tx_ring))) { netif_stop_queue(netdev); + adapter->stats.xmit_off++; return NETDEV_TX_BUSY; } @@ -1880,6 +1884,7 @@ static int qlcnic_process_cmd_ring(struct qlcnic_adapter *adapter) if (qlcnic_tx_avail(tx_ring) > TX_STOP_THRESH) { netif_wake_queue(netdev); adapter->tx_timeo_cnt = 0; + adapter->stats.xmit_on++; } __netif_tx_unlock(tx_ring->txq); } diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index dfc3573c91bb..9d3ebf3e975e 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c @@ -4270,7 +4270,7 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, tp->cur_tx += frags + 1; - smp_wmb(); + wmb(); RTL_W8(TxPoll, NPQ); /* set polling bit */ @@ -4621,7 +4621,7 @@ static int rtl8169_poll(struct napi_struct *napi, int budget) * until it does. */ tp->intr_mask = 0xffff; - smp_wmb(); + wmb(); RTL_W16(IntrMask, tp->intr_event); } diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c index 43bc66aa8405..df70657260dd 100644 --- a/drivers/net/s2io.c +++ b/drivers/net/s2io.c @@ -923,8 +923,8 @@ static int init_shared_mem(struct s2io_nic *nic) tmp_v_addr = mac_control->stats_mem; mac_control->stats_info = (struct stat_block *)tmp_v_addr; memset(tmp_v_addr, 0, size); - DBG_PRINT(INIT_DBG, "%s: Ring Mem PHY: 0x%llx\n", dev->name, - (unsigned long long)tmp_p_addr); + DBG_PRINT(INIT_DBG, "%s: Ring Mem PHY: 0x%llx\n", + dev_name(&nic->pdev->dev), (unsigned long long)tmp_p_addr); mac_control->stats_info->sw_stat.mem_allocated += mem_allocated; return SUCCESS; } @@ -3480,7 +3480,7 @@ static void s2io_reset(struct s2io_nic *sp) struct swStat *swstats; DBG_PRINT(INIT_DBG, "%s: Resetting XFrame card %s\n", - __func__, sp->dev->name); + __func__, pci_name(sp->pdev)); /* Back up the PCI-X CMD reg, dont want to lose MMRBC, OST settings */ pci_read_config_word(sp->pdev, PCIX_COMMAND_REGISTER, &(pci_cmd)); diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 653bdd76ef46..d8ec4c11fd49 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -4863,6 +4863,7 @@ static int sky2_resume(struct pci_dev *pdev) if (!hw) return 0; + rtnl_lock(); err = pci_set_power_state(pdev, PCI_D0); if (err) goto out; @@ -4884,7 +4885,6 @@ static int sky2_resume(struct pci_dev *pdev) sky2_write32(hw, B0_IMSK, Y2_IS_BASE); napi_enable(&hw->napi); - rtnl_lock(); for (i = 0; i < hw->ports; i++) { err = sky2_reattach(hw->dev[i]); if (err) diff --git a/drivers/net/smc91x.h b/drivers/net/smc91x.h index 54799544bda3..8d2772cc42f2 100644 --- a/drivers/net/smc91x.h +++ b/drivers/net/smc91x.h @@ -330,6 +330,48 @@ static inline void LPD7_SMC_outsw (unsigned char* a, int r, #include <unit/smc91111.h> +#elif defined(CONFIG_ARCH_MSM) + +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 1 + +#define SMC_inw(a, r) readw((a) + (r)) +#define SMC_outw(v, a, r) writew(v, (a) + (r)) +#define SMC_insw(a, r, p, l) readsw((a) + (r), p, l) +#define SMC_outsw(a, r, p, l) writesw((a) + (r), p, l) + +#define SMC_IRQ_FLAGS IRQF_TRIGGER_HIGH + +#elif defined(CONFIG_COLDFIRE) + +#define SMC_CAN_USE_8BIT 0 +#define SMC_CAN_USE_16BIT 1 +#define SMC_CAN_USE_32BIT 0 +#define SMC_NOWAIT 1 + +static inline void mcf_insw(void *a, unsigned char *p, int l) +{ + u16 *wp = (u16 *) p; + while (l-- > 0) + *wp++ = readw(a); +} + +static inline void mcf_outsw(void *a, unsigned char *p, int l) +{ + u16 *wp = (u16 *) p; + while (l-- > 0) + writew(*wp++, a); +} + +#define SMC_inw(a, r) _swapw(readw((a) + (r))) +#define SMC_outw(v, a, r) writew(_swapw(v), (a) + (r)) +#define SMC_insw(a, r, p, l) mcf_insw(a + r, p, l) +#define SMC_outsw(a, r, p, l) mcf_outsw(a + r, p, l) + +#define SMC_IRQ_FLAGS (IRQF_DISABLED) + #else /* diff --git a/drivers/net/tg3.c b/drivers/net/tg3.c index 0fa7688ab483..22cf1c446de3 100644 --- a/drivers/net/tg3.c +++ b/drivers/net/tg3.c @@ -5279,7 +5279,7 @@ static void tg3_poll_controller(struct net_device *dev) struct tg3 *tp = netdev_priv(dev); for (i = 0; i < tp->irq_cnt; i++) - tg3_interrupt(tp->napi[i].irq_vec, dev); + tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]); } #endif @@ -9776,7 +9776,7 @@ static int tg3_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) ADVERTISED_Pause | ADVERTISED_Asym_Pause; - if (!(tp->tg3_flags2 & TG3_FLAG_10_100_ONLY)) + if (!(tp->tg3_flags & TG3_FLAG_10_100_ONLY)) mask |= ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full; diff --git a/drivers/net/tulip/eeprom.c b/drivers/net/tulip/eeprom.c index 93f4e8309f81..49f05d1431f5 100644 --- a/drivers/net/tulip/eeprom.c +++ b/drivers/net/tulip/eeprom.c @@ -143,6 +143,12 @@ static void __devinit tulip_build_fake_mediatable(struct tulip_private *tp) void __devinit tulip_parse_eeprom(struct net_device *dev) { + /* + dev is not registered at this point, so logging messages can't + use dev_<level> or netdev_<level> but dev->name is good via a + hack in the caller + */ + /* The last media info list parsed, for multiport boards. */ static struct mediatable *last_mediatable; static unsigned char *last_ee_data; @@ -161,15 +167,14 @@ void __devinit tulip_parse_eeprom(struct net_device *dev) if (ee_data[0] == 0xff) { if (last_mediatable) { controller_index++; - dev_info(&dev->dev, - "Controller %d of multiport board\n", - controller_index); + pr_info("%s: Controller %d of multiport board\n", + dev->name, controller_index); tp->mtable = last_mediatable; ee_data = last_ee_data; goto subsequent_board; } else - dev_info(&dev->dev, - "Missing EEPROM, this interface may not work correctly!\n"); + pr_info("%s: Missing EEPROM, this interface may not work correctly!\n", + dev->name); return; } /* Do a fix-up based on the vendor half of the station address prefix. */ @@ -181,15 +186,14 @@ void __devinit tulip_parse_eeprom(struct net_device *dev) i++; /* An Accton EN1207, not an outlaw Maxtech. */ memcpy(ee_data + 26, eeprom_fixups[i].newtable, sizeof(eeprom_fixups[i].newtable)); - dev_info(&dev->dev, - "Old format EEPROM on '%s' board. Using substitute media control info\n", - eeprom_fixups[i].name); + pr_info("%s: Old format EEPROM on '%s' board. Using substitute media control info\n", + dev->name, eeprom_fixups[i].name); break; } } if (eeprom_fixups[i].name == NULL) { /* No fixup found. */ - dev_info(&dev->dev, - "Old style EEPROM with no media selection information\n"); + pr_info("%s: Old style EEPROM with no media selection information\n", + dev->name); return; } } @@ -217,8 +221,8 @@ subsequent_board: /* there is no phy information, don't even try to build mtable */ if (count == 0) { if (tulip_debug > 0) - dev_warn(&dev->dev, - "no phy info, aborting mtable build\n"); + pr_warning("%s: no phy info, aborting mtable build\n", + dev->name); return; } @@ -234,8 +238,10 @@ subsequent_board: mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0; mtable->csr15dir = mtable->csr15val = 0; - dev_info(&dev->dev, "EEPROM default media type %s\n", - media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]); + pr_info("%s: EEPROM default media type %s\n", + dev->name, + media & 0x0800 ? "Autosense" + : medianame[media & MEDIA_MASK]); for (i = 0; i < count; i++) { struct medialeaf *leaf = &mtable->mleaf[i]; @@ -298,17 +304,17 @@ subsequent_board: } if (tulip_debug > 1 && leaf->media == 11) { unsigned char *bp = leaf->leafdata; - dev_info(&dev->dev, - "MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n", - bp[0], bp[1], bp[2 + bp[1]*2], - bp[5 + bp[2 + bp[1]*2]*2], - bp[4 + bp[2 + bp[1]*2]*2]); + pr_info("%s: MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %02x %02x\n", + dev->name, + bp[0], bp[1], bp[2 + bp[1]*2], + bp[5 + bp[2 + bp[1]*2]*2], + bp[4 + bp[2 + bp[1]*2]*2]); } - dev_info(&dev->dev, - "Index #%d - Media %s (#%d) described by a %s (%d) block\n", - i, medianame[leaf->media & 15], leaf->media, - leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>", - leaf->type); + pr_info("%s: Index #%d - Media %s (#%d) described by a %s (%d) block\n", + dev->name, + i, medianame[leaf->media & 15], leaf->media, + leaf->type < ARRAY_SIZE(block_name) ? block_name[leaf->type] : "<unknown>", + leaf->type); } if (new_advertise) tp->sym_advertise = new_advertise; diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c index 2fbf15235c05..cd24e5f2b2a2 100644 --- a/drivers/net/typhoon.c +++ b/drivers/net/typhoon.c @@ -480,7 +480,7 @@ typhoon_hello(struct typhoon *tp) typhoon_inc_cmd_index(&ring->lastWrite, 1); INIT_COMMAND_NO_RESPONSE(cmd, TYPHOON_CMD_HELLO_RESP); - smp_wmb(); + wmb(); iowrite32(ring->lastWrite, tp->ioaddr + TYPHOON_REG_CMD_READY); spin_unlock(&tp->command_lock); } @@ -1311,13 +1311,15 @@ typhoon_init_interface(struct typhoon *tp) tp->txlo_dma_addr = le32_to_cpu(iface->txLoAddr); tp->card_state = Sleeping; - smp_wmb(); tp->offload = TYPHOON_OFFLOAD_IP_CHKSUM | TYPHOON_OFFLOAD_TCP_CHKSUM; tp->offload |= TYPHOON_OFFLOAD_UDP_CHKSUM | TSO_OFFLOAD_ON; spin_lock_init(&tp->command_lock); spin_lock_init(&tp->state_lock); + + /* Force the writes to the shared memory area out before continuing. */ + wmb(); } static void diff --git a/drivers/net/usb/asix.c b/drivers/net/usb/asix.c index 20e34608fa4a..9e05639435f2 100644 --- a/drivers/net/usb/asix.c +++ b/drivers/net/usb/asix.c @@ -54,6 +54,7 @@ static const char driver_name [] = "asix"; #define AX_CMD_WRITE_IPG0 0x12 #define AX_CMD_WRITE_IPG1 0x13 #define AX_CMD_READ_NODE_ID 0x13 +#define AX_CMD_WRITE_NODE_ID 0x14 #define AX_CMD_WRITE_IPG2 0x14 #define AX_CMD_WRITE_MULTI_FILTER 0x16 #define AX88172_CMD_READ_NODE_ID 0x17 @@ -165,6 +166,7 @@ static const char driver_name [] = "asix"; /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ struct asix_data { u8 multi_filter[AX_MCAST_FILTER_SIZE]; + u8 mac_addr[ETH_ALEN]; u8 phymode; u8 ledmode; u8 eeprom_len; @@ -732,6 +734,30 @@ static int asix_ioctl (struct net_device *net, struct ifreq *rq, int cmd) return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); } +static int asix_set_mac_address(struct net_device *net, void *p) +{ + struct usbnet *dev = netdev_priv(net); + struct asix_data *data = (struct asix_data *)&dev->data; + struct sockaddr *addr = p; + + if (netif_running(net)) + return -EBUSY; + if (!is_valid_ether_addr(addr->sa_data)) + return -EADDRNOTAVAIL; + + memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); + + /* We use the 20 byte dev->data + * for our 6 byte mac buffer + * to avoid allocating memory that + * is tricky to free later */ + memcpy(data->mac_addr, addr->sa_data, ETH_ALEN); + asix_write_cmd_async(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, + data->mac_addr); + + return 0; +} + /* We need to override some ethtool_ops so we require our own structure so we don't interfere with other usbnet devices that may be connected at the same time. */ @@ -919,7 +945,7 @@ static const struct net_device_ops ax88772_netdev_ops = { .ndo_start_xmit = usbnet_start_xmit, .ndo_tx_timeout = usbnet_tx_timeout, .ndo_change_mtu = usbnet_change_mtu, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = asix_set_mac_address, .ndo_validate_addr = eth_validate_addr, .ndo_do_ioctl = asix_ioctl, .ndo_set_multicast_list = asix_set_multicast, @@ -1213,7 +1239,7 @@ static const struct net_device_ops ax88178_netdev_ops = { .ndo_stop = usbnet_stop, .ndo_start_xmit = usbnet_start_xmit, .ndo_tx_timeout = usbnet_tx_timeout, - .ndo_set_mac_address = eth_mac_addr, + .ndo_set_mac_address = asix_set_mac_address, .ndo_validate_addr = eth_validate_addr, .ndo_set_multicast_list = asix_set_multicast, .ndo_do_ioctl = asix_ioctl, diff --git a/drivers/net/usb/pegasus.h b/drivers/net/usb/pegasus.h index 5d02f0200737..b90d8766ab74 100644 --- a/drivers/net/usb/pegasus.h +++ b/drivers/net/usb/pegasus.h @@ -177,7 +177,7 @@ PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x400c, PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0xabc1, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "USB 10/100 Fast Ethernet", VENDOR_ABOCOM, 0x200c, - DEFAULT_GPIO_RESET | PEGASUS_II ) + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Accton USB 10/100 Ethernet Adapter", VENDOR_ACCTON, 0x1046, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "SpeedStream USB 10/100 Ethernet", VENDOR_ACCTON, 0x5046, @@ -208,6 +208,8 @@ PEGASUS_DEV( "Allied Telesyn Int. AT-USB100", VENDOR_ALLIEDTEL, 0xb100, */ PEGASUS_DEV_CLASS( "Belkin F5D5050 USB Ethernet", VENDOR_BELKIN, 0x0121, 0x00, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "Belkin F5U122 10/100 USB Ethernet", VENDOR_BELKIN, 0x0122, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "Billionton USB-100", VENDOR_BILLIONTON, 0x0986, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Billionton USBLP-100", VENDOR_BILLIONTON, 0x0987, @@ -249,7 +251,7 @@ PEGASUS_DEV( "GIGABYTE GN-BR402W Wireless Router", VENDOR_GIGABYTE, 0x8002, PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "HP hn210c Ethernet USB", VENDOR_HP, 0x811c, - DEFAULT_GPIO_RESET | PEGASUS_II ) + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "IO DATA USB ET/TX", VENDOR_IODATA, 0x0904, DEFAULT_GPIO_RESET ) PEGASUS_DEV( "IO DATA USB ET/TX-S", VENDOR_IODATA, 0x0913, diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c index 698d5672a070..dc5018a6d9ed 100644 --- a/drivers/net/wireless/airo.c +++ b/drivers/net/wireless/airo.c @@ -5255,7 +5255,8 @@ static int set_wep_key(struct airo_info *ai, u16 index, const char *key, WepKeyRid wkr; int rc; - WARN_ON(keylen == 0); + if (WARN_ON(keylen == 0)) + return -1; memset(&wkr, 0, sizeof(wkr)); wkr.len = cpu_to_le16(sizeof(wkr)); diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h index 8c8ce67971e9..dc662b76a1c8 100644 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ b/drivers/net/wireless/ath/ar9170/ar9170.h @@ -166,6 +166,7 @@ struct ar9170 { struct ath_common common; struct mutex mutex; enum ar9170_device_state state; + bool registered; unsigned long bad_hw_nagger; int (*open)(struct ar9170 *); diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c index 08dc42da0f63..257c734733d1 100644 --- a/drivers/net/wireless/ath/ar9170/main.c +++ b/drivers/net/wireless/ath/ar9170/main.c @@ -2701,7 +2701,8 @@ int ar9170_register(struct ar9170 *ar, struct device *pdev) dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", wiphy_name(ar->hw->wiphy)); - return err; + ar->registered = true; + return 0; err_unreg: ieee80211_unregister_hw(ar->hw); @@ -2712,11 +2713,14 @@ err_out: void ar9170_unregister(struct ar9170 *ar) { + if (ar->registered) { #ifdef CONFIG_AR9170_LEDS - ar9170_unregister_leds(ar); + ar9170_unregister_leds(ar); #endif /* CONFIG_AR9170_LEDS */ - kfree_skb(ar->rx_failover); ieee80211_unregister_hw(ar->hw); + } + + kfree_skb(ar->rx_failover); mutex_destroy(&ar->mutex); } diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 0f361186b78f..4e30197afff6 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c @@ -582,43 +582,6 @@ static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, return 0; } -static int ar9170_usb_request_firmware(struct ar9170_usb *aru) -{ - int err = 0; - - err = request_firmware(&aru->firmware, "ar9170.fw", - &aru->udev->dev); - if (!err) { - aru->init_values = NULL; - return 0; - } - - if (aru->req_one_stage_fw) { - dev_err(&aru->udev->dev, "ar9170.fw firmware file " - "not found and is required for this device\n"); - return -EINVAL; - } - - dev_err(&aru->udev->dev, "ar9170.fw firmware file " - "not found, trying old firmware...\n"); - - err = request_firmware(&aru->init_values, "ar9170-1.fw", - &aru->udev->dev); - if (err) { - dev_err(&aru->udev->dev, "file with init values not found.\n"); - return err; - } - - err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev); - if (err) { - release_firmware(aru->init_values); - dev_err(&aru->udev->dev, "firmware file not found.\n"); - return err; - } - - return err; -} - static int ar9170_usb_reset(struct ar9170_usb *aru) { int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); @@ -757,6 +720,103 @@ err_out: return err; } +static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) +{ + struct device *parent = aru->udev->dev.parent; + + /* unbind anything failed */ + if (parent) + down(&parent->sem); + device_release_driver(&aru->udev->dev); + if (parent) + up(&parent->sem); +} + +static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) +{ + struct ar9170_usb *aru = context; + int err; + + aru->firmware = fw; + + if (!fw) { + dev_err(&aru->udev->dev, "firmware file not found.\n"); + goto err_freefw; + } + + err = ar9170_usb_init_device(aru); + if (err) + goto err_freefw; + + err = ar9170_usb_open(&aru->common); + if (err) + goto err_unrx; + + err = ar9170_register(&aru->common, &aru->udev->dev); + + ar9170_usb_stop(&aru->common); + if (err) + goto err_unrx; + + return; + + err_unrx: + ar9170_usb_cancel_urbs(aru); + + err_freefw: + ar9170_usb_firmware_failed(aru); +} + +static void ar9170_usb_firmware_inits(const struct firmware *fw, + void *context) +{ + struct ar9170_usb *aru = context; + int err; + + if (!fw) { + dev_err(&aru->udev->dev, "file with init values not found.\n"); + ar9170_usb_firmware_failed(aru); + return; + } + + aru->init_values = fw; + + /* ok so we have the init values -- get code for two-stage */ + + err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-2.fw", + &aru->udev->dev, GFP_KERNEL, aru, + ar9170_usb_firmware_finish); + if (err) + ar9170_usb_firmware_failed(aru); +} + +static void ar9170_usb_firmware_step2(const struct firmware *fw, void *context) +{ + struct ar9170_usb *aru = context; + int err; + + if (fw) { + ar9170_usb_firmware_finish(fw, context); + return; + } + + if (aru->req_one_stage_fw) { + dev_err(&aru->udev->dev, "ar9170.fw firmware file " + "not found and is required for this device\n"); + ar9170_usb_firmware_failed(aru); + return; + } + + dev_err(&aru->udev->dev, "ar9170.fw firmware file " + "not found, trying old firmware...\n"); + + err = request_firmware_nowait(THIS_MODULE, 1, "ar9170-1.fw", + &aru->udev->dev, GFP_KERNEL, aru, + ar9170_usb_firmware_inits); + if (err) + ar9170_usb_firmware_failed(aru); +} + static bool ar9170_requires_one_stage(const struct usb_device_id *id) { if (!id->driver_info) @@ -814,33 +874,9 @@ static int ar9170_usb_probe(struct usb_interface *intf, if (err) goto err_freehw; - err = ar9170_usb_request_firmware(aru); - if (err) - goto err_freehw; - - err = ar9170_usb_init_device(aru); - if (err) - goto err_freefw; - - err = ar9170_usb_open(ar); - if (err) - goto err_unrx; - - err = ar9170_register(ar, &udev->dev); - - ar9170_usb_stop(ar); - if (err) - goto err_unrx; - - return 0; - -err_unrx: - ar9170_usb_cancel_urbs(aru); - -err_freefw: - release_firmware(aru->init_values); - release_firmware(aru->firmware); - + return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", + &aru->udev->dev, GFP_KERNEL, aru, + ar9170_usb_firmware_step2); err_freehw: usb_set_intfdata(intf, NULL); usb_put_dev(udev); @@ -860,12 +896,12 @@ static void ar9170_usb_disconnect(struct usb_interface *intf) ar9170_unregister(&aru->common); ar9170_usb_cancel_urbs(aru); - release_firmware(aru->init_values); - release_firmware(aru->firmware); - usb_put_dev(aru->udev); usb_set_intfdata(intf, NULL); ieee80211_free_hw(aru->common.hw); + + release_firmware(aru->init_values); + release_firmware(aru->firmware); } #ifdef CONFIG_PM diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c index 6a3f4da7fb48..10b52262b232 100644 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ b/drivers/net/wireless/ath/ath5k/eeprom.c @@ -429,8 +429,8 @@ static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; AR5K_EEPROM_READ(o++, val); - ee->ee_i_cal[mode] = (val >> 8) & 0x3f; - ee->ee_q_cal[mode] = (val >> 3) & 0x1f; + ee->ee_i_cal[mode] = (val >> 5) & 0x3f; + ee->ee_q_cal[mode] = val & 0x1f; if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { AR5K_EEPROM_READ(o++, val); diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c index 72474c0ccaff..eff3323efb4b 100644 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ b/drivers/net/wireless/ath/ath5k/phy.c @@ -1386,38 +1386,39 @@ static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, goto done; /* Calibration has finished, get the results and re-run */ + + /* work around empty results which can apparently happen on 5212 */ for (i = 0; i <= 10; i++) { iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "iq_corr:%x i_pwr:%x q_pwr:%x", iq_corr, i_pwr, q_pwr); + if (i_pwr && q_pwr) + break; } i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; q_coffd = q_pwr >> 7; - /* No correction */ - if (i_coffd == 0 || q_coffd == 0) + /* protect against divide by 0 and loss of sign bits */ + if (i_coffd == 0 || q_coffd < 2) goto done; - i_coff = ((-iq_corr) / i_coffd); - - /* Boundary check */ - if (i_coff > 31) - i_coff = 31; - if (i_coff < -32) - i_coff = -32; + i_coff = (-iq_corr) / i_coffd; + i_coff = clamp(i_coff, -32, 31); /* signed 6 bit */ - q_coff = (((s32)i_pwr / q_coffd) - 128); + q_coff = (i_pwr / q_coffd) - 128; + q_coff = clamp(q_coff, -16, 15); /* signed 5 bit */ - /* Boundary check */ - if (q_coff > 15) - q_coff = 15; - if (q_coff < -16) - q_coff = -16; + ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, + "new I:%d Q:%d (i_coffd:%x q_coffd:%x)", + i_coff, q_coff, i_coffd, q_coffd); - /* Commit new I/Q value */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | - ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); + /* Commit new I/Q values (set enable bit last to match HAL sources) */ + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF, i_coff); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF, q_coff); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE); /* Re-enable calibration -if we don't we'll commit * the same values again and again */ @@ -1873,7 +1874,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) break; case AR5K_ANTMODE_FIXED_A: def_ant = 1; - tx_ant = 0; + tx_ant = 1; use_def_for_tx = true; update_def_on_tx = false; use_def_for_rts = true; @@ -1882,7 +1883,7 @@ ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) break; case AR5K_ANTMODE_FIXED_B: def_ant = 2; - tx_ant = 0; + tx_ant = 2; use_def_for_tx = true; update_def_on_tx = false; use_def_for_rts = true; diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h index 4cb9c5df9f46..1464f89b249c 100644 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ b/drivers/net/wireless/ath/ath5k/reg.h @@ -2187,6 +2187,7 @@ */ #define AR5K_PHY_IQ 0x9920 /* Register Address */ #define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */ +#define AR5K_PHY_IQ_CORR_Q_Q_COFF_S 0 #define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */ #define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5 #define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */ diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c index a35a7db0fc4c..cbf28e379843 100644 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ b/drivers/net/wireless/ath/ath5k/reset.c @@ -851,12 +851,15 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, AR5K_INIT_CYCRSSI_THR1); - /* I/Q correction - * TODO: Per channel i/q infos ? */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CORR_ENABLE | - (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) | - ee->ee_q_cal[ee_mode]); + /* I/Q correction (set enable bit last to match HAL sources) */ + /* TODO: Per channel i/q infos ? */ + if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_I_COFF, + ee->ee_i_cal[ee_mode]); + AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_Q_Q_COFF, + ee->ee_q_cal[ee_mode]); + AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE); + } /* Heavy clipping -disable for now */ if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) @@ -1379,11 +1382,10 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, ath5k_hw_set_sleep_clock(ah, true); /* - * Disable beacons and reset the register + * Disable beacons and reset the TSF */ - AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE | - AR5K_BEACON_RESET_TSF); - + AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); + ath5k_hw_reset_tsf(ah); return 0; } diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index ac34a055c713..0e79e58cf4c9 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1323,7 +1323,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, struct ieee80211_sta *sta, void *priv_sta, - u32 changed) + u32 changed, enum nl80211_channel_type oper_chan_type) { struct ath_softc *sc = priv; struct ath_rate_priv *ath_rc_priv = priv_sta; @@ -1340,8 +1340,8 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) return; - if (sc->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || - sc->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) + if (oper_chan_type == NL80211_CHAN_HT40MINUS || + oper_chan_type == NL80211_CHAN_HT40PLUS) oper_cw40 = true; oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 47294f90bbe5..b2c8207f7bc1 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -2258,7 +2258,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) if (ATH_TXQ_SETUP(sc, i)) { txq = &sc->tx.txq[i]; - spin_lock(&txq->axq_lock); + spin_lock_bh(&txq->axq_lock); list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { @@ -2279,7 +2279,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) } } - spin_unlock(&txq->axq_lock); + spin_unlock_bh(&txq->axq_lock); } } } diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 63c2a7ade5fb..5c7aa1b1eb56 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c @@ -3177,14 +3177,27 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) int total_nr = 0; int i; struct pci_pool *pool; - u32 *virts[CB_NUMBER_OF_ELEMENTS_SMALL]; - dma_addr_t phys[CB_NUMBER_OF_ELEMENTS_SMALL]; + void **virts; + dma_addr_t *phys; IPW_DEBUG_TRACE("<< : \n"); + virts = kmalloc(sizeof(void *) * CB_NUMBER_OF_ELEMENTS_SMALL, + GFP_KERNEL); + if (!virts) + return -ENOMEM; + + phys = kmalloc(sizeof(dma_addr_t) * CB_NUMBER_OF_ELEMENTS_SMALL, + GFP_KERNEL); + if (!phys) { + kfree(virts); + return -ENOMEM; + } pool = pci_pool_create("ipw2200", priv->pci_dev, CB_MAX_LENGTH, 0, 0); if (!pool) { IPW_ERROR("pci_pool_create failed\n"); + kfree(phys); + kfree(virts); return -ENOMEM; } @@ -3254,6 +3267,8 @@ static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) pci_pool_free(pool, virts[i], phys[i]); pci_pool_destroy(pool); + kfree(phys); + kfree(virts); return ret; } diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index bf45391172f3..a6d5e42647e4 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h @@ -797,7 +797,7 @@ struct libipw_device { /* Probe / Beacon management */ struct list_head network_free_list; struct list_head network_list; - struct libipw_network *networks; + struct libipw_network *networks[MAX_NETWORK_COUNT]; int scans; int scan_age; diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index 1ae0b2b02c38..2fa55867bd8b 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c @@ -67,16 +67,17 @@ void *libipw_wiphy_privid = &libipw_wiphy_privid; static int libipw_networks_allocate(struct libipw_device *ieee) { - if (ieee->networks) - return 0; - - ieee->networks = - kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_network), - GFP_KERNEL); - if (!ieee->networks) { - printk(KERN_WARNING "%s: Out of memory allocating beacons\n", - ieee->dev->name); - return -ENOMEM; + int i, j; + + for (i = 0; i < MAX_NETWORK_COUNT; i++) { + ieee->networks[i] = kzalloc(sizeof(struct libipw_network), + GFP_KERNEL); + if (!ieee->networks[i]) { + LIBIPW_ERROR("Out of memory allocating beacons\n"); + for (j = 0; j < i; j++) + kfree(ieee->networks[j]); + return -ENOMEM; + } } return 0; @@ -97,15 +98,11 @@ static inline void libipw_networks_free(struct libipw_device *ieee) { int i; - if (!ieee->networks) - return; - - for (i = 0; i < MAX_NETWORK_COUNT; i++) - if (ieee->networks[i].ibss_dfs) - kfree(ieee->networks[i].ibss_dfs); - - kfree(ieee->networks); - ieee->networks = NULL; + for (i = 0; i < MAX_NETWORK_COUNT; i++) { + if (ieee->networks[i]->ibss_dfs) + kfree(ieee->networks[i]->ibss_dfs); + kfree(ieee->networks[i]); + } } void libipw_networks_age(struct libipw_device *ieee, @@ -130,7 +127,7 @@ static void libipw_networks_initialize(struct libipw_device *ieee) INIT_LIST_HEAD(&ieee->network_free_list); INIT_LIST_HEAD(&ieee->network_list); for (i = 0; i < MAX_NETWORK_COUNT; i++) - list_add_tail(&ieee->networks[i].list, + list_add_tail(&ieee->networks[i]->list, &ieee->network_free_list); } diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 303cc8193adc..e0678d921055 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c @@ -184,7 +184,7 @@ static int iwl3945_hwrate_to_plcp_idx(u8 plcp) { int idx; - for (idx = 0; idx < IWL_RATE_COUNT; idx++) + for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++) if (iwl3945_rates[idx].plcp == plcp) return idx; return -1; @@ -805,7 +805,7 @@ void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, int sta_id, int tx_id) { u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value; - u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1); + u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945); u16 rate_mask; int rate; u8 rts_retry_limit; @@ -2146,7 +2146,7 @@ static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) /* fill in channel group's nominal powers for each rate */ for (rate_index = 0; - rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) { + rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) { switch (rate_index) { case IWL_RATE_36M_INDEX_TABLE: if (i == 0) /* B/G */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 6aeb82b6992f..818367b57bab 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c @@ -1463,59 +1463,66 @@ static void iwl_nic_start(struct iwl_priv *priv) } +static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context); +static int iwl_mac_setup_register(struct iwl_priv *priv); + +static int __must_check iwl_request_firmware(struct iwl_priv *priv, bool first) +{ + const char *name_pre = priv->cfg->fw_name_pre; + + if (first) + priv->fw_index = priv->cfg->ucode_api_max; + else + priv->fw_index--; + + if (priv->fw_index < priv->cfg->ucode_api_min) { + IWL_ERR(priv, "no suitable firmware found!\n"); + return -ENOENT; + } + + sprintf(priv->firmware_name, "%s%d%s", + name_pre, priv->fw_index, ".ucode"); + + IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n", + priv->firmware_name); + + return request_firmware_nowait(THIS_MODULE, 1, priv->firmware_name, + &priv->pci_dev->dev, GFP_KERNEL, priv, + iwl_ucode_callback); +} + /** - * iwl_read_ucode - Read uCode images from disk file. + * iwl_ucode_callback - callback when firmware was loaded * - * Copy into buffers for card to fetch via bus-mastering + * If loaded successfully, copies the firmware into buffers + * for the card to fetch (via DMA). */ -static int iwl_read_ucode(struct iwl_priv *priv) +static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context) { + struct iwl_priv *priv = context; struct iwl_ucode_header *ucode; - int ret = -EINVAL, index; - const struct firmware *ucode_raw; - const char *name_pre = priv->cfg->fw_name_pre; const unsigned int api_max = priv->cfg->ucode_api_max; const unsigned int api_min = priv->cfg->ucode_api_min; - char buf[25]; u8 *src; size_t len; u32 api_ver, build; u32 inst_size, data_size, init_size, init_data_size, boot_size; + int err; u16 eeprom_ver; - /* Ask kernel firmware_class module to get the boot firmware off disk. - * request_firmware() is synchronous, file is in memory on return. */ - for (index = api_max; index >= api_min; index--) { - sprintf(buf, "%s%d%s", name_pre, index, ".ucode"); - ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev); - if (ret < 0) { - IWL_ERR(priv, "%s firmware file req failed: %d\n", - buf, ret); - if (ret == -ENOENT) - continue; - else - goto error; - } else { - if (index < api_max) - IWL_ERR(priv, "Loaded firmware %s, " - "which is deprecated. " - "Please use API v%u instead.\n", - buf, api_max); - - IWL_DEBUG_INFO(priv, "Got firmware '%s' file (%zd bytes) from disk\n", - buf, ucode_raw->size); - break; - } + if (!ucode_raw) { + IWL_ERR(priv, "request for firmware file '%s' failed.\n", + priv->firmware_name); + goto try_again; } - if (ret < 0) - goto error; + IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n", + priv->firmware_name, ucode_raw->size); /* Make sure that we got at least the v1 header! */ if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { IWL_ERR(priv, "File size way too small!\n"); - ret = -EINVAL; - goto err_release; + goto try_again; } /* Data from ucode file: header followed by uCode images */ @@ -1540,10 +1547,9 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_ERR(priv, "Driver unable to support your firmware API. " "Driver supports v%u, firmware is v%u.\n", api_max, api_ver); - priv->ucode_ver = 0; - ret = -EINVAL; - goto err_release; + goto try_again; } + if (api_ver != api_max) IWL_ERR(priv, "Firmware has old API version. Expected v%u, " "got v%u. New firmware can be obtained " @@ -1585,6 +1591,12 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", boot_size); + /* + * For any of the failures below (before allocating pci memory) + * we will try to load a version with a smaller API -- maybe the + * user just got a corrupted version of the latest API. + */ + /* Verify size of file vs. image size info in file's header */ if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) + @@ -1594,41 +1606,35 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "uCode file size %d does not match expected size\n", (int)ucode_raw->size); - ret = -EINVAL; - goto err_release; + goto try_again; } /* Verify that uCode images will fit in card's SRAM */ if (inst_size > priv->hw_params.max_inst_size) { IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", inst_size); - ret = -EINVAL; - goto err_release; + goto try_again; } if (data_size > priv->hw_params.max_data_size) { IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", data_size); - ret = -EINVAL; - goto err_release; + goto try_again; } if (init_size > priv->hw_params.max_inst_size) { IWL_INFO(priv, "uCode init instr len %d too large to fit in\n", init_size); - ret = -EINVAL; - goto err_release; + goto try_again; } if (init_data_size > priv->hw_params.max_data_size) { IWL_INFO(priv, "uCode init data len %d too large to fit in\n", init_data_size); - ret = -EINVAL; - goto err_release; + goto try_again; } if (boot_size > priv->hw_params.max_bsm_size) { IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n", boot_size); - ret = -EINVAL; - goto err_release; + goto try_again; } /* Allocate ucode buffers for card's bus-master loading ... */ @@ -1712,20 +1718,36 @@ static int iwl_read_ucode(struct iwl_priv *priv) IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); memcpy(priv->ucode_boot.v_addr, src, len); + /************************************************** + * This is still part of probe() in a sense... + * + * 9. Setup and register with mac80211 and debugfs + **************************************************/ + err = iwl_mac_setup_register(priv); + if (err) + goto out_unbind; + + err = iwl_dbgfs_register(priv, DRV_NAME); + if (err) + IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); + /* We have our copies now, allow OS release its copies */ release_firmware(ucode_raw); - return 0; + return; + + try_again: + /* try next, if any */ + if (iwl_request_firmware(priv, false)) + goto out_unbind; + release_firmware(ucode_raw); + return; err_pci_alloc: IWL_ERR(priv, "failed to allocate pci memory\n"); - ret = -ENOMEM; iwl_dealloc_ucode_pci(priv); - - err_release: + out_unbind: + device_release_driver(&priv->pci_dev->dev); release_firmware(ucode_raw); - - error: - return ret; } static const char *desc_lookup_text[] = { @@ -2631,7 +2653,7 @@ static int iwl_mac_setup_register(struct iwl_priv *priv) */ hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX + 1; + hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; /* we create the 802.11 header and a zero-length SSID element */ hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; @@ -2667,21 +2689,7 @@ static int iwl_mac_start(struct ieee80211_hw *hw) /* we should be verifying the device is ready to be opened */ mutex_lock(&priv->mutex); - - /* fetch ucode file from disk, alloc and copy to bus-master buffers ... - * ucode filename and max sizes are card-specific. */ - - if (!priv->ucode_code.len) { - ret = iwl_read_ucode(priv); - if (ret) { - IWL_ERR(priv, "Could not read microcode: %d\n", ret); - mutex_unlock(&priv->mutex); - return ret; - } - } - ret = __iwl_up(priv); - mutex_unlock(&priv->mutex); if (ret) @@ -3654,17 +3662,10 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) iwl_power_initialize(priv); iwl_tt_initialize(priv); - /************************************************** - * 9. Setup and register with mac80211 and debugfs - **************************************************/ - err = iwl_mac_setup_register(priv); + err = iwl_request_firmware(priv, true); if (err) goto out_remove_sysfs; - err = iwl_dbgfs_register(priv, DRV_NAME); - if (err) - IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); - return 0; out_remove_sysfs: diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index ab891b958042..6054c5fba0c1 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h @@ -1132,6 +1132,7 @@ struct iwl_priv { u8 rev_id; /* uCode images, save to reload in case of failure */ + int fw_index; /* firmware we're trying to load */ u32 ucode_ver; /* version of ucode, copy of iwl_ucode.ver */ struct fw_desc ucode_code; /* runtime inst */ @@ -1142,6 +1143,7 @@ struct iwl_priv { struct fw_desc ucode_boot; /* bootstrap inst */ enum ucode_type ucode_type; u8 ucode_write_complete; /* the image write is complete */ + char firmware_name[25]; struct iwl_rxon_time_cmd rxon_timing; diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index dd9ff2ed645a..bd2f7c420563 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c @@ -638,20 +638,9 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, if (left < 0) return 0; *pos++ = WLAN_EID_SSID; - if (!priv->is_internal_short_scan && - priv->scan_request->n_ssids) { - struct cfg80211_ssid *ssid = - priv->scan_request->ssids; - - /* Broadcast if ssid_len is 0 */ - *pos++ = ssid->ssid_len; - memcpy(pos, ssid->ssid, ssid->ssid_len); - pos += ssid->ssid_len; - len += 2 + ssid->ssid_len; - } else { - *pos++ = 0; - len += 2; - } + *pos++ = 0; + + len += 2; if (WARN_ON(left < ie_len)) return len; @@ -780,26 +769,20 @@ static void iwl_bg_request_scan(struct work_struct *data) if (priv->is_internal_short_scan) { IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); } else if (priv->scan_request->n_ssids) { + int i, p = 0; IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); - /* - * The first SSID to scan is stuffed into the probe request - * template and the remaining ones are handled through the - * direct_scan array. - */ - if (priv->scan_request->n_ssids > 1) { - int i, p = 0; - for (i = 1; i < priv->scan_request->n_ssids; i++) { - if (!priv->scan_request->ssids[i].ssid_len) - continue; - scan->direct_scan[p].id = WLAN_EID_SSID; - scan->direct_scan[p].len = - priv->scan_request->ssids[i].ssid_len; - memcpy(scan->direct_scan[p].ssid, - priv->scan_request->ssids[i].ssid, - priv->scan_request->ssids[i].ssid_len); - n_probes++; - p++; - } + for (i = 0; i < priv->scan_request->n_ssids; i++) { + /* always does wildcard anyway */ + if (!priv->scan_request->ssids[i].ssid_len) + continue; + scan->direct_scan[p].id = WLAN_EID_SSID; + scan->direct_scan[p].len = + priv->scan_request->ssids[i].ssid_len; + memcpy(scan->direct_scan[p].ssid, + priv->scan_request->ssids[i].ssid, + priv->scan_request->ssids[i].ssid_len); + n_probes++; + p++; } is_active = true; } else diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c index 9f6d6bf06b8e..2887047069f2 100644 --- a/drivers/net/wireless/rndis_wlan.c +++ b/drivers/net/wireless/rndis_wlan.c @@ -1496,51 +1496,67 @@ static void set_multicast_list(struct usbnet *usbdev) { struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); struct dev_mc_list *mclist; - __le32 filter; - int ret, i, size; - char *buf; + __le32 filter, basefilter; + int ret; + char *mc_addrs = NULL; + int mc_count; - filter = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; + basefilter = filter = RNDIS_PACKET_TYPE_DIRECTED | + RNDIS_PACKET_TYPE_BROADCAST; - netif_addr_lock_bh(usbdev->net); if (usbdev->net->flags & IFF_PROMISC) { filter |= RNDIS_PACKET_TYPE_PROMISCUOUS | RNDIS_PACKET_TYPE_ALL_LOCAL; - } else if (usbdev->net->flags & IFF_ALLMULTI || - netdev_mc_count(usbdev->net) > priv->multicast_size) { + } else if (usbdev->net->flags & IFF_ALLMULTI) { + filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; + } + + if (filter != basefilter) + goto set_filter; + + /* + * mc_list should be accessed holding the lock, so copy addresses to + * local buffer first. + */ + netif_addr_lock_bh(usbdev->net); + mc_count = netdev_mc_count(usbdev->net); + if (mc_count > priv->multicast_size) { filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; - } else if (!netdev_mc_empty(usbdev->net)) { - size = min(priv->multicast_size, netdev_mc_count(usbdev->net)); - buf = kmalloc(size * ETH_ALEN, GFP_KERNEL); - if (!buf) { + } else if (mc_count) { + int i = 0; + + mc_addrs = kmalloc(mc_count * ETH_ALEN, GFP_ATOMIC); + if (!mc_addrs) { netdev_warn(usbdev->net, "couldn't alloc %d bytes of memory\n", - size * ETH_ALEN); + mc_count * ETH_ALEN); netif_addr_unlock_bh(usbdev->net); return; } - i = 0; - netdev_for_each_mc_addr(mclist, usbdev->net) { - if (i == size) - break; - memcpy(buf + i++ * ETH_ALEN, mclist->dmi_addr, ETH_ALEN); - } + netdev_for_each_mc_addr(mclist, usbdev->net) + memcpy(mc_addrs + i++ * ETH_ALEN, + mclist->dmi_addr, ETH_ALEN); + } + netif_addr_unlock_bh(usbdev->net); - ret = rndis_set_oid(usbdev, OID_802_3_MULTICAST_LIST, buf, - i * ETH_ALEN); - if (ret == 0 && i > 0) + if (filter != basefilter) + goto set_filter; + + if (mc_count) { + ret = rndis_set_oid(usbdev, OID_802_3_MULTICAST_LIST, mc_addrs, + mc_count * ETH_ALEN); + kfree(mc_addrs); + if (ret == 0) filter |= RNDIS_PACKET_TYPE_MULTICAST; else filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; netdev_dbg(usbdev->net, "OID_802_3_MULTICAST_LIST(%d, max: %d) -> %d\n", - i, priv->multicast_size, ret); - - kfree(buf); + mc_count, priv->multicast_size, ret); } - netif_addr_unlock_bh(usbdev->net); +set_filter: ret = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter, sizeof(filter)); if (ret < 0) { diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index aca8c124f434..91cce2d0f6db 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c @@ -1225,7 +1225,7 @@ MODULE_LICENSE("GPL"); #ifdef CONFIG_RT2800PCI_SOC static int rt2800soc_probe(struct platform_device *pdev) { - return rt2x00soc_probe(pdev, rt2800pci_ops); + return rt2x00soc_probe(pdev, &rt2800pci_ops); } static struct platform_driver rt2800soc_driver = { diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.c b/drivers/net/wireless/rt2x00/rt2x00soc.c index 4efdc96010f6..111c0ff5c6c7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.c +++ b/drivers/net/wireless/rt2x00/rt2x00soc.c @@ -112,6 +112,7 @@ exit_free_device: return retval; } +EXPORT_SYMBOL_GPL(rt2x00soc_probe); int rt2x00soc_remove(struct platform_device *pdev) { diff --git a/drivers/net/wireless/rt2x00/rt2x00soc.h b/drivers/net/wireless/rt2x00/rt2x00soc.h index 4739edfe2f00..474cbfc1efc7 100644 --- a/drivers/net/wireless/rt2x00/rt2x00soc.h +++ b/drivers/net/wireless/rt2x00/rt2x00soc.h @@ -26,8 +26,6 @@ #ifndef RT2X00SOC_H #define RT2X00SOC_H -#define KSEG1ADDR(__ptr) __ptr - /* * SoC driver handlers. */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index e77aec8d0a84..290d70bc5d22 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2352,6 +2352,8 @@ static struct usb_device_id rt73usb_device_table[] = { { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, + /* CEIVA */ + { USB_DEVICE(0x178d, 0x02be), USB_DEVICE_DATA(&rt73usb_ops) }, /* CNet */ { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c index a22a19203120..00e09e26c826 100644 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ b/drivers/net/wireless/zd1211rw/zd_mac.c @@ -350,7 +350,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, first_idx = info->status.rates[0].idx; ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates)); retries = &zd_retry_rates[first_idx]; - ZD_ASSERT(0<=retry && retry<=retries->count); + ZD_ASSERT(1 <= retry && retry <= retries->count); info->status.rates[0].idx = retries->rate[0]; info->status.rates[0].count = 1; // (retry > 1 ? 2 : 1); @@ -360,7 +360,7 @@ static void zd_mac_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, info->status.rates[i].count = 1; // ((i==retry-1) && success ? 1:2); } for (; i<IEEE80211_TX_MAX_RATES && i<retry; i++) { - info->status.rates[i].idx = retries->rate[retry-1]; + info->status.rates[i].idx = retries->rate[retry - 1]; info->status.rates[i].count = 1; // (success ? 1:2); } if (i<IEEE80211_TX_MAX_RATES) @@ -424,12 +424,10 @@ void zd_mac_tx_failed(struct urb *urb) first_idx = info->status.rates[0].idx; ZD_ASSERT(0<=first_idx && first_idx<ARRAY_SIZE(zd_retry_rates)); retries = &zd_retry_rates[first_idx]; - if (retry < 0 || retry > retries->count) { + if (retry <= 0 || retry > retries->count) continue; - } - ZD_ASSERT(0<=retry && retry<=retries->count); - final_idx = retries->rate[retry-1]; + final_idx = retries->rate[retry - 1]; final_rate = zd_rates[final_idx].hw_value; if (final_rate != tx_status->rate) { diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c index 1b1dddbd5744..bed764e3ea2a 100644 --- a/drivers/platform/x86/dell-wmi.c +++ b/drivers/platform/x86/dell-wmi.c @@ -142,7 +142,7 @@ static struct key_entry *dell_wmi_keymap = dell_legacy_wmi_keymap; static struct input_dev *dell_wmi_input_dev; -static struct key_entry *dell_wmi_get_entry_by_scancode(int code) +static struct key_entry *dell_wmi_get_entry_by_scancode(unsigned int code) { struct key_entry *key; @@ -153,7 +153,7 @@ static struct key_entry *dell_wmi_get_entry_by_scancode(int code) return NULL; } -static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode) +static struct key_entry *dell_wmi_get_entry_by_keycode(unsigned int keycode) { struct key_entry *key; @@ -164,8 +164,8 @@ static struct key_entry *dell_wmi_get_entry_by_keycode(int keycode) return NULL; } -static int dell_wmi_getkeycode(struct input_dev *dev, int scancode, - int *keycode) +static int dell_wmi_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct key_entry *key = dell_wmi_get_entry_by_scancode(scancode); @@ -177,13 +177,11 @@ static int dell_wmi_getkeycode(struct input_dev *dev, int scancode, return -EINVAL; } -static int dell_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int dell_wmi_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; + unsigned int old_keycode; key = dell_wmi_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 7ccf33c08967..56086363becc 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -278,7 +278,7 @@ static DEVICE_ATTR(als, S_IRUGO | S_IWUSR, show_als, set_als); static DEVICE_ATTR(dock, S_IRUGO, show_dock, NULL); static DEVICE_ATTR(tablet, S_IRUGO, show_tablet, NULL); -static struct key_entry *hp_wmi_get_entry_by_scancode(int code) +static struct key_entry *hp_wmi_get_entry_by_scancode(unsigned int code) { struct key_entry *key; @@ -289,7 +289,7 @@ static struct key_entry *hp_wmi_get_entry_by_scancode(int code) return NULL; } -static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode) +static struct key_entry *hp_wmi_get_entry_by_keycode(unsigned int keycode) { struct key_entry *key; @@ -300,7 +300,8 @@ static struct key_entry *hp_wmi_get_entry_by_keycode(int keycode) return NULL; } -static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode) +static int hp_wmi_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct key_entry *key = hp_wmi_get_entry_by_scancode(scancode); @@ -312,13 +313,11 @@ static int hp_wmi_getkeycode(struct input_dev *dev, int scancode, int *keycode) return -EINVAL; } -static int hp_wmi_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int hp_wmi_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; + unsigned int old_keycode; key = hp_wmi_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { diff --git a/drivers/platform/x86/panasonic-laptop.c b/drivers/platform/x86/panasonic-laptop.c index fe7cf0188acc..c9fc479fc290 100644 --- a/drivers/platform/x86/panasonic-laptop.c +++ b/drivers/platform/x86/panasonic-laptop.c @@ -200,7 +200,7 @@ static struct acpi_driver acpi_pcc_driver = { }; #define KEYMAP_SIZE 11 -static const int initial_keymap[KEYMAP_SIZE] = { +static const unsigned int initial_keymap[KEYMAP_SIZE] = { /* 0 */ KEY_RESERVED, /* 1 */ KEY_BRIGHTNESSDOWN, /* 2 */ KEY_BRIGHTNESSUP, @@ -222,7 +222,7 @@ struct pcc_acpi { struct acpi_device *device; struct input_dev *input_dev; struct backlight_device *backlight; - int keymap[KEYMAP_SIZE]; + unsigned int keymap[KEYMAP_SIZE]; }; struct pcc_keyinput { @@ -445,7 +445,8 @@ static struct attribute_group pcc_attr_group = { /* hotkey input device driver */ -static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode) +static int pcc_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct pcc_acpi *pcc = input_get_drvdata(dev); @@ -457,7 +458,7 @@ static int pcc_getkeycode(struct input_dev *dev, int scancode, int *keycode) return 0; } -static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode) +static int keymap_get_by_keycode(struct pcc_acpi *pcc, unsigned int keycode) { int i; @@ -469,7 +470,8 @@ static int keymap_get_by_keycode(struct pcc_acpi *pcc, int keycode) return 0; } -static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int pcc_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct pcc_acpi *pcc = input_get_drvdata(dev); int oldkeycode; @@ -477,9 +479,6 @@ static int pcc_setkeycode(struct input_dev *dev, int scancode, int keycode) if (scancode >= ARRAY_SIZE(pcc->keymap)) return -EINVAL; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - oldkeycode = pcc->keymap[scancode]; pcc->keymap[scancode] = keycode; diff --git a/drivers/platform/x86/topstar-laptop.c b/drivers/platform/x86/topstar-laptop.c index 02f3d4e9e666..4d6516fded7e 100644 --- a/drivers/platform/x86/topstar-laptop.c +++ b/drivers/platform/x86/topstar-laptop.c @@ -46,7 +46,7 @@ static struct tps_key_entry topstar_keymap[] = { { } }; -static struct tps_key_entry *tps_get_key_by_scancode(int code) +static struct tps_key_entry *tps_get_key_by_scancode(unsigned int code) { struct tps_key_entry *key; @@ -57,7 +57,7 @@ static struct tps_key_entry *tps_get_key_by_scancode(int code) return NULL; } -static struct tps_key_entry *tps_get_key_by_keycode(int code) +static struct tps_key_entry *tps_get_key_by_keycode(unsigned int code) { struct tps_key_entry *key; @@ -126,7 +126,8 @@ static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) return 0; } -static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode) +static int topstar_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct tps_key_entry *key = tps_get_key_by_scancode(scancode); @@ -137,14 +138,12 @@ static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode) return 0; } -static int topstar_setkeycode(struct input_dev *dev, int scancode, int keycode) +static int topstar_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct tps_key_entry *key; int old_keycode; - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - key = tps_get_key_by_scancode(scancode); if (!key) diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c index 405b969734d6..789240d1b577 100644 --- a/drivers/platform/x86/toshiba_acpi.c +++ b/drivers/platform/x86/toshiba_acpi.c @@ -745,7 +745,7 @@ static struct backlight_ops toshiba_backlight_data = { .update_status = set_lcd_status, }; -static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code) +static struct key_entry *toshiba_acpi_get_entry_by_scancode(unsigned int code) { struct key_entry *key; @@ -756,7 +756,7 @@ static struct key_entry *toshiba_acpi_get_entry_by_scancode(int code) return NULL; } -static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code) +static struct key_entry *toshiba_acpi_get_entry_by_keycode(unsigned int code) { struct key_entry *key; @@ -767,8 +767,8 @@ static struct key_entry *toshiba_acpi_get_entry_by_keycode(int code) return NULL; } -static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode, - int *keycode) +static int toshiba_acpi_getkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int *keycode) { struct key_entry *key = toshiba_acpi_get_entry_by_scancode(scancode); @@ -780,14 +780,11 @@ static int toshiba_acpi_getkeycode(struct input_dev *dev, int scancode, return -EINVAL; } -static int toshiba_acpi_setkeycode(struct input_dev *dev, int scancode, - int keycode) +static int toshiba_acpi_setkeycode(struct input_dev *dev, + unsigned int scancode, unsigned int keycode) { struct key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; + unsigned int old_keycode; key = toshiba_acpi_get_entry_by_scancode(scancode); if (key && key->type == KE_KEY) { diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index a3ac4456e0b1..fcd005aad989 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h @@ -763,7 +763,8 @@ static inline int qeth_get_micros(void) static inline int qeth_get_ip_version(struct sk_buff *skb) { - switch (skb->protocol) { + struct ethhdr *ehdr = (struct ethhdr *)skb->data; + switch (ehdr->h_proto) { case ETH_P_IPV6: return 6; case ETH_P_IP: diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 7d25bdd443cd..3bd4206f3470 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c @@ -537,7 +537,8 @@ static void qeth_send_control_data_cb(struct qeth_channel *channel, dev_err(&card->gdev->dev, "The qeth device is not configured " "for the OSI layer required by z/VM\n"); - qeth_schedule_recovery(card); + else + qeth_schedule_recovery(card); goto out; } @@ -1113,8 +1114,6 @@ static int qeth_setup_card(struct qeth_card *card) card->ipato.enabled = 0; card->ipato.invert4 = 0; card->ipato.invert6 = 0; - if (card->info.type == QETH_CARD_TYPE_IQD) - card->options.checksum_type = NO_CHECKSUMMING; /* init QDIO stuff */ qeth_init_qdio_info(card); return 0; diff --git a/drivers/s390/net/qeth_core_sys.c b/drivers/s390/net/qeth_core_sys.c index 88ae4357136a..25dfd5abd19b 100644 --- a/drivers/s390/net/qeth_core_sys.c +++ b/drivers/s390/net/qeth_core_sys.c @@ -8,6 +8,9 @@ * Frank Blaschka <frank.blaschka@de.ibm.com> */ +#define KMSG_COMPONENT "qeth" +#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt + #include <linux/list.h> #include <linux/rwsem.h> #include <asm/ebcdic.h> diff --git a/drivers/s390/net/qeth_l2_main.c b/drivers/s390/net/qeth_l2_main.c index 51fde6f2e0b8..6f1e3036bafd 100644 --- a/drivers/s390/net/qeth_l2_main.c +++ b/drivers/s390/net/qeth_l2_main.c @@ -1071,11 +1071,9 @@ static int qeth_l2_recover(void *ptr) dev_info(&card->gdev->dev, "Device successfully recovered!\n"); else { - if (card->dev) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); dev_warn(&card->gdev->dev, "The qeth device driver " "failed to recover an error on the device\n"); } @@ -1129,11 +1127,9 @@ static int qeth_l2_pm_resume(struct ccwgroup_device *gdev) if (card->state == CARD_STATE_RECOVER) { rc = __qeth_l2_set_online(card->gdev, 1); if (rc) { - if (card->dev) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); } } else rc = __qeth_l2_set_online(card->gdev, 0); diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 5475834ab916..b3b6e872d806 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c @@ -1691,39 +1691,43 @@ qeth_diags_trace_cb(struct qeth_card *card, struct qeth_reply *reply, cmd = (struct qeth_ipa_cmd *)data; rc = cmd->hdr.return_code; - if (rc) { + if (rc) QETH_DBF_TEXT_(TRACE, 2, "dxter%x", rc); - if (cmd->data.diagass.action == QETH_DIAGS_CMD_TRACE_ENABLE) { - switch (rc) { - case IPA_RC_HARDWARE_AUTH_ERROR: - dev_warn(&card->gdev->dev, "The device is not " - "authorized to run as a HiperSockets " - "network traffic analyzer\n"); - break; - case IPA_RC_TRACE_ALREADY_ACTIVE: - dev_warn(&card->gdev->dev, "A HiperSockets " - "network traffic analyzer is already " - "active in the HiperSockets LAN\n"); - break; - default: - break; - } - } - return 0; - } - switch (cmd->data.diagass.action) { case QETH_DIAGS_CMD_TRACE_QUERY: break; case QETH_DIAGS_CMD_TRACE_DISABLE: - card->info.promisc_mode = SET_PROMISC_MODE_OFF; - dev_info(&card->gdev->dev, "The HiperSockets network traffic " - "analyzer is deactivated\n"); + switch (rc) { + case 0: + case IPA_RC_INVALID_SUBCMD: + card->info.promisc_mode = SET_PROMISC_MODE_OFF; + dev_info(&card->gdev->dev, "The HiperSockets network " + "traffic analyzer is deactivated\n"); + break; + default: + break; + } break; case QETH_DIAGS_CMD_TRACE_ENABLE: - card->info.promisc_mode = SET_PROMISC_MODE_ON; - dev_info(&card->gdev->dev, "The HiperSockets network traffic " - "analyzer is activated\n"); + switch (rc) { + case 0: + card->info.promisc_mode = SET_PROMISC_MODE_ON; + dev_info(&card->gdev->dev, "The HiperSockets network " + "traffic analyzer is activated\n"); + break; + case IPA_RC_HARDWARE_AUTH_ERROR: + dev_warn(&card->gdev->dev, "The device is not " + "authorized to run as a HiperSockets network " + "traffic analyzer\n"); + break; + case IPA_RC_TRACE_ALREADY_ACTIVE: + dev_warn(&card->gdev->dev, "A HiperSockets " + "network traffic analyzer is already " + "active in the HiperSockets LAN\n"); + break; + default: + break; + } break; default: QETH_DBF_MESSAGE(2, "Unknown sniffer action (0x%04x) on %s\n", @@ -2215,11 +2219,9 @@ static int qeth_l3_stop_card(struct qeth_card *card, int recovery_mode) if (recovery_mode) qeth_l3_stop(card->dev); else { - if (card->dev) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); } if (!card->use_hard_stop) { rc = qeth_send_stoplan(card); @@ -2900,10 +2902,8 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) int data_offset = -1; int nr_frags; - if ((card->info.type == QETH_CARD_TYPE_IQD) && - (((skb->protocol != htons(ETH_P_IPV6)) && - (skb->protocol != htons(ETH_P_IP))) || - card->options.sniffer)) + if (((card->info.type == QETH_CARD_TYPE_IQD) && (!ipv)) || + card->options.sniffer) goto tx_drop; if ((card->state != CARD_STATE_UP) || !card->lan_online) { @@ -2949,14 +2949,14 @@ static int qeth_l3_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) if (data_offset < 0) skb_pull(new_skb, ETH_HLEN); } else { - if (new_skb->protocol == htons(ETH_P_IP)) { + if (ipv == 4) { if (card->dev->type == ARPHRD_IEEE802_TR) skb_pull(new_skb, TR_HLEN); else skb_pull(new_skb, ETH_HLEN); } - if (new_skb->protocol == ETH_P_IPV6 && card->vlangrp && + if (ipv == 6 && card->vlangrp && vlan_tx_tag_present(new_skb)) { skb_push(new_skb, VLAN_HLEN); skb_copy_to_linear_data(new_skb, new_skb->data + 4, 4); @@ -3534,11 +3534,9 @@ static int qeth_l3_pm_resume(struct ccwgroup_device *gdev) if (card->state == CARD_STATE_RECOVER) { rc = __qeth_l3_set_online(card->gdev, 1); if (rc) { - if (card->dev) { - rtnl_lock(); - dev_close(card->dev); - rtnl_unlock(); - } + rtnl_lock(); + dev_close(card->dev); + rtnl_unlock(); } } else rc = __qeth_l3_set_online(card->gdev, 0); diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index fa34b92850a6..1b8217076b0e 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c @@ -738,7 +738,7 @@ static int __devinit qpti_register_irq(struct qlogicpti *qpti) * sanely maintain. */ if (request_irq(qpti->irq, qpti_intr, - IRQF_SHARED, "Qlogic/PTI", qpti)) + IRQF_SHARED, "QlogicPTI", qpti)) goto fail; printk("qlogicpti%d: IRQ %d ", qpti->qpti_id, qpti->irq); diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 1c60053439a9..4be9b4832c55 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -912,6 +912,18 @@ config FB_XVR2500 mostly initialized the card already. It is treated as a completely dumb framebuffer device. +config FB_XVR1000 + bool "Sun XVR-1000 support" + depends on SPARC64 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer device for the Sun XVR-1000 and similar + graphics cards. The driver only works on sparc64 systems where + the system firmware has mostly initialized the card already. It + is treated as a completely dumb framebuffer device. + config FB_PVR2 tristate "NEC PowerVR 2 display support" depends on FB && SH_DREAMCAST @@ -1869,7 +1881,7 @@ config FB_W100 config FB_SH_MOBILE_LCDC tristate "SuperH Mobile LCDC framebuffer support" - depends on FB && SUPERH && HAVE_CLK + depends on FB && (SUPERH || ARCH_SHMOBILE) && HAVE_CLK select FB_SYS_FILLRECT select FB_SYS_COPYAREA select FB_SYS_IMAGEBLIT diff --git a/drivers/video/Makefile b/drivers/video/Makefile index a42ad55e3a15..ddc2af2ba45b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -79,6 +79,7 @@ obj-$(CONFIG_FB_N411) += n411.o obj-$(CONFIG_FB_HGA) += hgafb.o obj-$(CONFIG_FB_XVR500) += sunxvr500.o obj-$(CONFIG_FB_XVR2500) += sunxvr2500.o +obj-$(CONFIG_FB_XVR1000) += sunxvr1000.o obj-$(CONFIG_FB_IGA) += igafb.o obj-$(CONFIG_FB_APOLLO) += dnfb.o obj-$(CONFIG_FB_Q40) += q40fb.o diff --git a/drivers/video/sunxvr1000.c b/drivers/video/sunxvr1000.c new file mode 100644 index 000000000000..a8248c0b9192 --- /dev/null +++ b/drivers/video/sunxvr1000.c @@ -0,0 +1,228 @@ +/* sunxvr1000.c: Sun XVR-1000 driver for sparc64 systems + * + * Copyright (C) 2010 David S. Miller (davem@davemloft.net) + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/of_device.h> + +struct gfb_info { + struct fb_info *info; + + char __iomem *fb_base; + unsigned long fb_base_phys; + + struct device_node *of_node; + + unsigned int width; + unsigned int height; + unsigned int depth; + unsigned int fb_size; + + u32 pseudo_palette[16]; +}; + +static int __devinit gfb_get_props(struct gfb_info *gp) +{ + gp->width = of_getintprop_default(gp->of_node, "width", 0); + gp->height = of_getintprop_default(gp->of_node, "height", 0); + gp->depth = of_getintprop_default(gp->of_node, "depth", 32); + + if (!gp->width || !gp->height) { + printk(KERN_ERR "gfb: Critical properties missing for %s\n", + gp->of_node->full_name); + return -EINVAL; + } + + return 0; +} + +static int gfb_setcolreg(unsigned regno, + unsigned red, unsigned green, unsigned blue, + unsigned transp, struct fb_info *info) +{ + u32 value; + + if (regno < 16) { + red >>= 8; + green >>= 8; + blue >>= 8; + + value = (blue << 16) | (green << 8) | red; + ((u32 *)info->pseudo_palette)[regno] = value; + } + + return 0; +} + +static struct fb_ops gfb_ops = { + .owner = THIS_MODULE, + .fb_setcolreg = gfb_setcolreg, + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static int __devinit gfb_set_fbinfo(struct gfb_info *gp) +{ + struct fb_info *info = gp->info; + struct fb_var_screeninfo *var = &info->var; + + info->flags = FBINFO_DEFAULT; + info->fbops = &gfb_ops; + info->screen_base = gp->fb_base; + info->screen_size = gp->fb_size; + + info->pseudo_palette = gp->pseudo_palette; + + /* Fill fix common fields */ + strlcpy(info->fix.id, "gfb", sizeof(info->fix.id)); + info->fix.smem_start = gp->fb_base_phys; + info->fix.smem_len = gp->fb_size; + info->fix.type = FB_TYPE_PACKED_PIXELS; + if (gp->depth == 32 || gp->depth == 24) + info->fix.visual = FB_VISUAL_TRUECOLOR; + else + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + + var->xres = gp->width; + var->yres = gp->height; + var->xres_virtual = var->xres; + var->yres_virtual = var->yres; + var->bits_per_pixel = gp->depth; + + var->red.offset = 0; + var->red.length = 8; + var->green.offset = 8; + var->green.length = 8; + var->blue.offset = 16; + var->blue.length = 8; + var->transp.offset = 0; + var->transp.length = 0; + + if (fb_alloc_cmap(&info->cmap, 256, 0)) { + printk(KERN_ERR "gfb: Cannot allocate color map.\n"); + return -ENOMEM; + } + + return 0; +} + +static int __devinit gfb_probe(struct of_device *op, + const struct of_device_id *match) +{ + struct device_node *dp = op->node; + struct fb_info *info; + struct gfb_info *gp; + int err; + + info = framebuffer_alloc(sizeof(struct gfb_info), &op->dev); + if (!info) { + printk(KERN_ERR "gfb: Cannot allocate fb_info\n"); + err = -ENOMEM; + goto err_out; + } + + gp = info->par; + gp->info = info; + gp->of_node = dp; + + gp->fb_base_phys = op->resource[6].start; + + err = gfb_get_props(gp); + if (err) + goto err_release_fb; + + /* Framebuffer length is the same regardless of resolution. */ + info->fix.line_length = 16384; + gp->fb_size = info->fix.line_length * gp->height; + + gp->fb_base = of_ioremap(&op->resource[6], 0, + gp->fb_size, "gfb fb"); + if (!gp->fb_base) + goto err_release_fb; + + err = gfb_set_fbinfo(gp); + if (err) + goto err_unmap_fb; + + printk("gfb: Found device at %s\n", dp->full_name); + + err = register_framebuffer(info); + if (err < 0) { + printk(KERN_ERR "gfb: Could not register framebuffer %s\n", + dp->full_name); + goto err_unmap_fb; + } + + dev_set_drvdata(&op->dev, info); + + return 0; + +err_unmap_fb: + of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size); + +err_release_fb: + framebuffer_release(info); + +err_out: + return err; +} + +static int __devexit gfb_remove(struct of_device *op) +{ + struct fb_info *info = dev_get_drvdata(&op->dev); + struct gfb_info *gp = info->par; + + unregister_framebuffer(info); + + iounmap(gp->fb_base); + + of_iounmap(&op->resource[6], gp->fb_base, gp->fb_size); + + framebuffer_release(info); + + dev_set_drvdata(&op->dev, NULL); + + return 0; +} + +static const struct of_device_id gfb_match[] = { + { + .name = "SUNW,gfb", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, ffb_match); + +static struct of_platform_driver gfb_driver = { + .name = "gfb", + .match_table = gfb_match, + .probe = gfb_probe, + .remove = __devexit_p(gfb_remove), +}; + +static int __init gfb_init(void) +{ + if (fb_get_options("gfb", NULL)) + return -ENODEV; + + return of_register_driver(&gfb_driver, &of_bus_type); +} + +static void __exit gfb_exit(void) +{ + of_unregister_driver(&gfb_driver); +} + +module_init(gfb_init); +module_exit(gfb_exit); + +MODULE_DESCRIPTION("framebuffer driver for Sun XVR-1000 graphics"); +MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); +MODULE_VERSION("1.0"); +MODULE_LICENSE("GPL"); |