diff options
Diffstat (limited to 'drivers')
80 files changed, 1281 insertions, 1022 deletions
diff --git a/drivers/ata/pata_palmld.c b/drivers/ata/pata_palmld.c index a2a73d95384..b86d7e22595 100644 --- a/drivers/ata/pata_palmld.c +++ b/drivers/ata/pata_palmld.c @@ -33,6 +33,11 @@ #define DRV_NAME "pata_palmld" +static struct gpio palmld_hdd_gpios[] = { + { GPIO_NR_PALMLD_IDE_PWEN, GPIOF_INIT_HIGH, "HDD Power" }, + { GPIO_NR_PALMLD_IDE_RESET, GPIOF_INIT_LOW, "HDD Reset" }, +}; + static struct scsi_host_template palmld_sht = { ATA_PIO_SHT(DRV_NAME), }; @@ -52,28 +57,23 @@ static __devinit int palmld_pata_probe(struct platform_device *pdev) /* allocate host */ host = ata_host_alloc(&pdev->dev, 1); - if (!host) - return -ENOMEM; + if (!host) { + ret = -ENOMEM; + goto err1; + } /* remap drive's physical memory address */ mem = devm_ioremap(&pdev->dev, PALMLD_IDE_PHYS, 0x1000); - if (!mem) - return -ENOMEM; + if (!mem) { + ret = -ENOMEM; + goto err1; + } /* request and activate power GPIO, IRQ GPIO */ - ret = gpio_request(GPIO_NR_PALMLD_IDE_PWEN, "HDD PWR"); + ret = gpio_request_array(palmld_hdd_gpios, + ARRAY_SIZE(palmld_hdd_gpios)); if (ret) goto err1; - ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_PWEN, 1); - if (ret) - goto err2; - - ret = gpio_request(GPIO_NR_PALMLD_IDE_RESET, "HDD RST"); - if (ret) - goto err2; - ret = gpio_direction_output(GPIO_NR_PALMLD_IDE_RESET, 0); - if (ret) - goto err3; /* reset the drive */ gpio_set_value(GPIO_NR_PALMLD_IDE_RESET, 0); @@ -96,13 +96,15 @@ static __devinit int palmld_pata_probe(struct platform_device *pdev) ata_sff_std_ports(&ap->ioaddr); /* activate host */ - return ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING, + ret = ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING, &palmld_sht); + if (ret) + goto err2; + + return ret; -err3: - gpio_free(GPIO_NR_PALMLD_IDE_RESET); err2: - gpio_free(GPIO_NR_PALMLD_IDE_PWEN); + gpio_free_array(palmld_hdd_gpios, ARRAY_SIZE(palmld_hdd_gpios)); err1: return ret; } @@ -116,8 +118,7 @@ static __devexit int palmld_pata_remove(struct platform_device *dev) /* power down the HDD */ gpio_set_value(GPIO_NR_PALMLD_IDE_PWEN, 0); - gpio_free(GPIO_NR_PALMLD_IDE_RESET); - gpio_free(GPIO_NR_PALMLD_IDE_PWEN); + gpio_free_array(palmld_hdd_gpios, ARRAY_SIZE(palmld_hdd_gpios)); return 0; } diff --git a/drivers/atm/solos-pci.c b/drivers/atm/solos-pci.c index 25ef1a4556e..cd0ff66469b 100644 --- a/drivers/atm/solos-pci.c +++ b/drivers/atm/solos-pci.c @@ -165,7 +165,6 @@ static uint32_t fpga_tx(struct solos_card *); static irqreturn_t solos_irq(int irq, void *dev_id); static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci); static int list_vccs(int vci); -static void release_vccs(struct atm_dev *dev); static int atm_init(struct solos_card *, struct device *); static void atm_remove(struct solos_card *); static int send_command(struct solos_card *card, int dev, const char *buf, size_t size); @@ -384,7 +383,6 @@ static int process_status(struct solos_card *card, int port, struct sk_buff *skb /* Anything but 'Showtime' is down */ if (strcmp(state_str, "Showtime")) { atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_LOST); - release_vccs(card->atmdev[port]); dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str); return 0; } @@ -697,7 +695,7 @@ void solos_bh(unsigned long card_arg) size); } if (atmdebug) { - dev_info(&card->dev->dev, "Received: device %d\n", port); + dev_info(&card->dev->dev, "Received: port %d\n", port); dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n", size, le16_to_cpu(header->vpi), le16_to_cpu(header->vci)); @@ -710,8 +708,8 @@ void solos_bh(unsigned long card_arg) le16_to_cpu(header->vci)); if (!vcc) { if (net_ratelimit()) - dev_warn(&card->dev->dev, "Received packet for unknown VCI.VPI %d.%d on port %d\n", - le16_to_cpu(header->vci), le16_to_cpu(header->vpi), + dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n", + le16_to_cpu(header->vpi), le16_to_cpu(header->vci), port); continue; } @@ -830,28 +828,6 @@ static int list_vccs(int vci) return num_found; } -static void release_vccs(struct atm_dev *dev) -{ - int i; - - write_lock_irq(&vcc_sklist_lock); - for (i = 0; i < VCC_HTABLE_SIZE; i++) { - struct hlist_head *head = &vcc_hash[i]; - struct hlist_node *node, *tmp; - struct sock *s; - struct atm_vcc *vcc; - - sk_for_each_safe(s, node, tmp, head) { - vcc = atm_sk(s); - if (vcc->dev == dev) { - vcc_release_async(vcc, -EPIPE); - sk_del_node_init(s); - } - } - } - write_unlock_irq(&vcc_sklist_lock); -} - static int popen(struct atm_vcc *vcc) { @@ -1018,8 +994,15 @@ static uint32_t fpga_tx(struct solos_card *card) /* Clean up and free oldskb now it's gone */ if (atmdebug) { + struct pkt_hdr *header = (void *)oldskb->data; + int size = le16_to_cpu(header->size); + + skb_pull(oldskb, sizeof(*header)); dev_info(&card->dev->dev, "Transmitted: port %d\n", port); + dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n", + size, le16_to_cpu(header->vpi), + le16_to_cpu(header->vci)); print_buffer(oldskb); } @@ -1262,7 +1245,7 @@ static int atm_init(struct solos_card *card, struct device *parent) card->atmdev[i]->ci_range.vci_bits = 16; card->atmdev[i]->dev_data = card; card->atmdev[i]->phy_data = (void *)(unsigned long)i; - atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_UNKNOWN); + atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND); skb = alloc_skb(sizeof(*header), GFP_ATOMIC); if (!skb) { diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 866811428e2..762a5109c68 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -71,6 +71,9 @@ static struct usb_device_id btusb_table[] = { /* Apple MacBookAir3,1, MacBookAir3,2 */ { USB_DEVICE(0x05ac, 0x821b) }, + /* Apple MacBookPro8,2 */ + { USB_DEVICE(0x05ac, 0x821a) }, + /* AVM BlueFRITZ! USB v2.0 */ { USB_DEVICE(0x057c, 0x3800) }, @@ -690,7 +693,8 @@ static int btusb_send_frame(struct sk_buff *skb) break; case HCI_ACLDATA_PKT: - if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1) + if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 && + hdev->conn_hash.le_num < 1)) return -ENODEV; urb = usb_alloc_urb(0, GFP_ATOMIC); diff --git a/drivers/connector/cn_queue.c b/drivers/connector/cn_queue.c index 55653aba673..c42c9d51779 100644 --- a/drivers/connector/cn_queue.c +++ b/drivers/connector/cn_queue.c @@ -31,24 +31,9 @@ #include <linux/connector.h> #include <linux/delay.h> -void cn_queue_wrapper(struct work_struct *work) -{ - struct cn_callback_entry *cbq = - container_of(work, struct cn_callback_entry, work); - struct cn_callback_data *d = &cbq->data; - struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(d->skb)); - struct netlink_skb_parms *nsp = &NETLINK_CB(d->skb); - - d->callback(msg, nsp); - - kfree_skb(d->skb); - d->skb = NULL; - - kfree(d->free); -} - static struct cn_callback_entry * -cn_queue_alloc_callback_entry(const char *name, struct cb_id *id, +cn_queue_alloc_callback_entry(struct cn_queue_dev *dev, const char *name, + struct cb_id *id, void (*callback)(struct cn_msg *, struct netlink_skb_parms *)) { struct cn_callback_entry *cbq; @@ -59,17 +44,23 @@ cn_queue_alloc_callback_entry(const char *name, struct cb_id *id, return NULL; } + atomic_set(&cbq->refcnt, 1); + + atomic_inc(&dev->refcnt); + cbq->pdev = dev; + snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name); memcpy(&cbq->id.id, id, sizeof(struct cb_id)); - cbq->data.callback = callback; - - INIT_WORK(&cbq->work, &cn_queue_wrapper); + cbq->callback = callback; return cbq; } -static void cn_queue_free_callback(struct cn_callback_entry *cbq) +void cn_queue_release_callback(struct cn_callback_entry *cbq) { - flush_workqueue(cbq->pdev->cn_queue); + if (!atomic_dec_and_test(&cbq->refcnt)) + return; + + atomic_dec(&cbq->pdev->refcnt); kfree(cbq); } @@ -85,13 +76,10 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name, struct cn_callback_entry *cbq, *__cbq; int found = 0; - cbq = cn_queue_alloc_callback_entry(name, id, callback); + cbq = cn_queue_alloc_callback_entry(dev, name, id, callback); if (!cbq) return -ENOMEM; - atomic_inc(&dev->refcnt); - cbq->pdev = dev; - spin_lock_bh(&dev->queue_lock); list_for_each_entry(__cbq, &dev->queue_list, callback_entry) { if (cn_cb_equal(&__cbq->id.id, id)) { @@ -104,8 +92,7 @@ int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name, spin_unlock_bh(&dev->queue_lock); if (found) { - cn_queue_free_callback(cbq); - atomic_dec(&dev->refcnt); + cn_queue_release_callback(cbq); return -EINVAL; } @@ -130,10 +117,8 @@ void cn_queue_del_callback(struct cn_queue_dev *dev, struct cb_id *id) } spin_unlock_bh(&dev->queue_lock); - if (found) { - cn_queue_free_callback(cbq); - atomic_dec(&dev->refcnt); - } + if (found) + cn_queue_release_callback(cbq); } struct cn_queue_dev *cn_queue_alloc_dev(const char *name, struct sock *nls) @@ -151,12 +136,6 @@ struct cn_queue_dev *cn_queue_alloc_dev(const char *name, struct sock *nls) dev->nls = nls; - dev->cn_queue = alloc_ordered_workqueue(dev->name, 0); - if (!dev->cn_queue) { - kfree(dev); - return NULL; - } - return dev; } @@ -164,9 +143,6 @@ void cn_queue_free_dev(struct cn_queue_dev *dev) { struct cn_callback_entry *cbq, *n; - flush_workqueue(dev->cn_queue); - destroy_workqueue(dev->cn_queue); - spin_lock_bh(&dev->queue_lock); list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry) list_del(&cbq->callback_entry); diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c index f7554de3be5..d77005849af 100644 --- a/drivers/connector/connector.c +++ b/drivers/connector/connector.c @@ -122,51 +122,28 @@ EXPORT_SYMBOL_GPL(cn_netlink_send); */ static int cn_call_callback(struct sk_buff *skb) { - struct cn_callback_entry *__cbq, *__new_cbq; + struct cn_callback_entry *i, *cbq = NULL; struct cn_dev *dev = &cdev; struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(skb)); + struct netlink_skb_parms *nsp = &NETLINK_CB(skb); int err = -ENODEV; spin_lock_bh(&dev->cbdev->queue_lock); - list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) { - if (cn_cb_equal(&__cbq->id.id, &msg->id)) { - if (likely(!work_pending(&__cbq->work) && - __cbq->data.skb == NULL)) { - __cbq->data.skb = skb; - - if (queue_work(dev->cbdev->cn_queue, - &__cbq->work)) - err = 0; - else - err = -EINVAL; - } else { - struct cn_callback_data *d; - - err = -ENOMEM; - __new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC); - if (__new_cbq) { - d = &__new_cbq->data; - d->skb = skb; - d->callback = __cbq->data.callback; - d->free = __new_cbq; - - INIT_WORK(&__new_cbq->work, - &cn_queue_wrapper); - - if (queue_work(dev->cbdev->cn_queue, - &__new_cbq->work)) - err = 0; - else { - kfree(__new_cbq); - err = -EINVAL; - } - } - } + list_for_each_entry(i, &dev->cbdev->queue_list, callback_entry) { + if (cn_cb_equal(&i->id.id, &msg->id)) { + atomic_inc(&i->refcnt); + cbq = i; break; } } spin_unlock_bh(&dev->cbdev->queue_lock); + if (cbq != NULL) { + cbq->callback(msg, nsp); + kfree_skb(skb); + cn_queue_release_callback(cbq); + } + return err; } diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index ffb5ad080be..38ab8e2cd7f 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c @@ -1147,13 +1147,14 @@ static struct platform_driver mpc85xx_mc_err_driver = { static void __init mpc85xx_mc_clear_rfxe(void *data) { orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1); - mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~0x20000)); + mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~HID1_RFXE)); } #endif static int __init mpc85xx_mc_init(void) { int res = 0; + u32 pvr = 0; printk(KERN_INFO "Freescale(R) MPC85xx EDAC driver, " "(C) 2006 Montavista Software\n"); @@ -1183,12 +1184,17 @@ static int __init mpc85xx_mc_init(void) #endif #ifdef CONFIG_FSL_SOC_BOOKE - /* - * need to clear HID1[RFXE] to disable machine check int - * so we can catch it - */ - if (edac_op_state == EDAC_OPSTATE_INT) - on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0); + pvr = mfspr(SPRN_PVR); + + if ((PVR_VER(pvr) == PVR_VER_E500V1) || + (PVR_VER(pvr) == PVR_VER_E500V2)) { + /* + * need to clear HID1[RFXE] to disable machine check int + * so we can catch it + */ + if (edac_op_state == EDAC_OPSTATE_INT) + on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0); + } #endif return 0; @@ -1206,7 +1212,12 @@ static void __exit mpc85xx_mc_restore_hid1(void *data) static void __exit mpc85xx_mc_exit(void) { #ifdef CONFIG_FSL_SOC_BOOKE - on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0); + u32 pvr = mfspr(SPRN_PVR); + + if ((PVR_VER(pvr) == PVR_VER_E500V1) || + (PVR_VER(pvr) == PVR_VER_E500V2)) { + on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0); + } #endif #ifdef CONFIG_PCI platform_driver_unregister(&mpc85xx_pci_err_driver); diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index 9c595e3b9c2..adc9358c9be 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c @@ -1297,7 +1297,7 @@ add_detailed_modes(struct drm_connector *connector, struct edid *edid, /** * Search EDID for CEA extension block. */ -static u8 *drm_find_cea_extension(struct edid *edid) +u8 *drm_find_cea_extension(struct edid *edid) { u8 *edid_ext = NULL; int i; @@ -1318,6 +1318,7 @@ static u8 *drm_find_cea_extension(struct edid *edid) return edid_ext; } +EXPORT_SYMBOL(drm_find_cea_extension); /** * drm_detect_hdmi_monitor - detect whether monitor is hdmi. diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 8342259f316..d03fc05b39c 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c @@ -269,21 +269,6 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) return ret; } -static bool intel_crt_ddc_probe(struct drm_i915_private *dev_priv, int ddc_bus) -{ - u8 buf; - struct i2c_msg msgs[] = { - { - .addr = 0xA0, - .flags = 0, - .len = 1, - .buf = &buf, - }, - }; - /* DDC monitor detect: Does it ACK a write to 0xA0? */ - return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1; -} - static bool intel_crt_detect_ddc(struct drm_connector *connector) { struct intel_crt *crt = intel_attached_crt(connector); @@ -293,11 +278,6 @@ static bool intel_crt_detect_ddc(struct drm_connector *connector) if (crt->base.type != INTEL_OUTPUT_ANALOG) return false; - if (intel_crt_ddc_probe(dev_priv, dev_priv->crt_ddc_pin)) { - DRM_DEBUG_KMS("CRT detected via DDC:0xa0\n"); - return true; - } - if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) { struct edid *edid; bool is_digital = false; diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index 5daa991cb28..f5b0d8306d8 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h @@ -39,7 +39,7 @@ ret__ = -ETIMEDOUT; \ break; \ } \ - if (W && !in_dbg_master()) msleep(W); \ + if (W && !(in_atomic() || in_dbg_master())) msleep(W); \ } \ ret__; \ }) diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index 82d04c5899d..d3b903bce7c 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c @@ -259,7 +259,7 @@ gmbus_xfer(struct i2c_adapter *adapter, if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) goto timeout; if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) - return 0; + goto clear_err; val = I915_READ(GMBUS3 + reg_offset); do { @@ -287,7 +287,7 @@ gmbus_xfer(struct i2c_adapter *adapter, if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50)) goto timeout; if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) - return 0; + goto clear_err; val = loop = 0; do { @@ -302,14 +302,31 @@ gmbus_xfer(struct i2c_adapter *adapter, if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50)) goto timeout; if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER) - return 0; + goto clear_err; } - return num; + goto done; + +clear_err: + /* Toggle the Software Clear Interrupt bit. This has the effect + * of resetting the GMBUS controller and so clearing the + * BUS_ERROR raised by the slave's NAK. + */ + I915_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT); + I915_WRITE(GMBUS1 + reg_offset, 0); + +done: + /* Mark the GMBUS interface as disabled. We will re-enable it at the + * start of the next xfer, till then let it sleep. + */ + I915_WRITE(GMBUS0 + reg_offset, 0); + return i; timeout: DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n", bus->reg0 & 0xff, bus->adapter.name); + I915_WRITE(GMBUS0 + reg_offset, 0); + /* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */ bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff); if (!bus->force_bit) diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 1a311ad0111..a562bd2648c 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c @@ -473,19 +473,13 @@ static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector, bool force) { struct drm_device *dev = connector->dev; - enum drm_connector_status status = connector_status_connected; + enum drm_connector_status status; status = intel_panel_detect(dev); if (status != connector_status_unknown) return status; - /* ACPI lid methods were generally unreliable in this generation, so - * don't even bother. - */ - if (IS_GEN2(dev) || IS_GEN3(dev)) - return connector_status_connected; - - return status; + return connector_status_connected; } /** @@ -835,25 +829,6 @@ static bool lvds_is_present_in_vbt(struct drm_device *dev, return false; } -static bool intel_lvds_ddc_probe(struct drm_device *dev, u8 pin) -{ - struct drm_i915_private *dev_priv = dev->dev_private; - u8 buf = 0; - struct i2c_msg msgs[] = { - { - .addr = 0xA0, - .flags = 0, - .len = 1, - .buf = &buf, - }, - }; - struct i2c_adapter *i2c = &dev_priv->gmbus[pin].adapter; - /* XXX this only appears to work when using GMBUS */ - if (intel_gmbus_is_forced_bit(i2c)) - return true; - return i2c_transfer(i2c, msgs, 1) == 1; -} - /** * intel_lvds_init - setup LVDS connectors on this device * @dev: drm device @@ -894,11 +869,6 @@ bool intel_lvds_init(struct drm_device *dev) } } - if (!intel_lvds_ddc_probe(dev, pin)) { - DRM_DEBUG_KMS("LVDS did not respond to DDC probe\n"); - return false; - } - intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL); if (!intel_lvds) { return false; diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index e8b04f4aed7..b52e4601824 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c @@ -97,7 +97,7 @@ nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan, return -ENOMEM; } - nvbo->bo.persistant_swap_storage = nvbo->gem->filp; + nvbo->bo.persistent_swap_storage = nvbo->gem->filp; nvbo->gem->driver_private = nvbo; return 0; } diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 10e41af6b02..b41ec59c710 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c @@ -1009,6 +1009,7 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, uint64_t fb_location; uint32_t fb_format, fb_pitch_pixels, tiling_flags; u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE); + u32 tmp; int r; /* no fb bound */ @@ -1137,6 +1138,15 @@ static int dce4_crtc_do_set_base(struct drm_crtc *crtc, WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset, (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); + /* pageflip setup */ + /* make sure flip is at vb rather than hb */ + tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); + tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; + WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); + + /* set pageflip to happen anywhere in vblank interval */ + WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); + if (!atomic && fb && fb != crtc->fb) { radeon_fb = to_radeon_framebuffer(fb); rbo = gem_to_radeon_bo(radeon_fb->obj); @@ -1167,6 +1177,7 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, uint64_t fb_location; uint32_t fb_format, fb_pitch_pixels, tiling_flags; u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE; + u32 tmp; int r; /* no fb bound */ @@ -1294,6 +1305,15 @@ static int avivo_crtc_do_set_base(struct drm_crtc *crtc, WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset, (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay); + /* pageflip setup */ + /* make sure flip is at vb rather than hb */ + tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); + tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; + WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); + + /* set pageflip to happen anywhere in vblank interval */ + WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); + if (!atomic && fb && fb != crtc->fb) { radeon_fb = to_radeon_framebuffer(fb); rbo = gem_to_radeon_bo(radeon_fb->obj); diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 941080a7794..0b0cc74c08c 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -43,17 +43,6 @@ static void evergreen_pcie_gen2_enable(struct radeon_device *rdev); void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc) { - struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; - u32 tmp; - - /* make sure flip is at vb rather than hb */ - tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); - tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN; - WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); - - /* set pageflip to happen anywhere in vblank interval */ - WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); - /* enable the pflip int */ radeon_irq_kms_pflip_irq_get(rdev, crtc); } diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 02d5c415f49..99768d9d91d 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -675,7 +675,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ATOM_ENCODER_CAP_RECORD *cap_record; u16 caps = 0; - while (record->ucRecordType > 0 && + while (record->ucRecordSize > 0 && + record->ucRecordType > 0 && record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { switch (record->ucRecordType) { case ATOM_ENCODER_CAP_RECORD_TYPE: @@ -720,7 +721,8 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) break; } - while (record->ucRecordType > 0 && + while (record->ucRecordSize > 0 && + record->ucRecordType > 0 && record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { switch (record->ucRecordType) { case ATOM_I2C_RECORD_TYPE: @@ -782,10 +784,9 @@ bool radeon_get_atom_connector_info_from_object_table(struct drm_device *dev) ATOM_HPD_INT_RECORD *hpd_record; ATOM_I2C_ID_CONFIG_ACCESS *i2c_config; - while (record->ucRecordType > 0 - && record-> - ucRecordType <= - ATOM_MAX_OBJECT_RECORD_NUMBER) { + while (record->ucRecordSize > 0 && + record->ucRecordType > 0 && + record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) { switch (record->ucRecordType) { case ATOM_I2C_RECORD_TYPE: i2c_record = diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index cf602e2d071..8caf546c8e9 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c @@ -2079,6 +2079,19 @@ bool radeon_get_legacy_connector_info_from_table(struct drm_device *dev) DRM_MODE_CONNECTOR_DVII, &ddc_i2c, CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I, &hpd); + /* TV - TV DAC */ + ddc_i2c.valid = false; + hpd.hpd = RADEON_HPD_NONE; + radeon_add_legacy_encoder(dev, + radeon_get_encoder_enum(dev, + ATOM_DEVICE_TV1_SUPPORT, + 2), + ATOM_DEVICE_TV1_SUPPORT); + radeon_add_legacy_connector(dev, 2, ATOM_DEVICE_TV1_SUPPORT, + DRM_MODE_CONNECTOR_SVIDEO, + &ddc_i2c, + CONNECTOR_OBJECT_ID_SVIDEO, + &hpd); break; default: DRM_INFO("Connector table: %d (invalid)\n", diff --git a/drivers/gpu/drm/radeon/rs600.c b/drivers/gpu/drm/radeon/rs600.c index 19763f5df5e..876cebc4b8b 100644 --- a/drivers/gpu/drm/radeon/rs600.c +++ b/drivers/gpu/drm/radeon/rs600.c @@ -48,17 +48,6 @@ int rs600_mc_wait_for_idle(struct radeon_device *rdev); void rs600_pre_page_flip(struct radeon_device *rdev, int crtc) { - struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc]; - u32 tmp; - - /* make sure flip is at vb rather than hb */ - tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset); - tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN; - WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp); - - /* set pageflip to happen anywhere in vblank interval */ - WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0); - /* enable the pflip int */ radeon_irq_kms_pflip_irq_get(rdev, crtc); } diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 0b6a55ac2f8..2e618b5ac46 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c @@ -1168,7 +1168,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev, uint32_t page_alignment, unsigned long buffer_start, bool interruptible, - struct file *persistant_swap_storage, + struct file *persistent_swap_storage, size_t acc_size, void (*destroy) (struct ttm_buffer_object *)) { @@ -1211,7 +1211,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev, bo->priv_flags = 0; bo->mem.placement = (TTM_PL_FLAG_SYSTEM | TTM_PL_FLAG_CACHED); bo->seq_valid = false; - bo->persistant_swap_storage = persistant_swap_storage; + bo->persistent_swap_storage = persistent_swap_storage; bo->acc_size = acc_size; atomic_inc(&bo->glob->bo_count); @@ -1260,7 +1260,7 @@ int ttm_bo_create(struct ttm_bo_device *bdev, uint32_t page_alignment, unsigned long buffer_start, bool interruptible, - struct file *persistant_swap_storage, + struct file *persistent_swap_storage, struct ttm_buffer_object **p_bo) { struct ttm_buffer_object *bo; @@ -1282,7 +1282,7 @@ int ttm_bo_create(struct ttm_bo_device *bdev, ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment, buffer_start, interruptible, - persistant_swap_storage, acc_size, NULL); + persistent_swap_storage, acc_size, NULL); if (likely(ret == 0)) *p_bo = bo; @@ -1863,7 +1863,7 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink) if (bo->bdev->driver->swap_notify) bo->bdev->driver->swap_notify(bo); - ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage); + ret = ttm_tt_swapout(bo->ttm, bo->persistent_swap_storage); out: /** diff --git a/drivers/gpu/drm/ttm/ttm_tt.c b/drivers/gpu/drm/ttm/ttm_tt.c index 86d5b1745a4..90e23e0bfad 100644 --- a/drivers/gpu/drm/ttm/ttm_tt.c +++ b/drivers/gpu/drm/ttm/ttm_tt.c @@ -332,7 +332,7 @@ void ttm_tt_destroy(struct ttm_tt *ttm) ttm_tt_free_page_directory(ttm); } - if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTANT_SWAP) && + if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) && ttm->swap_storage) fput(ttm->swap_storage); @@ -503,7 +503,7 @@ static int ttm_tt_swapin(struct ttm_tt *ttm) page_cache_release(from_page); } - if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTANT_SWAP)) + if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP)) fput(swap_storage); ttm->swap_storage = NULL; ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED; @@ -514,7 +514,7 @@ out_err: return ret; } -int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage) +int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage) { struct address_space *swap_space; struct file *swap_storage; @@ -540,7 +540,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage) return 0; } - if (!persistant_swap_storage) { + if (!persistent_swap_storage) { swap_storage = shmem_file_setup("ttm swap", ttm->num_pages << PAGE_SHIFT, 0); @@ -549,7 +549,7 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage) return PTR_ERR(swap_storage); } } else - swap_storage = persistant_swap_storage; + swap_storage = persistent_swap_storage; swap_space = swap_storage->f_path.dentry->d_inode->i_mapping; @@ -577,12 +577,12 @@ int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage) ttm_tt_free_alloced_pages(ttm); ttm->swap_storage = swap_storage; ttm->page_flags |= TTM_PAGE_FLAG_SWAPPED; - if (persistant_swap_storage) - ttm->page_flags |= TTM_PAGE_FLAG_PERSISTANT_SWAP; + if (persistent_swap_storage) + ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP; return 0; out_err: - if (!persistant_swap_storage) + if (!persistent_swap_storage) fput(swap_storage); return ret; diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c index 97e22bef85a..de5819199e2 100644 --- a/drivers/hwmon/twl4030-madc-hwmon.c +++ b/drivers/hwmon/twl4030-madc-hwmon.c @@ -154,4 +154,4 @@ module_exit(twl4030_madc_hwmon_exit); MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("J Keerthy"); -MODULE_ALIAS("twl4030_madc_hwmon"); +MODULE_ALIAS("platform:twl4030_madc_hwmon"); diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 0e406d73b2c..177db6d5b2f 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c @@ -430,6 +430,26 @@ static inline void ide_unlock_host(struct ide_host *host) } } +static void __ide_requeue_and_plug(struct request_queue *q, struct request *rq) +{ + if (rq) + blk_requeue_request(q, rq); + if (rq || blk_peek_request(q)) { + /* Use 3ms as that was the old plug delay */ + blk_delay_queue(q, 3); + } +} + +void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) +{ + struct request_queue *q = drive->queue; + unsigned long flags; + + spin_lock_irqsave(q->queue_lock, flags); + __ide_requeue_and_plug(q, rq); + spin_unlock_irqrestore(q->queue_lock, flags); +} + /* * Issue a new request to a device. */ @@ -550,28 +570,7 @@ plug_device: ide_unlock_host(host); plug_device_2: spin_lock_irq(q->queue_lock); - - if (rq) { - blk_requeue_request(q, rq); - blk_delay_queue(q, queue_run_ms); - } -} - -void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) -{ - struct request_queue *q = drive->queue; - unsigned long flags; - - spin_lock_irqsave(q->queue_lock, flags); - - if (rq) - blk_requeue_request(q, rq); - - spin_unlock_irqrestore(q->queue_lock, flags); - - /* Use 3ms as that was the old plug delay */ - if (rq) - blk_delay_queue(q, 3); + __ide_requeue_and_plug(q, rq); } static int drive_is_ready(ide_drive_t *drive) diff --git a/drivers/input/keyboard/spear-keyboard.c b/drivers/input/keyboard/spear-keyboard.c index bee03d64c45..d712dffd215 100644 --- a/drivers/input/keyboard/spear-keyboard.c +++ b/drivers/input/keyboard/spear-keyboard.c @@ -69,7 +69,7 @@ static irqreturn_t spear_kbd_interrupt(int irq, void *dev_id) u8 sts, val; sts = readb(kbd->io_base + STATUS_REG); - if (sts & DATA_AVAIL) + if (!(sts & DATA_AVAIL)) return IRQ_NONE; if (kbd->last_key != KEY_RESERVED) { diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 364bdf43a38..736056897e5 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c @@ -302,10 +302,14 @@ static int uinput_validate_absbits(struct input_dev *dev) int retval = 0; for (cnt = 0; cnt < ABS_CNT; cnt++) { + int min, max; if (!test_bit(cnt, dev->absbit)) continue; - if (input_abs_get_max(dev, cnt) <= input_abs_get_min(dev, cnt)) { + min = input_abs_get_min(dev, cnt); + max = input_abs_get_max(dev, cnt); + + if ((min != 0 || max != 0) && max <= min) { printk(KERN_DEBUG "%s: invalid abs[%02x] min:%d max:%d\n", UINPUT_NAME, cnt, diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index aa186cf6c51..e06e045bf90 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c @@ -836,8 +836,8 @@ static const struct dmi_system_id __initconst toshiba_dmi_table[] = { }, }, - { } #endif + { } }; static bool broken_olpc_ec; @@ -851,8 +851,8 @@ static const struct dmi_system_id __initconst olpc_dmi_table[] = { DMI_MATCH(DMI_PRODUCT_NAME, "XO"), }, }, - { } #endif + { } }; void __init synaptics_module_init(void) diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c index ac4c93689ab..d37a48e099d 100644 --- a/drivers/input/serio/i8042.c +++ b/drivers/input/serio/i8042.c @@ -869,15 +869,15 @@ static int i8042_controller_selftest(void) do { if (i8042_command(¶m, I8042_CMD_CTL_TEST)) { - pr_err("i8042 controller self test timeout\n"); + pr_err("i8042 controller selftest timeout\n"); return -ENODEV; } if (param == I8042_RET_CTL_TEST) return 0; - pr_err("i8042 controller selftest failed. (%#x != %#x)\n", - param, I8042_RET_CTL_TEST); + dbg("i8042 controller selftest: %#x != %#x\n", + param, I8042_RET_CTL_TEST); msleep(50); } while (i++ < 5); @@ -891,6 +891,7 @@ static int i8042_controller_selftest(void) pr_info("giving up on controller selftest, continuing anyway...\n"); return 0; #else + pr_err("i8042 controller selftest failed\n"); return -EIO; #endif } diff --git a/drivers/input/serio/rpckbd.c b/drivers/input/serio/rpckbd.c index 9da6fbcaaa7..7ec3c97dc1b 100644 --- a/drivers/input/serio/rpckbd.c +++ b/drivers/input/serio/rpckbd.c @@ -90,7 +90,7 @@ static int rpckbd_open(struct serio *port) if (request_irq(IRQ_KEYBOARDTX, rpckbd_tx, 0, "rpckbd", port) != 0) { printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n"); - free_irq(IRQ_KEYBOARDRX, NULL); + free_irq(IRQ_KEYBOARDRX, port); return -EBUSY; } diff --git a/drivers/input/sparse-keymap.c b/drivers/input/sparse-keymap.c index 337bf51bc98..fdb6a3976f9 100644 --- a/drivers/input/sparse-keymap.c +++ b/drivers/input/sparse-keymap.c @@ -208,6 +208,12 @@ int sparse_keymap_setup(struct input_dev *dev, } } + if (test_bit(EV_KEY, dev->evbit)) { + __set_bit(KEY_UNKNOWN, dev->keybit); + __set_bit(EV_MSC, dev->evbit); + __set_bit(MSC_SCAN, dev->mscbit); + } + dev->keycode = map; dev->keycodemax = map_size; dev->getkeycode = sparse_keymap_getkeycode; @@ -268,6 +274,7 @@ void sparse_keymap_report_entry(struct input_dev *dev, const struct key_entry *k { switch (ke->type) { case KE_KEY: + input_event(dev, EV_MSC, MSC_SCAN, ke->code); input_report_key(dev, ke->keycode, value); input_sync(dev); if (value && autorelease) { @@ -305,12 +312,19 @@ bool sparse_keymap_report_event(struct input_dev *dev, unsigned int code, { const struct key_entry *ke = sparse_keymap_entry_from_scancode(dev, code); + struct key_entry unknown_ke; if (ke) { sparse_keymap_report_entry(dev, ke, value, autorelease); return true; } + /* Report an unknown key event as a debugging aid */ + unknown_ke.type = KE_KEY; + unknown_ke.code = code; + unknown_ke.keycode = KEY_UNKNOWN; + sparse_keymap_report_entry(dev, &unknown_ke, value, true); + return false; } EXPORT_SYMBOL(sparse_keymap_report_event); diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 5597637cfd4..08ba5ad9c9b 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c @@ -16,6 +16,14 @@ #include "wacom.h" #include <linux/input/mt.h> +/* resolution for penabled devices */ +#define WACOM_PL_RES 20 +#define WACOM_PENPRTN_RES 40 +#define WACOM_VOLITO_RES 50 +#define WACOM_GRAPHIRE_RES 80 +#define WACOM_INTUOS_RES 100 +#define WACOM_INTUOS3_RES 200 + static int wacom_penpartner_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; @@ -1055,6 +1063,19 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max, features->pressure_fuzz, 0); + if (features->device_type == BTN_TOOL_PEN) { + /* penabled devices have fixed resolution for each model */ + input_abs_set_res(input_dev, ABS_X, features->x_resolution); + input_abs_set_res(input_dev, ABS_Y, features->y_resolution); + } else { + input_abs_set_res(input_dev, ABS_X, + wacom_calculate_touch_res(features->x_max, + features->x_phy)); + input_abs_set_res(input_dev, ABS_Y, + wacom_calculate_touch_res(features->y_max, + features->y_phy)); + } + __set_bit(ABS_MISC, input_dev->absbit); switch (wacom_wac->features.type) { @@ -1171,15 +1192,9 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, case TABLETPC: __clear_bit(ABS_MISC, input_dev->absbit); - if (features->device_type != BTN_TOOL_PEN) { - input_abs_set_res(input_dev, ABS_X, - wacom_calculate_touch_res(features->x_max, - features->x_phy)); - input_abs_set_res(input_dev, ABS_Y, - wacom_calculate_touch_res(features->y_max, - features->y_phy)); + if (features->device_type != BTN_TOOL_PEN) break; /* no need to process stylus stuff */ - } + /* fall through */ case PL: @@ -1216,12 +1231,6 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, input_set_abs_params(input_dev, ABS_MT_PRESSURE, 0, features->pressure_max, features->pressure_fuzz, 0); - input_abs_set_res(input_dev, ABS_X, - wacom_calculate_touch_res(features->x_max, - features->x_phy)); - input_abs_set_res(input_dev, ABS_Y, - wacom_calculate_touch_res(features->y_max, - features->y_phy)); } else if (features->device_type == BTN_TOOL_PEN) { __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_TOOL_PEN, input_dev->keybit); @@ -1233,161 +1242,242 @@ void wacom_setup_input_capabilities(struct input_dev *input_dev, } static const struct wacom_features wacom_features_0x00 = - { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, 0, PENPARTNER }; + { "Wacom Penpartner", WACOM_PKGLEN_PENPRTN, 5040, 3780, 255, + 0, PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; static const struct wacom_features wacom_features_0x10 = - { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }; + { "Wacom Graphire", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, + 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x11 = - { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, 63, GRAPHIRE }; + { "Wacom Graphire2 4x5", WACOM_PKGLEN_GRAPHIRE, 10206, 7422, 511, + 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x12 = - { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, 63, GRAPHIRE }; + { "Wacom Graphire2 5x7", WACOM_PKGLEN_GRAPHIRE, 13918, 10206, 511, + 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x13 = - { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, GRAPHIRE }; + { "Wacom Graphire3", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, + 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x14 = - { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }; + { "Wacom Graphire3 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, + 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x15 = - { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, 63, WACOM_G4 }; + { "Wacom Graphire4 4x5", WACOM_PKGLEN_GRAPHIRE, 10208, 7424, 511, + 63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x16 = - { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, WACOM_G4 }; + { "Wacom Graphire4 6x8", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, + 63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x17 = - { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }; + { "Wacom BambooFun 4x5", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, + 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x18 = - { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, 63, WACOM_MO }; + { "Wacom BambooFun 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 511, + 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x19 = - { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, 63, GRAPHIRE }; + { "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE, 16704, 12064, 511, + 63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES }; static const struct wacom_features wacom_features_0x60 = - { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; + { "Wacom Volito", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, + 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; static const struct wacom_features wacom_features_0x61 = - { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, 63, GRAPHIRE }; + { "Wacom PenStation2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 255, + 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; static const struct wacom_features wacom_features_0x62 = - { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; + { "Wacom Volito2 4x5", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, + 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; static const struct wacom_features wacom_features_0x63 = - { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, 63, GRAPHIRE }; + { "Wacom Volito2 2x3", WACOM_PKGLEN_GRAPHIRE, 3248, 2320, 511, + 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; static const struct wacom_features wacom_features_0x64 = - { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, 63, GRAPHIRE }; + { "Wacom PenPartner2", WACOM_PKGLEN_GRAPHIRE, 3250, 2320, 511, + 63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES }; static const struct wacom_features wacom_features_0x65 = - { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, 63, WACOM_MO }; + { "Wacom Bamboo", WACOM_PKGLEN_BBFUN, 14760, 9225, 511, + 63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x69 = - { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, 63, GRAPHIRE }; + { "Wacom Bamboo1", WACOM_PKGLEN_GRAPHIRE, 5104, 3712, 511, + 63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES }; static const struct wacom_features wacom_features_0x20 = - { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }; + { "Wacom Intuos 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x21 = - { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; + { "Wacom Intuos 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x22 = - { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }; + { "Wacom Intuos 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x23 = - { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }; + { "Wacom Intuos 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x24 = - { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }; + { "Wacom Intuos 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x30 = - { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, 0, PL }; + { "Wacom PL400", WACOM_PKGLEN_GRAPHIRE, 5408, 4056, 255, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x31 = - { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, 0, PL }; + { "Wacom PL500", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 255, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x32 = - { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, 0, PL }; + { "Wacom PL600", WACOM_PKGLEN_GRAPHIRE, 6126, 4604, 255, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x33 = - { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, 0, PL }; + { "Wacom PL600SX", WACOM_PKGLEN_GRAPHIRE, 6260, 5016, 255, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x34 = - { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, 0, PL }; + { "Wacom PL550", WACOM_PKGLEN_GRAPHIRE, 6144, 4608, 511, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x35 = - { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, 0, PL }; + { "Wacom PL800", WACOM_PKGLEN_GRAPHIRE, 7220, 5780, 511, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x37 = - { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, 0, PL }; + { "Wacom PL700", WACOM_PKGLEN_GRAPHIRE, 6758, 5406, 511, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x38 = - { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }; + { "Wacom PL510", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x39 = - { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, 0, PL }; + { "Wacom DTU710", WACOM_PKGLEN_GRAPHIRE, 34080, 27660, 511, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0xC4 = - { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, 0, PL }; + { "Wacom DTF521", WACOM_PKGLEN_GRAPHIRE, 6282, 4762, 511, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0xC0 = - { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }; + { "Wacom DTF720", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0xC2 = - { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, 0, PL }; + { "Wacom DTF720a", WACOM_PKGLEN_GRAPHIRE, 6858, 5506, 511, + 0, PL, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x03 = - { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, 0, PTU }; + { "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE, 20480, 15360, 511, + 0, PTU, WACOM_PL_RES, WACOM_PL_RES }; static const struct wacom_features wacom_features_0x41 = - { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, 31, INTUOS }; + { "Wacom Intuos2 4x5", WACOM_PKGLEN_INTUOS, 12700, 10600, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x42 = - { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; + { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x43 = - { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, 31, INTUOS }; + { "Wacom Intuos2 9x12", WACOM_PKGLEN_INTUOS, 30480, 24060, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x44 = - { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, 31, INTUOS }; + { "Wacom Intuos2 12x12", WACOM_PKGLEN_INTUOS, 30480, 31680, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x45 = - { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, 31, INTUOS }; + { "Wacom Intuos2 12x18", WACOM_PKGLEN_INTUOS, 45720, 31680, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xB0 = - { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, 63, INTUOS3S }; + { "Wacom Intuos3 4x5", WACOM_PKGLEN_INTUOS, 25400, 20320, 1023, + 63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB1 = - { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, 63, INTUOS3 }; + { "Wacom Intuos3 6x8", WACOM_PKGLEN_INTUOS, 40640, 30480, 1023, + 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB2 = - { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, 63, INTUOS3 }; + { "Wacom Intuos3 9x12", WACOM_PKGLEN_INTUOS, 60960, 45720, 1023, + 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB3 = - { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, 63, INTUOS3L }; + { "Wacom Intuos3 12x12", WACOM_PKGLEN_INTUOS, 60960, 60960, 1023, + 63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB4 = - { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, 63, INTUOS3L }; + { "Wacom Intuos3 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 1023, + 63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB5 = - { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, 63, INTUOS3 }; + { "Wacom Intuos3 6x11", WACOM_PKGLEN_INTUOS, 54204, 31750, 1023, + 63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB7 = - { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, 63, INTUOS3S }; + { "Wacom Intuos3 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 1023, + 63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB8 = - { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, 63, INTUOS4S }; + { "Wacom Intuos4 4x6", WACOM_PKGLEN_INTUOS, 31496, 19685, 2047, + 63, INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xB9 = - { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, 63, INTUOS4 }; + { "Wacom Intuos4 6x9", WACOM_PKGLEN_INTUOS, 44704, 27940, 2047, + 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xBA = - { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, 63, INTUOS4L }; + { "Wacom Intuos4 8x13", WACOM_PKGLEN_INTUOS, 65024, 40640, 2047, + 63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xBB = - { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, 63, INTUOS4L }; + { "Wacom Intuos4 12x19", WACOM_PKGLEN_INTUOS, 97536, 60960, 2047, + 63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xBC = - { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047, 63, INTUOS4 }; + { "Wacom Intuos4 WL", WACOM_PKGLEN_INTUOS, 40840, 25400, 2047, + 63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x3F = - { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, 63, CINTIQ }; + { "Wacom Cintiq 21UX", WACOM_PKGLEN_INTUOS, 87200, 65600, 1023, + 63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xC5 = - { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, 63, WACOM_BEE }; + { "Wacom Cintiq 20WSX", WACOM_PKGLEN_INTUOS, 86680, 54180, 1023, + 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xC6 = - { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, 63, WACOM_BEE }; + { "Wacom Cintiq 12WX", WACOM_PKGLEN_INTUOS, 53020, 33440, 1023, + 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0xC7 = - { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, 0, PL }; + { "Wacom DTU1931", WACOM_PKGLEN_GRAPHIRE, 37832, 30305, 511, + 0, PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xCE = - { "Wacom DTU2231", WACOM_PKGLEN_GRAPHIRE, 47864, 27011, 511, 0, DTU }; + { "Wacom DTU2231", WACOM_PKGLEN_GRAPHIRE, 47864, 27011, 511, + 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xF0 = - { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511, 0, DTU }; + { "Wacom DTU1631", WACOM_PKGLEN_GRAPHIRE, 34623, 19553, 511, + 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xCC = - { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, 63, WACOM_21UX2 }; + { "Wacom Cintiq 21UX2", WACOM_PKGLEN_INTUOS, 87200, 65600, 2047, + 63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x90 = - { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; + { "Wacom ISDv4 90", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x93 = - { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; + { "Wacom ISDv4 93", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x9A = - { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; + { "Wacom ISDv4 9A", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x9F = - { "Wacom ISDv4 9F", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, 0, TABLETPC }; + { "Wacom ISDv4 9F", WACOM_PKGLEN_GRAPHIRE, 26202, 16325, 255, + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xE2 = - { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; + { "Wacom ISDv4 E2", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, + 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xE3 = - { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, 0, TABLETPC2FG }; + { "Wacom ISDv4 E3", WACOM_PKGLEN_TPC2FG, 26202, 16325, 255, + 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xE6 = + { "Wacom ISDv4 E6", WACOM_PKGLEN_TPC2FG, 27760, 15694, 255, + 0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x47 = - { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, 31, INTUOS }; -static struct wacom_features wacom_features_0xD0 = - { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; -static struct wacom_features wacom_features_0xD1 = - { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; -static struct wacom_features wacom_features_0xD2 = - { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; -static struct wacom_features wacom_features_0xD3 = - { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT }; + { "Wacom Intuos2 6x8", WACOM_PKGLEN_INTUOS, 20320, 16240, 1023, + 31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xD0 = + { "Wacom Bamboo 2FG", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, + 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xD1 = + { "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, + 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xD2 = + { "Wacom Bamboo Craft", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, + 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xD3 = + { "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, + 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xD4 = - { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 255, 63, BAMBOO_PT }; -static struct wacom_features wacom_features_0xD6 = - { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; -static struct wacom_features wacom_features_0xD7 = - { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; -static struct wacom_features wacom_features_0xD8 = - { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT }; -static struct wacom_features wacom_features_0xDA = - { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, 63, BAMBOO_PT }; + { "Wacom Bamboo Pen", WACOM_PKGLEN_BBFUN, 14720, 9200, 255, + 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xD6 = + { "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, + 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xD7 = + { "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, + 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xD8 = + { "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, + 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; +static const struct wacom_features wacom_features_0xDA = + { "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN, 14720, 9200, 1023, + 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static struct wacom_features wacom_features_0xDB = - { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, 63, BAMBOO_PT }; + { "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN, 21648, 13530, 1023, + 63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x6004 = - { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, 0, TABLETPC }; + { "ISD-V4", WACOM_PKGLEN_GRAPHIRE, 12800, 8000, 255, + 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; #define USB_DEVICE_WACOM(prod) \ USB_DEVICE(USB_VENDOR_ID_WACOM, prod), \ @@ -1474,6 +1564,7 @@ const struct usb_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x9F) }, { USB_DEVICE_WACOM(0xE2) }, { USB_DEVICE_WACOM(0xE3) }, + { USB_DEVICE_WACOM(0xE6) }, { USB_DEVICE_WACOM(0x47) }, { USB_DEVICE_LENOVO(0x6004) }, { } diff --git a/drivers/input/tablet/wacom_wac.h b/drivers/input/tablet/wacom_wac.h index 835f756b150..53eb71b6833 100644 --- a/drivers/input/tablet/wacom_wac.h +++ b/drivers/input/tablet/wacom_wac.h @@ -74,6 +74,8 @@ struct wacom_features { int pressure_max; int distance_max; int type; + int x_resolution; + int y_resolution; int device_type; int x_phy; int y_phy; diff --git a/drivers/input/touchscreen/h3600_ts_input.c b/drivers/input/touchscreen/h3600_ts_input.c index b4d7f63deff..efa06882de0 100644 --- a/drivers/input/touchscreen/h3600_ts_input.c +++ b/drivers/input/touchscreen/h3600_ts_input.c @@ -62,7 +62,7 @@ MODULE_LICENSE("GPL"); Programmer has no control over these numbers. TODO there are holes - specifically 1,7,0x0a */ -#define VERSION_ID 0 /* Get Version (request/respose) */ +#define VERSION_ID 0 /* Get Version (request/response) */ #define KEYBD_ID 2 /* Keyboard (event) */ #define TOUCHS_ID 3 /* Touch Screen (event)*/ #define EEPROM_READ_ID 4 /* (request/response) */ diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c index bca2af2e376..c987033714f 100644 --- a/drivers/macintosh/therm_pm72.c +++ b/drivers/macintosh/therm_pm72.c @@ -153,7 +153,7 @@ static struct i2c_adapter * u3_0; static struct i2c_adapter * u3_1; static struct i2c_adapter * k2; static struct i2c_client * fcu; -static struct cpu_pid_state cpu_state[2]; +static struct cpu_pid_state processor_state[2]; static struct basckside_pid_params backside_params; static struct backside_pid_state backside_state; static struct drives_pid_state drives_state; @@ -664,8 +664,8 @@ static int read_eeprom(int cpu, struct mpu_data *out) static void fetch_cpu_pumps_minmax(void) { - struct cpu_pid_state *state0 = &cpu_state[0]; - struct cpu_pid_state *state1 = &cpu_state[1]; + struct cpu_pid_state *state0 = &processor_state[0]; + struct cpu_pid_state *state1 = &processor_state[1]; u16 pump_min = 0, pump_max = 0xffff; u16 tmp[4]; @@ -717,17 +717,17 @@ static ssize_t show_##name(struct device *dev, struct device_attribute *attr, ch return sprintf(buf, "%d", data); \ } -BUILD_SHOW_FUNC_FIX(cpu0_temperature, cpu_state[0].last_temp) -BUILD_SHOW_FUNC_FIX(cpu0_voltage, cpu_state[0].voltage) -BUILD_SHOW_FUNC_FIX(cpu0_current, cpu_state[0].current_a) -BUILD_SHOW_FUNC_INT(cpu0_exhaust_fan_rpm, cpu_state[0].rpm) -BUILD_SHOW_FUNC_INT(cpu0_intake_fan_rpm, cpu_state[0].intake_rpm) +BUILD_SHOW_FUNC_FIX(cpu0_temperature, processor_state[0].last_temp) +BUILD_SHOW_FUNC_FIX(cpu0_voltage, processor_state[0].voltage) +BUILD_SHOW_FUNC_FIX(cpu0_current, processor_state[0].current_a) +BUILD_SHOW_FUNC_INT(cpu0_exhaust_fan_rpm, processor_state[0].rpm) +BUILD_SHOW_FUNC_INT(cpu0_intake_fan_rpm, processor_state[0].intake_rpm) -BUILD_SHOW_FUNC_FIX(cpu1_temperature, cpu_state[1].last_temp) -BUILD_SHOW_FUNC_FIX(cpu1_voltage, cpu_state[1].voltage) -BUILD_SHOW_FUNC_FIX(cpu1_current, cpu_state[1].current_a) -BUILD_SHOW_FUNC_INT(cpu1_exhaust_fan_rpm, cpu_state[1].rpm) -BUILD_SHOW_FUNC_INT(cpu1_intake_fan_rpm, cpu_state[1].intake_rpm) +BUILD_SHOW_FUNC_FIX(cpu1_temperature, processor_state[1].last_temp) +BUILD_SHOW_FUNC_FIX(cpu1_voltage, processor_state[1].voltage) +BUILD_SHOW_FUNC_FIX(cpu1_current, processor_state[1].current_a) +BUILD_SHOW_FUNC_INT(cpu1_exhaust_fan_rpm, processor_state[1].rpm) +BUILD_SHOW_FUNC_INT(cpu1_intake_fan_rpm, processor_state[1].intake_rpm) BUILD_SHOW_FUNC_FIX(backside_temperature, backside_state.last_temp) BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm) @@ -919,8 +919,8 @@ static void do_cpu_pid(struct cpu_pid_state *state, s32 temp, s32 power) static void do_monitor_cpu_combined(void) { - struct cpu_pid_state *state0 = &cpu_state[0]; - struct cpu_pid_state *state1 = &cpu_state[1]; + struct cpu_pid_state *state0 = &processor_state[0]; + struct cpu_pid_state *state1 = &processor_state[1]; s32 temp0, power0, temp1, power1; s32 temp_combi, power_combi; int rc, intake, pump; @@ -1150,7 +1150,7 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state) /* * Initialize the state structure for one CPU control loop */ -static int init_cpu_state(struct cpu_pid_state *state, int index) +static int init_processor_state(struct cpu_pid_state *state, int index) { int err; @@ -1205,7 +1205,7 @@ static int init_cpu_state(struct cpu_pid_state *state, int index) /* * Dispose of the state data for one CPU control loop */ -static void dispose_cpu_state(struct cpu_pid_state *state) +static void dispose_processor_state(struct cpu_pid_state *state) { if (state->monitor == NULL) return; @@ -1804,9 +1804,9 @@ static int main_control_loop(void *x) set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM); /* Initialize ADCs */ - initialize_adc(&cpu_state[0]); - if (cpu_state[1].monitor != NULL) - initialize_adc(&cpu_state[1]); + initialize_adc(&processor_state[0]); + if (processor_state[1].monitor != NULL) + initialize_adc(&processor_state[1]); fcu_tickle_ticks = FCU_TICKLE_TICKS; @@ -1833,14 +1833,14 @@ static int main_control_loop(void *x) if (cpu_pid_type == CPU_PID_TYPE_COMBINED) do_monitor_cpu_combined(); else if (cpu_pid_type == CPU_PID_TYPE_RACKMAC) { - do_monitor_cpu_rack(&cpu_state[0]); - if (cpu_state[1].monitor != NULL) - do_monitor_cpu_rack(&cpu_state[1]); + do_monitor_cpu_rack(&processor_state[0]); + if (processor_state[1].monitor != NULL) + do_monitor_cpu_rack(&processor_state[1]); // better deal with UP } else { - do_monitor_cpu_split(&cpu_state[0]); - if (cpu_state[1].monitor != NULL) - do_monitor_cpu_split(&cpu_state[1]); + do_monitor_cpu_split(&processor_state[0]); + if (processor_state[1].monitor != NULL) + do_monitor_cpu_split(&processor_state[1]); // better deal with UP } /* Then, the rest */ @@ -1885,8 +1885,8 @@ static int main_control_loop(void *x) */ static void dispose_control_loops(void) { - dispose_cpu_state(&cpu_state[0]); - dispose_cpu_state(&cpu_state[1]); + dispose_processor_state(&processor_state[0]); + dispose_processor_state(&processor_state[1]); dispose_backside_state(&backside_state); dispose_drives_state(&drives_state); dispose_slots_state(&slots_state); @@ -1928,12 +1928,12 @@ static int create_control_loops(void) /* Create control loops for everything. If any fail, everything * fails */ - if (init_cpu_state(&cpu_state[0], 0)) + if (init_processor_state(&processor_state[0], 0)) goto fail; if (cpu_pid_type == CPU_PID_TYPE_COMBINED) fetch_cpu_pumps_minmax(); - if (cpu_count > 1 && init_cpu_state(&cpu_state[1], 1)) + if (cpu_count > 1 && init_processor_state(&processor_state[1], 1)) goto fail; if (init_backside_state(&backside_state)) goto fail; diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 416d4e258df..cb8380c9767 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c @@ -927,20 +927,80 @@ static int dm_table_build_index(struct dm_table *t) } /* + * Get a disk whose integrity profile reflects the table's profile. + * If %match_all is true, all devices' profiles must match. + * If %match_all is false, all devices must at least have an + * allocated integrity profile; but uninitialized is ok. + * Returns NULL if integrity support was inconsistent or unavailable. + */ +static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t, + bool match_all) +{ + struct list_head *devices = dm_table_get_devices(t); + struct dm_dev_internal *dd = NULL; + struct gendisk *prev_disk = NULL, *template_disk = NULL; + + list_for_each_entry(dd, devices, list) { + template_disk = dd->dm_dev.bdev->bd_disk; + if (!blk_get_integrity(template_disk)) + goto no_integrity; + if (!match_all && !blk_integrity_is_initialized(template_disk)) + continue; /* skip uninitialized profiles */ + else if (prev_disk && + blk_integrity_compare(prev_disk, template_disk) < 0) + goto no_integrity; + prev_disk = template_disk; + } + + return template_disk; + +no_integrity: + if (prev_disk) + DMWARN("%s: integrity not set: %s and %s profile mismatch", + dm_device_name(t->md), + prev_disk->disk_name, + template_disk->disk_name); + return NULL; +} + +/* * Register the mapped device for blk_integrity support if - * the underlying devices support it. + * the underlying devices have an integrity profile. But all devices + * may not have matching profiles (checking all devices isn't reliable + * during table load because this table may use other DM device(s) which + * must be resumed before they will have an initialized integity profile). + * Stacked DM devices force a 2 stage integrity profile validation: + * 1 - during load, validate all initialized integrity profiles match + * 2 - during resume, validate all integrity profiles match */ static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md) { - struct list_head *devices = dm_table_get_devices(t); - struct dm_dev_internal *dd; + struct gendisk *template_disk = NULL; - list_for_each_entry(dd, devices, list) - if (bdev_get_integrity(dd->dm_dev.bdev)) { - t->integrity_supported = 1; - return blk_integrity_register(dm_disk(md), NULL); - } + template_disk = dm_table_get_integrity_disk(t, false); + if (!template_disk) + return 0; + if (!blk_integrity_is_initialized(dm_disk(md))) { + t->integrity_supported = 1; + return blk_integrity_register(dm_disk(md), NULL); + } + + /* + * If DM device already has an initalized integrity + * profile the new profile should not conflict. + */ + if (blk_integrity_is_initialized(template_disk) && + blk_integrity_compare(dm_disk(md), template_disk) < 0) { + DMWARN("%s: conflict with existing integrity profile: " + "%s profile mismatch", + dm_device_name(t->md), + template_disk->disk_name); + return 1; + } + + /* Preserve existing initialized integrity profile */ + t->integrity_supported = 1; return 0; } @@ -1094,41 +1154,27 @@ combine_limits: /* * Set the integrity profile for this device if all devices used have - * matching profiles. + * matching profiles. We're quite deep in the resume path but still + * don't know if all devices (particularly DM devices this device + * may be stacked on) have matching profiles. Even if the profiles + * don't match we have no way to fail (to resume) at this point. */ static void dm_table_set_integrity(struct dm_table *t) { - struct list_head *devices = dm_table_get_devices(t); - struct dm_dev_internal *prev = NULL, *dd = NULL; + struct gendisk *template_disk = NULL; if (!blk_get_integrity(dm_disk(t->md))) return; - list_for_each_entry(dd, devices, list) { - if (prev && - blk_integrity_compare(prev->dm_dev.bdev->bd_disk, - dd->dm_dev.bdev->bd_disk) < 0) { - DMWARN("%s: integrity not set: %s and %s mismatch", - dm_device_name(t->md), - prev->dm_dev.bdev->bd_disk->disk_name, - dd->dm_dev.bdev->bd_disk->disk_name); - goto no_integrity; - } - prev = dd; + template_disk = dm_table_get_integrity_disk(t, true); + if (!template_disk && + blk_integrity_is_initialized(dm_disk(t->md))) { + DMWARN("%s: device no longer has a valid integrity profile", + dm_device_name(t->md)); + return; } - - if (!prev || !bdev_get_integrity(prev->dm_dev.bdev)) - goto no_integrity; - blk_integrity_register(dm_disk(t->md), - bdev_get_integrity(prev->dm_dev.bdev)); - - return; - -no_integrity: - blk_integrity_register(dm_disk(t->md), NULL); - - return; + blk_get_integrity(template_disk)); } void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q, diff --git a/drivers/media/radio/wl128x/fmdrv_common.c b/drivers/media/radio/wl128x/fmdrv_common.c index 64454d39c0c..ecfd9fb167d 100644 --- a/drivers/media/radio/wl128x/fmdrv_common.c +++ b/drivers/media/radio/wl128x/fmdrv_common.c @@ -1494,12 +1494,17 @@ u32 fmc_prepare(struct fmdev *fmdev) } memset(&fm_st_proto, 0, sizeof(fm_st_proto)); - fm_st_proto.type = ST_FM; fm_st_proto.recv = fm_st_receive; fm_st_proto.match_packet = NULL; fm_st_proto.reg_complete_cb = fm_st_reg_comp_cb; fm_st_proto.write = NULL; /* TI ST driver will fill write pointer */ fm_st_proto.priv_data = fmdev; + fm_st_proto.chnl_id = 0x08; + fm_st_proto.max_frame_size = 0xff; + fm_st_proto.hdr_len = 1; + fm_st_proto.offset_len_in_hdr = 0; + fm_st_proto.len_size = 1; + fm_st_proto.reserve = 1; ret = st_register(&fm_st_proto); if (ret == -EINPROGRESS) { @@ -1532,7 +1537,7 @@ u32 fmc_prepare(struct fmdev *fmdev) g_st_write = fm_st_proto.write; } else { fmerr("Failed to get ST write func pointer\n"); - ret = st_unregister(ST_FM); + ret = st_unregister(&fm_st_proto); if (ret < 0) fmerr("st_unregister failed %d\n", ret); return -EAGAIN; @@ -1586,6 +1591,7 @@ u32 fmc_prepare(struct fmdev *fmdev) */ u32 fmc_release(struct fmdev *fmdev) { + static struct st_proto_s fm_st_proto; u32 ret; if (!test_bit(FM_CORE_READY, &fmdev->flag)) { @@ -1604,7 +1610,11 @@ u32 fmc_release(struct fmdev *fmdev) fmdev->resp_comp = NULL; fmdev->rx.freq = 0; - ret = st_unregister(ST_FM); + memset(&fm_st_proto, 0, sizeof(fm_st_proto)); + fm_st_proto.chnl_id = 0x08; + + ret = st_unregister(&fm_st_proto); + if (ret < 0) fmerr("Failed to de-register FM from ST %d\n", ret); else diff --git a/drivers/media/rc/ite-cir.c b/drivers/media/rc/ite-cir.c index ac0e42b47b2..accaf6c9789 100644 --- a/drivers/media/rc/ite-cir.c +++ b/drivers/media/rc/ite-cir.c @@ -41,6 +41,7 @@ #include <linux/bitops.h> #include <media/rc-core.h> #include <linux/pci_ids.h> +#include <linux/delay.h> #include "ite-cir.h" diff --git a/drivers/net/atlx/atl2.c b/drivers/net/atlx/atl2.c index e637e9f28fd..937ef1afa5d 100644 --- a/drivers/net/atlx/atl2.c +++ b/drivers/net/atlx/atl2.c @@ -1996,13 +1996,15 @@ static int atl2_set_eeprom(struct net_device *netdev, if (!eeprom_buff) return -ENOMEM; - ptr = (u32 *)eeprom_buff; + ptr = eeprom_buff; if (eeprom->offset & 3) { /* need read/modify/write of first changed EEPROM word */ /* only the second byte of the word is being modified */ - if (!atl2_read_eeprom(hw, first_dword*4, &(eeprom_buff[0]))) - return -EIO; + if (!atl2_read_eeprom(hw, first_dword*4, &(eeprom_buff[0]))) { + ret_val = -EIO; + goto out; + } ptr++; } if (((eeprom->offset + eeprom->len) & 3)) { @@ -2011,18 +2013,22 @@ static int atl2_set_eeprom(struct net_device *netdev, * only the first byte of the word is being modified */ if (!atl2_read_eeprom(hw, last_dword * 4, - &(eeprom_buff[last_dword - first_dword]))) - return -EIO; + &(eeprom_buff[last_dword - first_dword]))) { + ret_val = -EIO; + goto out; + } } /* Device's eeprom is always little-endian, word addressable */ memcpy(ptr, bytes, eeprom->len); for (i = 0; i < last_dword - first_dword + 1; i++) { - if (!atl2_write_eeprom(hw, ((first_dword+i)*4), eeprom_buff[i])) - return -EIO; + if (!atl2_write_eeprom(hw, ((first_dword+i)*4), eeprom_buff[i])) { + ret_val = -EIO; + goto out; + } } - + out: kfree(eeprom_buff); return ret_val; } diff --git a/drivers/net/bonding/bond_alb.h b/drivers/net/bonding/bond_alb.h index 118c28aa471..4b3e3587840 100644 --- a/drivers/net/bonding/bond_alb.h +++ b/drivers/net/bonding/bond_alb.h @@ -74,7 +74,7 @@ struct tlb_client_info { * packets to a Client that the Hash function * gave this entry index. */ - u32 tx_bytes; /* Each Client acumulates the BytesTx that + u32 tx_bytes; /* Each Client accumulates the BytesTx that * were tranmitted to it, and after each * CallBack the LoadHistory is devided * by the balance interval diff --git a/drivers/net/irda/via-ircc.c b/drivers/net/irda/via-ircc.c index 67c0ad42d81..186cd28a61c 100644 --- a/drivers/net/irda/via-ircc.c +++ b/drivers/net/irda/via-ircc.c @@ -75,15 +75,9 @@ static int dongle_id = 0; /* default: probe */ /* We can't guess the type of connected dongle, user *must* supply it. */ module_param(dongle_id, int, 0); -/* FIXME : we should not need this, because instances should be automatically - * managed by the PCI layer. Especially that we seem to only be using the - * first entry. Jean II */ -/* Max 4 instances for now */ -static struct via_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL }; - /* Some prototypes */ -static int via_ircc_open(int i, chipio_t * info, unsigned int id); -static int via_ircc_close(struct via_ircc_cb *self); +static int via_ircc_open(struct pci_dev *pdev, chipio_t * info, + unsigned int id); static int via_ircc_dma_receive(struct via_ircc_cb *self); static int via_ircc_dma_receive_complete(struct via_ircc_cb *self, int iobase); @@ -215,7 +209,7 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi pci_write_config_byte(pcidev,0x42,(bTmp | 0xf0)); pci_write_config_byte(pcidev,0x5a,0xc0); WriteLPCReg(0x28, 0x70 ); - if (via_ircc_open(0, &info,0x3076) == 0) + if (via_ircc_open(pcidev, &info, 0x3076) == 0) rc=0; } else rc = -ENODEV; //IR not turn on @@ -254,7 +248,7 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi info.irq=FirIRQ; info.dma=FirDRQ1; info.dma2=FirDRQ0; - if (via_ircc_open(0, &info,0x3096) == 0) + if (via_ircc_open(pcidev, &info, 0x3096) == 0) rc=0; } else rc = -ENODEV; //IR not turn on !!!!! @@ -264,48 +258,10 @@ static int __devinit via_init_one (struct pci_dev *pcidev, const struct pci_devi return rc; } -/* - * Function via_ircc_clean () - * - * Close all configured chips - * - */ -static void via_ircc_clean(void) -{ - int i; - - IRDA_DEBUG(3, "%s()\n", __func__); - - for (i=0; i < ARRAY_SIZE(dev_self); i++) { - if (dev_self[i]) - via_ircc_close(dev_self[i]); - } -} - -static void __devexit via_remove_one (struct pci_dev *pdev) -{ - IRDA_DEBUG(3, "%s()\n", __func__); - - /* FIXME : This is ugly. We should use pci_get_drvdata(pdev); - * to get our driver instance and call directly via_ircc_close(). - * See vlsi_ir for details... - * Jean II */ - via_ircc_clean(); - - /* FIXME : This should be in via_ircc_close(), because here we may - * theoritically disable still configured devices :-( - Jean II */ - pci_disable_device(pdev); -} - static void __exit via_ircc_cleanup(void) { IRDA_DEBUG(3, "%s()\n", __func__); - /* FIXME : This should be redundant, as pci_unregister_driver() - * should call via_remove_one() on each device. - * Jean II */ - via_ircc_clean(); - /* Cleanup all instances of the driver */ pci_unregister_driver (&via_driver); } @@ -324,12 +280,13 @@ static const struct net_device_ops via_ircc_fir_ops = { }; /* - * Function via_ircc_open (iobase, irq) + * Function via_ircc_open(pdev, iobase, irq) * * Open driver instance * */ -static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) +static __devinit int via_ircc_open(struct pci_dev *pdev, chipio_t * info, + unsigned int id) { struct net_device *dev; struct via_ircc_cb *self; @@ -337,9 +294,6 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) IRDA_DEBUG(3, "%s()\n", __func__); - if (i >= ARRAY_SIZE(dev_self)) - return -ENOMEM; - /* Allocate new instance of the driver */ dev = alloc_irdadev(sizeof(struct via_ircc_cb)); if (dev == NULL) @@ -349,13 +303,8 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) self->netdev = dev; spin_lock_init(&self->lock); - /* FIXME : We should store our driver instance in the PCI layer, - * using pci_set_drvdata(), not in this array. - * See vlsi_ir for details... - Jean II */ - /* FIXME : 'i' is always 0 (see via_init_one()) :-( - Jean II */ - /* Need to store self somewhere */ - dev_self[i] = self; - self->index = i; + pci_set_drvdata(pdev, self); + /* Initialize Resource */ self->io.cfg_base = info->cfg_base; self->io.fir_base = info->fir_base; @@ -414,7 +363,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) /* Allocate memory if needed */ self->rx_buff.head = - dma_alloc_coherent(NULL, self->rx_buff.truesize, + dma_alloc_coherent(&pdev->dev, self->rx_buff.truesize, &self->rx_buff_dma, GFP_KERNEL); if (self->rx_buff.head == NULL) { err = -ENOMEM; @@ -423,7 +372,7 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) memset(self->rx_buff.head, 0, self->rx_buff.truesize); self->tx_buff.head = - dma_alloc_coherent(NULL, self->tx_buff.truesize, + dma_alloc_coherent(&pdev->dev, self->tx_buff.truesize, &self->tx_buff_dma, GFP_KERNEL); if (self->tx_buff.head == NULL) { err = -ENOMEM; @@ -455,33 +404,32 @@ static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id) via_hw_init(self); return 0; err_out4: - dma_free_coherent(NULL, self->tx_buff.truesize, + dma_free_coherent(&pdev->dev, self->tx_buff.truesize, self->tx_buff.head, self->tx_buff_dma); err_out3: - dma_free_coherent(NULL, self->rx_buff.truesize, + dma_free_coherent(&pdev->dev, self->rx_buff.truesize, self->rx_buff.head, self->rx_buff_dma); err_out2: release_region(self->io.fir_base, self->io.fir_ext); err_out1: + pci_set_drvdata(pdev, NULL); free_netdev(dev); - dev_self[i] = NULL; return err; } /* - * Function via_ircc_close (self) + * Function via_remove_one(pdev) * * Close driver instance * */ -static int via_ircc_close(struct via_ircc_cb *self) +static void __devexit via_remove_one(struct pci_dev *pdev) { + struct via_ircc_cb *self = pci_get_drvdata(pdev); int iobase; IRDA_DEBUG(3, "%s()\n", __func__); - IRDA_ASSERT(self != NULL, return -1;); - iobase = self->io.fir_base; ResetChip(iobase, 5); //hardware reset. @@ -493,16 +441,16 @@ static int via_ircc_close(struct via_ircc_cb *self) __func__, self->io.fir_base); release_region(self->io.fir_base, self->io.fir_ext); if (self->tx_buff.head) - dma_free_coherent(NULL, self->tx_buff.truesize, + dma_free_coherent(&pdev->dev, self->tx_buff.truesize, self->tx_buff.head, self->tx_buff_dma); if (self->rx_buff.head) - dma_free_coherent(NULL, self->rx_buff.truesize, + dma_free_coherent(&pdev->dev, self->rx_buff.truesize, self->rx_buff.head, self->rx_buff_dma); - dev_self[self->index] = NULL; + pci_set_drvdata(pdev, NULL); free_netdev(self->netdev); - return 0; + pci_disable_device(pdev); } /* diff --git a/drivers/net/mlx4/eq.c b/drivers/net/mlx4/eq.c index 506cfd0372e..1ad1f6029af 100644 --- a/drivers/net/mlx4/eq.c +++ b/drivers/net/mlx4/eq.c @@ -603,7 +603,9 @@ int mlx4_init_eq_table(struct mlx4_dev *dev) } for (i = 0; i < dev->caps.num_comp_vectors; ++i) { - err = mlx4_create_eq(dev, dev->caps.num_cqs + MLX4_NUM_SPARE_EQE, + err = mlx4_create_eq(dev, dev->caps.num_cqs - + dev->caps.reserved_cqs + + MLX4_NUM_SPARE_EQE, (dev->flags & MLX4_FLAG_MSI_X) ? i : 0, &priv->eq_table.eq[i]); if (err) { diff --git a/drivers/net/mlx4/mcg.c b/drivers/net/mlx4/mcg.c index e71372aa9cc..c6d336aed2d 100644 --- a/drivers/net/mlx4/mcg.c +++ b/drivers/net/mlx4/mcg.c @@ -111,7 +111,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port, u32 members_count; struct mlx4_steer_index *new_entry; struct mlx4_promisc_qp *pqp; - struct mlx4_promisc_qp *dqp; + struct mlx4_promisc_qp *dqp = NULL; u32 prot; int err; u8 pf_num; @@ -184,7 +184,7 @@ out_mailbox: out_alloc: if (dqp) { list_del(&dqp->list); - kfree(&dqp); + kfree(dqp); } list_del(&new_entry->list); kfree(new_entry); @@ -469,7 +469,6 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port, /*remove from list of promisc qps */ list_del(&pqp->list); - kfree(pqp); /* set the default entry not to include the removed one */ mailbox = mlx4_alloc_cmd_mailbox(dev); @@ -528,6 +527,8 @@ out_mailbox: out_list: if (back_to_list) list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]); + else + kfree(pqp); out_mutex: mutex_unlock(&priv->mcg_table.mutex); return err; diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 993c52c82ae..e870c0698bb 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -442,11 +442,11 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, u32 flags, phy_interface_t interface) { struct device *d = &phydev->dev; + int err; /* Assume that if there is no driver, that it doesn't * exist, and we should use the genphy driver. */ if (NULL == d->driver) { - int err; d->driver = &genphy_driver.driver; err = d->driver->probe(d); @@ -474,7 +474,11 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev, /* Do initial configuration here, now that * we have certain key parameters * (dev_flags and interface) */ - return phy_init_hw(phydev); + err = phy_init_hw(phydev); + if (err) + phy_detach(phydev); + + return err; } /** diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c index a4f2bd52e54..36045f3b032 100644 --- a/drivers/net/starfire.c +++ b/drivers/net/starfire.c @@ -144,11 +144,7 @@ static int full_duplex[MAX_UNITS] = {0, }; /* Time in jiffies before concluding the transmitter is hung. */ #define TX_TIMEOUT (2 * HZ) -/* - * This SUCKS. - * We need a much better method to determine if dma_addr_t is 64-bit. - */ -#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || (defined(CONFIG_MIPS) && ((defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || defined(CONFIG_64BIT))) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT)) +#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT /* 64-bit dma_addr_t */ #define ADDR_64BITS /* This chip uses 64 bit addresses. */ #define netdrv_addr_t __le64 diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 6f600cced6e..3ec22c30779 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig @@ -433,4 +433,19 @@ config USB_SIERRA_NET To compile this driver as a module, choose M here: the module will be called sierra_net. +config USB_VL600 + tristate "LG VL600 modem dongle" + depends on USB_NET_CDCETHER + select USB_ACM + help + Select this if you want to use an LG Electronics 4G/LTE usb modem + called VL600. This driver only handles the ethernet + interface exposed by the modem firmware. To establish a connection + you will first need a userspace program that sends the right + command to the modem through its CDC ACM port, and most + likely also a DHCP client. See this thread about using the + 4G modem from Verizon: + + http://ubuntuforums.org/showpost.php?p=10589647&postcount=17 + endmenu diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index cac17030118..c7ec8a5f0a9 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile @@ -27,4 +27,5 @@ obj-$(CONFIG_USB_IPHETH) += ipheth.o obj-$(CONFIG_USB_SIERRA_NET) += sierra_net.o obj-$(CONFIG_USB_NET_CX82310_ETH) += cx82310_eth.o obj-$(CONFIG_USB_NET_CDC_NCM) += cdc_ncm.o +obj-$(CONFIG_USB_VL600) += lg-vl600.o diff --git a/drivers/net/usb/cdc_eem.c b/drivers/net/usb/cdc_eem.c index 5f3b97668e6..8f128541656 100644 --- a/drivers/net/usb/cdc_eem.c +++ b/drivers/net/usb/cdc_eem.c @@ -340,7 +340,7 @@ next: static const struct driver_info eem_info = { .description = "CDC EEM Device", - .flags = FLAG_ETHER, + .flags = FLAG_ETHER | FLAG_POINTTOPOINT, .bind = eem_bind, .rx_fixup = eem_rx_fixup, .tx_fixup = eem_tx_fixup, diff --git a/drivers/net/usb/cdc_ether.c b/drivers/net/usb/cdc_ether.c index 9a60e415d76..341f7056a80 100644 --- a/drivers/net/usb/cdc_ether.c +++ b/drivers/net/usb/cdc_ether.c @@ -378,7 +378,7 @@ static void dumpspeed(struct usbnet *dev, __le32 *speeds) __le32_to_cpu(speeds[1]) / 1000); } -static void cdc_status(struct usbnet *dev, struct urb *urb) +void usbnet_cdc_status(struct usbnet *dev, struct urb *urb) { struct usb_cdc_notification *event; @@ -418,8 +418,9 @@ static void cdc_status(struct usbnet *dev, struct urb *urb) break; } } +EXPORT_SYMBOL_GPL(usbnet_cdc_status); -static int cdc_bind(struct usbnet *dev, struct usb_interface *intf) +int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf) { int status; struct cdc_state *info = (void *) &dev->data; @@ -441,6 +442,7 @@ static int cdc_bind(struct usbnet *dev, struct usb_interface *intf) */ return 0; } +EXPORT_SYMBOL_GPL(usbnet_cdc_bind); static int cdc_manage_power(struct usbnet *dev, int on) { @@ -450,20 +452,20 @@ static int cdc_manage_power(struct usbnet *dev, int on) static const struct driver_info cdc_info = { .description = "CDC Ethernet Device", - .flags = FLAG_ETHER, + .flags = FLAG_ETHER | FLAG_POINTTOPOINT, // .check_connect = cdc_check_connect, - .bind = cdc_bind, + .bind = usbnet_cdc_bind, .unbind = usbnet_cdc_unbind, - .status = cdc_status, + .status = usbnet_cdc_status, .manage_power = cdc_manage_power, }; static const struct driver_info mbm_info = { .description = "Mobile Broadband Network Device", .flags = FLAG_WWAN, - .bind = cdc_bind, + .bind = usbnet_cdc_bind, .unbind = usbnet_cdc_unbind, - .status = cdc_status, + .status = usbnet_cdc_status, .manage_power = cdc_manage_power, }; @@ -560,6 +562,13 @@ static const struct usb_device_id products [] = { .driver_info = 0, }, +/* LG Electronics VL600 wants additional headers on every frame */ +{ + USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = 0, +}, + /* * WHITELIST!!! * diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 7113168473c..967371f0445 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c @@ -1237,7 +1237,7 @@ static int cdc_ncm_manage_power(struct usbnet *dev, int status) static const struct driver_info cdc_ncm_info = { .description = "CDC NCM", - .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET, + .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET, .bind = cdc_ncm_bind, .unbind = cdc_ncm_unbind, .check_connect = cdc_ncm_check_connect, diff --git a/drivers/net/usb/cdc_subset.c b/drivers/net/usb/cdc_subset.c index ca39ace0b0e..fc5f13d47ad 100644 --- a/drivers/net/usb/cdc_subset.c +++ b/drivers/net/usb/cdc_subset.c @@ -89,6 +89,7 @@ static int always_connected (struct usbnet *dev) static const struct driver_info ali_m5632_info = { .description = "ALi M5632", + .flags = FLAG_POINTTOPOINT, }; #endif @@ -110,6 +111,7 @@ static const struct driver_info ali_m5632_info = { static const struct driver_info an2720_info = { .description = "AnchorChips/Cypress 2720", + .flags = FLAG_POINTTOPOINT, // no reset available! // no check_connect available! @@ -132,6 +134,7 @@ static const struct driver_info an2720_info = { static const struct driver_info belkin_info = { .description = "Belkin, eTEK, or compatible", + .flags = FLAG_POINTTOPOINT, }; #endif /* CONFIG_USB_BELKIN */ @@ -157,6 +160,7 @@ static const struct driver_info belkin_info = { static const struct driver_info epson2888_info = { .description = "Epson USB Device", .check_connect = always_connected, + .flags = FLAG_POINTTOPOINT, .in = 4, .out = 3, }; @@ -173,6 +177,7 @@ static const struct driver_info epson2888_info = { #define HAVE_HARDWARE static const struct driver_info kc2190_info = { .description = "KC Technology KC-190", + .flags = FLAG_POINTTOPOINT, }; #endif /* CONFIG_USB_KC2190 */ @@ -200,16 +205,19 @@ static const struct driver_info kc2190_info = { static const struct driver_info linuxdev_info = { .description = "Linux Device", .check_connect = always_connected, + .flags = FLAG_POINTTOPOINT, }; static const struct driver_info yopy_info = { .description = "Yopy", .check_connect = always_connected, + .flags = FLAG_POINTTOPOINT, }; static const struct driver_info blob_info = { .description = "Boot Loader OBject", .check_connect = always_connected, + .flags = FLAG_POINTTOPOINT, }; #endif /* CONFIG_USB_ARMLINUX */ diff --git a/drivers/net/usb/gl620a.c b/drivers/net/usb/gl620a.c index dcd57c37ef7..c4cfd1dea88 100644 --- a/drivers/net/usb/gl620a.c +++ b/drivers/net/usb/gl620a.c @@ -193,7 +193,7 @@ static int genelink_bind(struct usbnet *dev, struct usb_interface *intf) static const struct driver_info genelink_info = { .description = "Genesys GeneLink", - .flags = FLAG_FRAMING_GL | FLAG_NO_SETINT, + .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_GL | FLAG_NO_SETINT, .bind = genelink_bind, .rx_fixup = genelink_rx_fixup, .tx_fixup = genelink_tx_fixup, diff --git a/drivers/net/usb/lg-vl600.c b/drivers/net/usb/lg-vl600.c new file mode 100644 index 00000000000..1d83ccfd727 --- /dev/null +++ b/drivers/net/usb/lg-vl600.c @@ -0,0 +1,346 @@ +/* + * Ethernet interface part of the LG VL600 LTE modem (4G dongle) + * + * Copyright (C) 2011 Intel Corporation + * Author: Andrzej Zaborowski <balrogg@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#include <linux/etherdevice.h> +#include <linux/ethtool.h> +#include <linux/mii.h> +#include <linux/usb.h> +#include <linux/usb/cdc.h> +#include <linux/usb/usbnet.h> +#include <linux/if_ether.h> +#include <linux/if_arp.h> +#include <linux/inetdevice.h> + +/* + * The device has a CDC ACM port for modem control (it claims to be + * CDC ACM anyway) and a CDC Ethernet port for actual network data. + * It will however ignore data on both ports that is not encapsulated + * in a specific way, any data returned is also encapsulated the same + * way. The headers don't seem to follow any popular standard. + * + * This driver adds and strips these headers from the ethernet frames + * sent/received from the CDC Ethernet port. The proprietary header + * replaces the standard ethernet header in a packet so only actual + * ethernet frames are allowed. The headers allow some form of + * multiplexing by using non standard values of the .h_proto field. + * Windows/Mac drivers do send a couple of such frames to the device + * during initialisation, with protocol set to 0x0906 or 0x0b06 and (what + * seems to be) a flag in the .dummy_flags. This doesn't seem necessary + * for modem operation but can possibly be used for GPS or other funcitons. + */ + +struct vl600_frame_hdr { + __le32 len; + __le32 serial; + __le32 pkt_cnt; + __le32 dummy_flags; + __le32 dummy; + __le32 magic; +} __attribute__((packed)); + +struct vl600_pkt_hdr { + __le32 dummy[2]; + __le32 len; + __be16 h_proto; +} __attribute__((packed)); + +struct vl600_state { + struct sk_buff *current_rx_buf; +}; + +static int vl600_bind(struct usbnet *dev, struct usb_interface *intf) +{ + int ret; + struct vl600_state *s = kzalloc(sizeof(struct vl600_state), GFP_KERNEL); + + if (!s) + return -ENOMEM; + + ret = usbnet_cdc_bind(dev, intf); + if (ret) { + kfree(s); + return ret; + } + + dev->driver_priv = s; + + /* ARP packets don't go through, but they're also of no use. The + * subnet has only two hosts anyway: us and the gateway / DHCP + * server (probably simulated by modem firmware or network operator) + * whose address changes everytime we connect to the intarwebz and + * who doesn't bother answering ARP requests either. So hardware + * addresses have no meaning, the destination and the source of every + * packet depend only on whether it is on the IN or OUT endpoint. */ + dev->net->flags |= IFF_NOARP; + + return ret; +} + +static void vl600_unbind(struct usbnet *dev, struct usb_interface *intf) +{ + struct vl600_state *s = dev->driver_priv; + + if (s->current_rx_buf) + dev_kfree_skb(s->current_rx_buf); + + kfree(s); + + return usbnet_cdc_unbind(dev, intf); +} + +static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb) +{ + struct vl600_frame_hdr *frame; + struct vl600_pkt_hdr *packet; + struct ethhdr *ethhdr; + int packet_len, count; + struct sk_buff *buf = skb; + struct sk_buff *clone; + struct vl600_state *s = dev->driver_priv; + + /* Frame lengths are generally 4B multiplies but every couple of + * hours there's an odd number of bytes sized yet correct frame, + * so don't require this. */ + + /* Allow a packet (or multiple packets batched together) to be + * split across many frames. We don't allow a new batch to + * begin in the same frame another one is ending however, and no + * leading or trailing pad bytes. */ + if (s->current_rx_buf) { + frame = (struct vl600_frame_hdr *) s->current_rx_buf->data; + if (skb->len + s->current_rx_buf->len > + le32_to_cpup(&frame->len)) { + netif_err(dev, ifup, dev->net, "Fragment too long\n"); + dev->net->stats.rx_length_errors++; + goto error; + } + + buf = s->current_rx_buf; + memcpy(skb_put(buf, skb->len), skb->data, skb->len); + } else if (skb->len < 4) { + netif_err(dev, ifup, dev->net, "Frame too short\n"); + dev->net->stats.rx_length_errors++; + goto error; + } + + frame = (struct vl600_frame_hdr *) buf->data; + /* NOTE: Should check that frame->magic == 0x53544448? + * Otherwise if we receive garbage at the beginning of the frame + * we may end up allocating a huge buffer and saving all the + * future incoming data into it. */ + + if (buf->len < sizeof(*frame) || + buf->len != le32_to_cpup(&frame->len)) { + /* Save this fragment for later assembly */ + if (s->current_rx_buf) + return 0; + + s->current_rx_buf = skb_copy_expand(skb, 0, + le32_to_cpup(&frame->len), GFP_ATOMIC); + if (!s->current_rx_buf) { + netif_err(dev, ifup, dev->net, "Reserving %i bytes " + "for packet assembly failed.\n", + le32_to_cpup(&frame->len)); + dev->net->stats.rx_errors++; + } + + return 0; + } + + count = le32_to_cpup(&frame->pkt_cnt); + + skb_pull(buf, sizeof(*frame)); + + while (count--) { + if (buf->len < sizeof(*packet)) { + netif_err(dev, ifup, dev->net, "Packet too short\n"); + goto error; + } + + packet = (struct vl600_pkt_hdr *) buf->data; + packet_len = sizeof(*packet) + le32_to_cpup(&packet->len); + if (packet_len > buf->len) { + netif_err(dev, ifup, dev->net, + "Bad packet length stored in header\n"); + goto error; + } + + /* Packet header is same size as the ethernet header + * (sizeof(*packet) == sizeof(*ethhdr)), additionally + * the h_proto field is in the same place so we just leave it + * alone and fill in the remaining fields. + */ + ethhdr = (struct ethhdr *) skb->data; + if (be16_to_cpup(ðhdr->h_proto) == ETH_P_ARP && + buf->len > 0x26) { + /* Copy the addresses from packet contents */ + memcpy(ethhdr->h_source, + &buf->data[sizeof(*ethhdr) + 0x8], + ETH_ALEN); + memcpy(ethhdr->h_dest, + &buf->data[sizeof(*ethhdr) + 0x12], + ETH_ALEN); + } else { + memset(ethhdr->h_source, 0, ETH_ALEN); + memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN); + } + + if (count) { + /* Not the last packet in this batch */ + clone = skb_clone(buf, GFP_ATOMIC); + if (!clone) + goto error; + + skb_trim(clone, packet_len); + usbnet_skb_return(dev, clone); + + skb_pull(buf, (packet_len + 3) & ~3); + } else { + skb_trim(buf, packet_len); + + if (s->current_rx_buf) { + usbnet_skb_return(dev, buf); + s->current_rx_buf = NULL; + return 0; + } + + return 1; + } + } + +error: + if (s->current_rx_buf) { + dev_kfree_skb_any(s->current_rx_buf); + s->current_rx_buf = NULL; + } + dev->net->stats.rx_errors++; + return 0; +} + +static struct sk_buff *vl600_tx_fixup(struct usbnet *dev, + struct sk_buff *skb, gfp_t flags) +{ + struct sk_buff *ret; + struct vl600_frame_hdr *frame; + struct vl600_pkt_hdr *packet; + static uint32_t serial = 1; + int orig_len = skb->len - sizeof(struct ethhdr); + int full_len = (skb->len + sizeof(struct vl600_frame_hdr) + 3) & ~3; + + frame = (struct vl600_frame_hdr *) skb->data; + if (skb->len > sizeof(*frame) && skb->len == le32_to_cpup(&frame->len)) + return skb; /* Already encapsulated? */ + + if (skb->len < sizeof(struct ethhdr)) + /* Drop, device can only deal with ethernet packets */ + return NULL; + + if (!skb_cloned(skb)) { + int headroom = skb_headroom(skb); + int tailroom = skb_tailroom(skb); + + if (tailroom >= full_len - skb->len - sizeof(*frame) && + headroom >= sizeof(*frame)) + /* There's enough head and tail room */ + goto encapsulate; + + if (headroom + tailroom + skb->len >= full_len) { + /* There's enough total room, just readjust */ + skb->data = memmove(skb->head + sizeof(*frame), + skb->data, skb->len); + skb_set_tail_pointer(skb, skb->len); + goto encapsulate; + } + } + + /* Alloc a new skb with the required size */ + ret = skb_copy_expand(skb, sizeof(struct vl600_frame_hdr), full_len - + skb->len - sizeof(struct vl600_frame_hdr), flags); + dev_kfree_skb_any(skb); + if (!ret) + return ret; + skb = ret; + +encapsulate: + /* Packet header is same size as ethernet packet header + * (sizeof(*packet) == sizeof(struct ethhdr)), additionally the + * h_proto field is in the same place so we just leave it alone and + * overwrite the remaining fields. + */ + packet = (struct vl600_pkt_hdr *) skb->data; + memset(&packet->dummy, 0, sizeof(packet->dummy)); + packet->len = cpu_to_le32(orig_len); + + frame = (struct vl600_frame_hdr *) skb_push(skb, sizeof(*frame)); + memset(frame, 0, sizeof(*frame)); + frame->len = cpu_to_le32(full_len); + frame->serial = cpu_to_le32(serial++); + frame->pkt_cnt = cpu_to_le32(1); + + if (skb->len < full_len) /* Pad */ + skb_put(skb, full_len - skb->len); + + return skb; +} + +static const struct driver_info vl600_info = { + .description = "LG VL600 modem", + .flags = FLAG_ETHER | FLAG_RX_ASSEMBLE, + .bind = vl600_bind, + .unbind = vl600_unbind, + .status = usbnet_cdc_status, + .rx_fixup = vl600_rx_fixup, + .tx_fixup = vl600_tx_fixup, +}; + +static const struct usb_device_id products[] = { + { + USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM, + USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE), + .driver_info = (unsigned long) &vl600_info, + }, + {}, /* End */ +}; +MODULE_DEVICE_TABLE(usb, products); + +static struct usb_driver lg_vl600_driver = { + .name = "lg-vl600", + .id_table = products, + .probe = usbnet_probe, + .disconnect = usbnet_disconnect, + .suspend = usbnet_suspend, + .resume = usbnet_resume, +}; + +static int __init vl600_init(void) +{ + return usb_register(&lg_vl600_driver); +} +module_init(vl600_init); + +static void __exit vl600_exit(void) +{ + usb_deregister(&lg_vl600_driver); +} +module_exit(vl600_exit); + +MODULE_AUTHOR("Anrzej Zaborowski"); +MODULE_DESCRIPTION("LG-VL600 modem's ethernet link"); +MODULE_LICENSE("GPL"); diff --git a/drivers/net/usb/net1080.c b/drivers/net/usb/net1080.c index ba72a7281cb..01db4602a39 100644 --- a/drivers/net/usb/net1080.c +++ b/drivers/net/usb/net1080.c @@ -560,7 +560,7 @@ static int net1080_bind(struct usbnet *dev, struct usb_interface *intf) static const struct driver_info net1080_info = { .description = "NetChip TurboCONNECT", - .flags = FLAG_FRAMING_NC, + .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_NC, .bind = net1080_bind, .reset = net1080_reset, .check_connect = net1080_check_connect, diff --git a/drivers/net/usb/plusb.c b/drivers/net/usb/plusb.c index 08ad269f6b4..823c5375130 100644 --- a/drivers/net/usb/plusb.c +++ b/drivers/net/usb/plusb.c @@ -96,7 +96,7 @@ static int pl_reset(struct usbnet *dev) static const struct driver_info prolific_info = { .description = "Prolific PL-2301/PL-2302", - .flags = FLAG_NO_SETINT, + .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT, /* some PL-2302 versions seem to fail usb_set_interface() */ .reset = pl_reset, }; diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c index dd8a4adf48c..5994a25c56a 100644 --- a/drivers/net/usb/rndis_host.c +++ b/drivers/net/usb/rndis_host.c @@ -573,7 +573,7 @@ EXPORT_SYMBOL_GPL(rndis_tx_fixup); static const struct driver_info rndis_info = { .description = "RNDIS device", - .flags = FLAG_ETHER | FLAG_FRAMING_RN | FLAG_NO_SETINT, + .flags = FLAG_ETHER | FLAG_POINTTOPOINT | FLAG_FRAMING_RN | FLAG_NO_SETINT, .bind = rndis_bind, .unbind = rndis_unbind, .status = rndis_status, diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 95c41d56631..069c1cf0fdf 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c @@ -387,8 +387,12 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) { if (dev->driver_info->rx_fixup && - !dev->driver_info->rx_fixup (dev, skb)) - goto error; + !dev->driver_info->rx_fixup (dev, skb)) { + /* With RX_ASSEMBLE, rx_fixup() must update counters */ + if (!(dev->driver_info->flags & FLAG_RX_ASSEMBLE)) + dev->net->stats.rx_errors++; + goto done; + } // else network stack removes extra byte if we forced a short packet if (skb->len) { @@ -401,8 +405,8 @@ static inline void rx_process (struct usbnet *dev, struct sk_buff *skb) } netif_dbg(dev, rx_err, dev->net, "drop\n"); -error: dev->net->stats.rx_errors++; +done: skb_queue_tail(&dev->done, skb); } @@ -1376,7 +1380,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) // else "eth%d" when there's reasonable doubt. userspace // can rename the link if it knows better. if ((dev->driver_info->flags & FLAG_ETHER) != 0 && - (net->dev_addr [0] & 0x02) == 0) + ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 || + (net->dev_addr [0] & 0x02) == 0)) strcpy (net->name, "eth%d"); /* WLAN devices should always be named "wlan%d" */ if ((dev->driver_info->flags & FLAG_WLAN) != 0) diff --git a/drivers/net/usb/zaurus.c b/drivers/net/usb/zaurus.c index 3eb0b167b5b..241756e0e86 100644 --- a/drivers/net/usb/zaurus.c +++ b/drivers/net/usb/zaurus.c @@ -102,7 +102,7 @@ static int always_connected (struct usbnet *dev) static const struct driver_info zaurus_sl5x00_info = { .description = "Sharp Zaurus SL-5x00", - .flags = FLAG_FRAMING_Z, + .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, .check_connect = always_connected, .bind = zaurus_bind, .unbind = usbnet_cdc_unbind, @@ -112,7 +112,7 @@ static const struct driver_info zaurus_sl5x00_info = { static const struct driver_info zaurus_pxa_info = { .description = "Sharp Zaurus, PXA-2xx based", - .flags = FLAG_FRAMING_Z, + .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, .check_connect = always_connected, .bind = zaurus_bind, .unbind = usbnet_cdc_unbind, @@ -122,7 +122,7 @@ static const struct driver_info zaurus_pxa_info = { static const struct driver_info olympus_mxl_info = { .description = "Olympus R1000", - .flags = FLAG_FRAMING_Z, + .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, .check_connect = always_connected, .bind = zaurus_bind, .unbind = usbnet_cdc_unbind, @@ -258,7 +258,7 @@ bad_desc: static const struct driver_info bogus_mdlm_info = { .description = "pseudo-MDLM (BLAN) device", - .flags = FLAG_FRAMING_Z, + .flags = FLAG_POINTTOPOINT | FLAG_FRAMING_Z, .check_connect = always_connected, .tx_fixup = zaurus_tx_fixup, .bind = blan_mdlm_bind, diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 524825720a0..dddb85de622 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1048,6 +1048,8 @@ static int ath9k_start(struct ieee80211_hw *hw) "Starting driver with initial channel: %d MHz\n", curchan->center_freq); + ath9k_ps_wakeup(sc); + mutex_lock(&sc->mutex); /* setup initial channel */ @@ -1143,6 +1145,8 @@ static int ath9k_start(struct ieee80211_hw *hw) mutex_unlock: mutex_unlock(&sc->mutex); + ath9k_ps_restore(sc); + return r; } diff --git a/drivers/net/wireless/ath/carl9170/carl9170.h b/drivers/net/wireless/ath/carl9170/carl9170.h index c6a5fae634a..9cad061cc1d 100644 --- a/drivers/net/wireless/ath/carl9170/carl9170.h +++ b/drivers/net/wireless/ath/carl9170/carl9170.h @@ -443,6 +443,7 @@ struct carl9170_ba_stats { u8 ampdu_len; u8 ampdu_ack_len; bool clear; + bool req; }; struct carl9170_sta_info { diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c index ede3d7e5a04..89fe60accf8 100644 --- a/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c @@ -1355,6 +1355,7 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw, tid_info = rcu_dereference(sta_info->agg[tid]); sta_info->stats[tid].clear = true; + sta_info->stats[tid].req = false; if (tid_info) { bitmap_zero(tid_info->bitmap, CARL9170_BAW_SIZE); diff --git a/drivers/net/wireless/ath/carl9170/tx.c b/drivers/net/wireless/ath/carl9170/tx.c index 0ef70b6fc51..cb70ed7ec5c 100644 --- a/drivers/net/wireless/ath/carl9170/tx.c +++ b/drivers/net/wireless/ath/carl9170/tx.c @@ -383,6 +383,7 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, if (sta_info->stats[tid].clear) { sta_info->stats[tid].clear = false; + sta_info->stats[tid].req = false; sta_info->stats[tid].ampdu_len = 0; sta_info->stats[tid].ampdu_ack_len = 0; } @@ -391,10 +392,16 @@ static void carl9170_tx_status_process_ampdu(struct ar9170 *ar, if (txinfo->status.rates[0].count == 1) sta_info->stats[tid].ampdu_ack_len++; + if (!(txinfo->flags & IEEE80211_TX_STAT_ACK)) + sta_info->stats[tid].req = true; + if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) { super->s.rix = sta_info->stats[tid].ampdu_len; super->s.cnt = sta_info->stats[tid].ampdu_ack_len; txinfo->flags |= IEEE80211_TX_STAT_AMPDU; + if (sta_info->stats[tid].req) + txinfo->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; + sta_info->stats[tid].clear = true; } spin_unlock_bh(&tid_info->lock); diff --git a/drivers/net/wireless/iwlegacy/iwl-core.c b/drivers/net/wireless/iwlegacy/iwl-core.c index d418b647be8..a209a0e76bf 100644 --- a/drivers/net/wireless/iwlegacy/iwl-core.c +++ b/drivers/net/wireless/iwlegacy/iwl-core.c @@ -1805,6 +1805,15 @@ iwl_legacy_mac_change_interface(struct ieee80211_hw *hw, mutex_lock(&priv->mutex); + if (!ctx->vif || !iwl_legacy_is_ready_rf(priv)) { + /* + * Huh? But wait ... this can maybe happen when + * we're in the middle of a firmware restart! + */ + err = -EBUSY; + goto out; + } + interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes; if (!(interface_modes & BIT(newtype))) { @@ -1832,6 +1841,7 @@ iwl_legacy_mac_change_interface(struct ieee80211_hw *hw, /* success */ iwl_legacy_teardown_interface(priv, vif, true); vif->type = newtype; + vif->p2p = newp2p; err = iwl_legacy_setup_interface(priv, ctx); WARN_ON(err); /* diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c index ab87e1b7352..28eb3d885ba 100644 --- a/drivers/net/wireless/iwlegacy/iwl3945-base.c +++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c @@ -93,6 +93,7 @@ MODULE_LICENSE("GPL"); struct iwl_mod_params iwl3945_mod_params = { .sw_crypto = 1, .restart_fw = 1, + .disable_hw_scan = 1, /* the rest are 0 by default */ }; @@ -3960,8 +3961,7 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e * "the hard way", rather than using device's scan. */ if (iwl3945_mod_params.disable_hw_scan) { - dev_printk(KERN_DEBUG, &(pdev->dev), - "sw scan support is deprecated\n"); + IWL_DEBUG_INFO(priv, "Disabling hw_scan\n"); iwl3945_hw_ops.hw_scan = NULL; } @@ -4280,8 +4280,7 @@ MODULE_PARM_DESC(swcrypto, "using software crypto (default 1 [software])"); module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, S_IRUGO); -MODULE_PARM_DESC(disable_hw_scan, - "disable hardware scanning (default 0) (deprecated)"); +MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 1)"); #ifdef CONFIG_IWLWIFI_LEGACY_DEBUG module_param_named(debug, iwlegacy_debug_level, uint, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "debug output mask"); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 4e368657a83..37509d01991 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c @@ -730,8 +730,12 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x825b), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x935a), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x050d, 0x935b), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Buffalo */ { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x0411, 0x016f), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Conceptronic */ { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -818,6 +822,7 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Pegatron */ { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, + { USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Philips */ { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Planex */ @@ -899,6 +904,8 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Sitecom */ { USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) }, + /* Toshiba */ + { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zinwell */ { USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif @@ -961,7 +968,6 @@ static struct usb_device_id rt2800usb_device_table[] = { { USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Planex */ { USB_DEVICE(0x2019, 0x5201), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, @@ -975,8 +981,6 @@ static struct usb_device_id rt2800usb_device_table[] = { /* Sweex */ { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Toshiba */ - { USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) }, /* Zyxel */ { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, #endif diff --git a/drivers/pcmcia/pxa2xx_colibri.c b/drivers/pcmcia/pxa2xx_colibri.c index a52039564e7..443cb7fc872 100644 --- a/drivers/pcmcia/pxa2xx_colibri.c +++ b/drivers/pcmcia/pxa2xx_colibri.c @@ -34,14 +34,24 @@ #define COLIBRI320_DETECT_GPIO 81 #define COLIBRI320_READY_GPIO 29 -static struct { - int reset_gpio; - int ppen_gpio; - int bvd1_gpio; - int bvd2_gpio; - int detect_gpio; - int ready_gpio; -} colibri_pcmcia_gpio; +enum { + DETECT = 0, + READY = 1, + BVD1 = 2, + BVD2 = 3, + PPEN = 4, + RESET = 5, +}; + +/* Contents of this array are configured on-the-fly in init function */ +static struct gpio colibri_pcmcia_gpios[] = { + { 0, GPIOF_IN, "PCMCIA Detect" }, + { 0, GPIOF_IN, "PCMCIA Ready" }, + { 0, GPIOF_IN, "PCMCIA BVD1" }, + { 0, GPIOF_IN, "PCMCIA BVD2" }, + { 0, GPIOF_INIT_LOW, "PCMCIA PPEN" }, + { 0, GPIOF_INIT_HIGH,"PCMCIA Reset" }, +}; static struct pcmcia_irqs colibri_irqs[] = { { @@ -54,88 +64,42 @@ static int colibri_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret; - ret = gpio_request(colibri_pcmcia_gpio.detect_gpio, "DETECT"); + ret = gpio_request_array(colibri_pcmcia_gpios, + ARRAY_SIZE(colibri_pcmcia_gpios)); if (ret) goto err1; - ret = gpio_direction_input(colibri_pcmcia_gpio.detect_gpio); - if (ret) - goto err2; - - ret = gpio_request(colibri_pcmcia_gpio.ready_gpio, "READY"); - if (ret) - goto err2; - ret = gpio_direction_input(colibri_pcmcia_gpio.ready_gpio); - if (ret) - goto err3; - ret = gpio_request(colibri_pcmcia_gpio.bvd1_gpio, "BVD1"); - if (ret) - goto err3; - ret = gpio_direction_input(colibri_pcmcia_gpio.bvd1_gpio); - if (ret) - goto err4; + colibri_irqs[0].irq = gpio_to_irq(colibri_pcmcia_gpios[DETECT].gpio); + skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpios[READY].gpio); - ret = gpio_request(colibri_pcmcia_gpio.bvd2_gpio, "BVD2"); - if (ret) - goto err4; - ret = gpio_direction_input(colibri_pcmcia_gpio.bvd2_gpio); - if (ret) - goto err5; - - ret = gpio_request(colibri_pcmcia_gpio.ppen_gpio, "PPEN"); - if (ret) - goto err5; - ret = gpio_direction_output(colibri_pcmcia_gpio.ppen_gpio, 0); - if (ret) - goto err6; - - ret = gpio_request(colibri_pcmcia_gpio.reset_gpio, "RESET"); - if (ret) - goto err6; - ret = gpio_direction_output(colibri_pcmcia_gpio.reset_gpio, 1); + ret = soc_pcmcia_request_irqs(skt, colibri_irqs, + ARRAY_SIZE(colibri_irqs)); if (ret) - goto err7; - - colibri_irqs[0].irq = gpio_to_irq(colibri_pcmcia_gpio.detect_gpio); - skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpio.ready_gpio); + goto err2; - return soc_pcmcia_request_irqs(skt, colibri_irqs, - ARRAY_SIZE(colibri_irqs)); + return ret; -err7: - gpio_free(colibri_pcmcia_gpio.detect_gpio); -err6: - gpio_free(colibri_pcmcia_gpio.ready_gpio); -err5: - gpio_free(colibri_pcmcia_gpio.bvd1_gpio); -err4: - gpio_free(colibri_pcmcia_gpio.bvd2_gpio); -err3: - gpio_free(colibri_pcmcia_gpio.reset_gpio); err2: - gpio_free(colibri_pcmcia_gpio.ppen_gpio); + gpio_free_array(colibri_pcmcia_gpios, + ARRAY_SIZE(colibri_pcmcia_gpios)); err1: return ret; } static void colibri_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - gpio_free(colibri_pcmcia_gpio.detect_gpio); - gpio_free(colibri_pcmcia_gpio.ready_gpio); - gpio_free(colibri_pcmcia_gpio.bvd1_gpio); - gpio_free(colibri_pcmcia_gpio.bvd2_gpio); - gpio_free(colibri_pcmcia_gpio.reset_gpio); - gpio_free(colibri_pcmcia_gpio.ppen_gpio); + gpio_free_array(colibri_pcmcia_gpios, + ARRAY_SIZE(colibri_pcmcia_gpios)); } static void colibri_pcmcia_socket_state(struct soc_pcmcia_socket *skt, struct pcmcia_state *state) { - state->detect = !!gpio_get_value(colibri_pcmcia_gpio.detect_gpio); - state->ready = !!gpio_get_value(colibri_pcmcia_gpio.ready_gpio); - state->bvd1 = !!gpio_get_value(colibri_pcmcia_gpio.bvd1_gpio); - state->bvd2 = !!gpio_get_value(colibri_pcmcia_gpio.bvd2_gpio); + state->detect = !!gpio_get_value(colibri_pcmcia_gpios[DETECT].gpio); + state->ready = !!gpio_get_value(colibri_pcmcia_gpios[READY].gpio); + state->bvd1 = !!gpio_get_value(colibri_pcmcia_gpios[BVD1].gpio); + state->bvd2 = !!gpio_get_value(colibri_pcmcia_gpios[BVD2].gpio); state->wrprot = 0; state->vs_3v = 1; state->vs_Xv = 0; @@ -145,9 +109,10 @@ static int colibri_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { - gpio_set_value(colibri_pcmcia_gpio.ppen_gpio, + gpio_set_value(colibri_pcmcia_gpios[PPEN].gpio, !(state->Vcc == 33 && state->Vpp < 50)); - gpio_set_value(colibri_pcmcia_gpio.reset_gpio, state->flags & SS_RESET); + gpio_set_value(colibri_pcmcia_gpios[RESET].gpio, + state->flags & SS_RESET); return 0; } @@ -190,20 +155,20 @@ static int __init colibri_pcmcia_init(void) /* Colibri PXA270 */ if (machine_is_colibri()) { - colibri_pcmcia_gpio.reset_gpio = COLIBRI270_RESET_GPIO; - colibri_pcmcia_gpio.ppen_gpio = COLIBRI270_PPEN_GPIO; - colibri_pcmcia_gpio.bvd1_gpio = COLIBRI270_BVD1_GPIO; - colibri_pcmcia_gpio.bvd2_gpio = COLIBRI270_BVD2_GPIO; - colibri_pcmcia_gpio.detect_gpio = COLIBRI270_DETECT_GPIO; - colibri_pcmcia_gpio.ready_gpio = COLIBRI270_READY_GPIO; + colibri_pcmcia_gpios[RESET].gpio = COLIBRI270_RESET_GPIO; + colibri_pcmcia_gpios[PPEN].gpio = COLIBRI270_PPEN_GPIO; + colibri_pcmcia_gpios[BVD1].gpio = COLIBRI270_BVD1_GPIO; + colibri_pcmcia_gpios[BVD2].gpio = COLIBRI270_BVD2_GPIO; + colibri_pcmcia_gpios[DETECT].gpio = COLIBRI270_DETECT_GPIO; + colibri_pcmcia_gpios[READY].gpio = COLIBRI270_READY_GPIO; /* Colibri PXA320 */ } else if (machine_is_colibri320()) { - colibri_pcmcia_gpio.reset_gpio = COLIBRI320_RESET_GPIO; - colibri_pcmcia_gpio.ppen_gpio = COLIBRI320_PPEN_GPIO; - colibri_pcmcia_gpio.bvd1_gpio = COLIBRI320_BVD1_GPIO; - colibri_pcmcia_gpio.bvd2_gpio = COLIBRI320_BVD2_GPIO; - colibri_pcmcia_gpio.detect_gpio = COLIBRI320_DETECT_GPIO; - colibri_pcmcia_gpio.ready_gpio = COLIBRI320_READY_GPIO; + colibri_pcmcia_gpios[RESET].gpio = COLIBRI320_RESET_GPIO; + colibri_pcmcia_gpios[PPEN].gpio = COLIBRI320_PPEN_GPIO; + colibri_pcmcia_gpios[BVD1].gpio = COLIBRI320_BVD1_GPIO; + colibri_pcmcia_gpios[BVD2].gpio = COLIBRI320_BVD2_GPIO; + colibri_pcmcia_gpios[DETECT].gpio = COLIBRI320_DETECT_GPIO; + colibri_pcmcia_gpios[READY].gpio = COLIBRI320_READY_GPIO; } ret = platform_device_add_data(colibri_pcmcia_device, diff --git a/drivers/pcmcia/pxa2xx_palmld.c b/drivers/pcmcia/pxa2xx_palmld.c index 6fb6f7f0672..69f73670949 100644 --- a/drivers/pcmcia/pxa2xx_palmld.c +++ b/drivers/pcmcia/pxa2xx_palmld.c @@ -4,7 +4,7 @@ * Driver for Palm LifeDrive PCMCIA * * Copyright (C) 2006 Alex Osborne <ato@meshy.org> - * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com> + * Copyright (C) 2007-2011 Marek Vasut <marek.vasut@gmail.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 @@ -20,49 +20,27 @@ #include <mach/palmld.h> #include "soc_common.h" +static struct gpio palmld_pcmcia_gpios[] = { + { GPIO_NR_PALMLD_PCMCIA_POWER, GPIOF_INIT_LOW, "PCMCIA Power" }, + { GPIO_NR_PALMLD_PCMCIA_RESET, GPIOF_INIT_HIGH,"PCMCIA Reset" }, + { GPIO_NR_PALMLD_PCMCIA_READY, GPIOF_IN, "PCMCIA Ready" }, +}; + static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret; - ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_POWER, "PCMCIA PWR"); - if (ret) - goto err1; - ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_POWER, 0); - if (ret) - goto err2; - - ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_RESET, "PCMCIA RST"); - if (ret) - goto err2; - ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_RESET, 1); - if (ret) - goto err3; - - ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_READY, "PCMCIA RDY"); - if (ret) - goto err3; - ret = gpio_direction_input(GPIO_NR_PALMLD_PCMCIA_READY); - if (ret) - goto err4; + ret = gpio_request_array(palmld_pcmcia_gpios, + ARRAY_SIZE(palmld_pcmcia_gpios)); skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY); - return 0; -err4: - gpio_free(GPIO_NR_PALMLD_PCMCIA_READY); -err3: - gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET); -err2: - gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER); -err1: return ret; } static void palmld_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - gpio_free(GPIO_NR_PALMLD_PCMCIA_READY); - gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET); - gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER); + gpio_free_array(palmld_pcmcia_gpios, ARRAY_SIZE(palmld_pcmcia_gpios)); } static void palmld_pcmcia_socket_state(struct soc_pcmcia_socket *skt, diff --git a/drivers/pcmcia/pxa2xx_palmtc.c b/drivers/pcmcia/pxa2xx_palmtc.c index 459a232d66b..d0ad6a76bbd 100644 --- a/drivers/pcmcia/pxa2xx_palmtc.c +++ b/drivers/pcmcia/pxa2xx_palmtc.c @@ -4,7 +4,7 @@ * Driver for Palm Tungsten|C PCMCIA * * Copyright (C) 2008 Alex Osborne <ato@meshy.org> - * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com> + * Copyright (C) 2009-2011 Marek Vasut <marek.vasut@gmail.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 @@ -21,79 +21,30 @@ #include <mach/palmtc.h> #include "soc_common.h" +static struct gpio palmtc_pcmcia_gpios[] = { + { GPIO_NR_PALMTC_PCMCIA_POWER1, GPIOF_INIT_LOW, "PCMCIA Power 1" }, + { GPIO_NR_PALMTC_PCMCIA_POWER2, GPIOF_INIT_LOW, "PCMCIA Power 2" }, + { GPIO_NR_PALMTC_PCMCIA_POWER3, GPIOF_INIT_LOW, "PCMCIA Power 3" }, + { GPIO_NR_PALMTC_PCMCIA_RESET, GPIOF_INIT_HIGH,"PCMCIA Reset" }, + { GPIO_NR_PALMTC_PCMCIA_READY, GPIOF_IN, "PCMCIA Ready" }, + { GPIO_NR_PALMTC_PCMCIA_PWRREADY, GPIOF_IN, "PCMCIA Power Ready" }, +}; + static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret; - ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER1, "PCMCIA PWR1"); - if (ret) - goto err1; - ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER1, 0); - if (ret) - goto err2; - - ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER2, "PCMCIA PWR2"); - if (ret) - goto err2; - ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER2, 0); - if (ret) - goto err3; - - ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER3, "PCMCIA PWR3"); - if (ret) - goto err3; - ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER3, 0); - if (ret) - goto err4; - - ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_RESET, "PCMCIA RST"); - if (ret) - goto err4; - ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_RESET, 1); - if (ret) - goto err5; - - ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_READY, "PCMCIA RDY"); - if (ret) - goto err5; - ret = gpio_direction_input(GPIO_NR_PALMTC_PCMCIA_READY); - if (ret) - goto err6; - - ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_PWRREADY, "PCMCIA PWRRDY"); - if (ret) - goto err6; - ret = gpio_direction_input(GPIO_NR_PALMTC_PCMCIA_PWRREADY); - if (ret) - goto err7; + ret = gpio_request_array(palmtc_pcmcia_gpios, + ARRAY_SIZE(palmtc_pcmcia_gpios)); skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY); - return 0; -err7: - gpio_free(GPIO_NR_PALMTC_PCMCIA_PWRREADY); -err6: - gpio_free(GPIO_NR_PALMTC_PCMCIA_READY); -err5: - gpio_free(GPIO_NR_PALMTC_PCMCIA_RESET); -err4: - gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER3); -err3: - gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER2); -err2: - gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER1); -err1: return ret; } static void palmtc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - gpio_free(GPIO_NR_PALMTC_PCMCIA_PWRREADY); - gpio_free(GPIO_NR_PALMTC_PCMCIA_READY); - gpio_free(GPIO_NR_PALMTC_PCMCIA_RESET); - gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER3); - gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER2); - gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER1); + gpio_free_array(palmtc_pcmcia_gpios, ARRAY_SIZE(palmtc_pcmcia_gpios)); } static void palmtc_pcmcia_socket_state(struct soc_pcmcia_socket *skt, diff --git a/drivers/pcmcia/pxa2xx_palmtx.c b/drivers/pcmcia/pxa2xx_palmtx.c index b07b247a399..1a258045040 100644 --- a/drivers/pcmcia/pxa2xx_palmtx.c +++ b/drivers/pcmcia/pxa2xx_palmtx.c @@ -3,7 +3,7 @@ * * Driver for Palm T|X PCMCIA * - * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com> + * Copyright (C) 2007-2011 Marek Vasut <marek.vasut@gmail.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 @@ -13,67 +13,34 @@ #include <linux/module.h> #include <linux/platform_device.h> +#include <linux/gpio.h> #include <asm/mach-types.h> - -#include <mach/gpio.h> #include <mach/palmtx.h> - #include "soc_common.h" +static struct gpio palmtx_pcmcia_gpios[] = { + { GPIO_NR_PALMTX_PCMCIA_POWER1, GPIOF_INIT_LOW, "PCMCIA Power 1" }, + { GPIO_NR_PALMTX_PCMCIA_POWER2, GPIOF_INIT_LOW, "PCMCIA Power 2" }, + { GPIO_NR_PALMTX_PCMCIA_RESET, GPIOF_INIT_HIGH,"PCMCIA Reset" }, + { GPIO_NR_PALMTX_PCMCIA_READY, GPIOF_IN, "PCMCIA Ready" }, +}; + static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { int ret; - ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER1, "PCMCIA PWR1"); - if (ret) - goto err1; - ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER1, 0); - if (ret) - goto err2; - - ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER2, "PCMCIA PWR2"); - if (ret) - goto err2; - ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER2, 0); - if (ret) - goto err3; - - ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_RESET, "PCMCIA RST"); - if (ret) - goto err3; - ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_RESET, 1); - if (ret) - goto err4; - - ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_READY, "PCMCIA RDY"); - if (ret) - goto err4; - ret = gpio_direction_input(GPIO_NR_PALMTX_PCMCIA_READY); - if (ret) - goto err5; + ret = gpio_request_array(palmtx_pcmcia_gpios, + ARRAY_SIZE(palmtx_pcmcia_gpios)); skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMTX_PCMCIA_READY); - return 0; -err5: - gpio_free(GPIO_NR_PALMTX_PCMCIA_READY); -err4: - gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET); -err3: - gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2); -err2: - gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1); -err1: return ret; } static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - gpio_free(GPIO_NR_PALMTX_PCMCIA_READY); - gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET); - gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2); - gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1); + gpio_free_array(palmtx_pcmcia_gpios, ARRAY_SIZE(palmtx_pcmcia_gpios)); } static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt, diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c index 55627eccee8..435002dfc3c 100644 --- a/drivers/pcmcia/pxa2xx_vpac270.c +++ b/drivers/pcmcia/pxa2xx_vpac270.c @@ -3,8 +3,7 @@ * * Driver for Voipac PXA270 PCMCIA and CF sockets * - * Copyright (C) 2010 - * Marek Vasut <marek.vasut@gmail.com> + * Copyright (C) 2010-2011 Marek Vasut <marek.vasut@gmail.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 @@ -22,6 +21,19 @@ #include "soc_common.h" +static struct gpio vpac270_pcmcia_gpios[] = { + { GPIO84_VPAC270_PCMCIA_CD, GPIOF_IN, "PCMCIA Card Detect" }, + { GPIO35_VPAC270_PCMCIA_RDY, GPIOF_IN, "PCMCIA Ready" }, + { GPIO107_VPAC270_PCMCIA_PPEN, GPIOF_INIT_LOW, "PCMCIA PPEN" }, + { GPIO11_VPAC270_PCMCIA_RESET, GPIOF_INIT_LOW, "PCMCIA Reset" }, +}; + +static struct gpio vpac270_cf_gpios[] = { + { GPIO17_VPAC270_CF_CD, GPIOF_IN, "CF Card Detect" }, + { GPIO12_VPAC270_CF_RDY, GPIOF_IN, "CF Ready" }, + { GPIO16_VPAC270_CF_RESET, GPIOF_INIT_LOW, "CF Reset" }, +}; + static struct pcmcia_irqs cd_irqs[] = { { .sock = 0, @@ -40,96 +52,34 @@ static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) int ret; if (skt->nr == 0) { - ret = gpio_request(GPIO84_VPAC270_PCMCIA_CD, "PCMCIA CD"); - if (ret) - goto err1; - ret = gpio_direction_input(GPIO84_VPAC270_PCMCIA_CD); - if (ret) - goto err2; - - ret = gpio_request(GPIO35_VPAC270_PCMCIA_RDY, "PCMCIA RDY"); - if (ret) - goto err2; - ret = gpio_direction_input(GPIO35_VPAC270_PCMCIA_RDY); - if (ret) - goto err3; - - ret = gpio_request(GPIO107_VPAC270_PCMCIA_PPEN, "PCMCIA PPEN"); - if (ret) - goto err3; - ret = gpio_direction_output(GPIO107_VPAC270_PCMCIA_PPEN, 0); - if (ret) - goto err4; - - ret = gpio_request(GPIO11_VPAC270_PCMCIA_RESET, "PCMCIA RESET"); - if (ret) - goto err4; - ret = gpio_direction_output(GPIO11_VPAC270_PCMCIA_RESET, 0); - if (ret) - goto err5; + ret = gpio_request_array(vpac270_pcmcia_gpios, + ARRAY_SIZE(vpac270_pcmcia_gpios)); skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY); - return soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1); - -err5: - gpio_free(GPIO11_VPAC270_PCMCIA_RESET); -err4: - gpio_free(GPIO107_VPAC270_PCMCIA_PPEN); -err3: - gpio_free(GPIO35_VPAC270_PCMCIA_RDY); -err2: - gpio_free(GPIO84_VPAC270_PCMCIA_CD); -err1: - return ret; - + if (!ret) + ret = soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1); } else { - ret = gpio_request(GPIO17_VPAC270_CF_CD, "CF CD"); - if (ret) - goto err6; - ret = gpio_direction_input(GPIO17_VPAC270_CF_CD); - if (ret) - goto err7; - - ret = gpio_request(GPIO12_VPAC270_CF_RDY, "CF RDY"); - if (ret) - goto err7; - ret = gpio_direction_input(GPIO12_VPAC270_CF_RDY); - if (ret) - goto err8; - - ret = gpio_request(GPIO16_VPAC270_CF_RESET, "CF RESET"); - if (ret) - goto err8; - ret = gpio_direction_output(GPIO16_VPAC270_CF_RESET, 0); - if (ret) - goto err9; + ret = gpio_request_array(vpac270_cf_gpios, + ARRAY_SIZE(vpac270_cf_gpios)); skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY); - return soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1); - -err9: - gpio_free(GPIO16_VPAC270_CF_RESET); -err8: - gpio_free(GPIO12_VPAC270_CF_RDY); -err7: - gpio_free(GPIO17_VPAC270_CF_CD); -err6: - return ret; - + if (!ret) + ret = soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1); } + + return ret; } static void vpac270_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) { - gpio_free(GPIO11_VPAC270_PCMCIA_RESET); - gpio_free(GPIO107_VPAC270_PCMCIA_PPEN); - gpio_free(GPIO35_VPAC270_PCMCIA_RDY); - gpio_free(GPIO84_VPAC270_PCMCIA_CD); - gpio_free(GPIO16_VPAC270_CF_RESET); - gpio_free(GPIO12_VPAC270_CF_RDY); - gpio_free(GPIO17_VPAC270_CF_CD); + if (skt->nr == 0) + gpio_request_array(vpac270_pcmcia_gpios, + ARRAY_SIZE(vpac270_pcmcia_gpios)); + else + gpio_request_array(vpac270_cf_gpios, + ARRAY_SIZE(vpac270_cf_gpios)); } static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt, diff --git a/drivers/rtc/rtc-mrst.c b/drivers/rtc/rtc-mrst.c index b86bc328463..332a2c4a891 100644 --- a/drivers/rtc/rtc-mrst.c +++ b/drivers/rtc/rtc-mrst.c @@ -319,7 +319,7 @@ static irqreturn_t mrst_rtc_irq(int irq, void *p) return IRQ_NONE; } -static int __init +static int __devinit vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq) { int retval = 0; @@ -391,7 +391,7 @@ static void rtc_mrst_do_shutdown(void) spin_unlock_irq(&rtc_lock); } -static void __exit rtc_mrst_do_remove(struct device *dev) +static void __devexit rtc_mrst_do_remove(struct device *dev) { struct mrst_rtc *mrst = dev_get_drvdata(dev); struct resource *iomem; @@ -500,14 +500,14 @@ static inline int mrst_poweroff(struct device *dev) #endif -static int __init vrtc_mrst_platform_probe(struct platform_device *pdev) +static int __devinit vrtc_mrst_platform_probe(struct platform_device *pdev) { return vrtc_mrst_do_probe(&pdev->dev, platform_get_resource(pdev, IORESOURCE_MEM, 0), platform_get_irq(pdev, 0)); } -static int __exit vrtc_mrst_platform_remove(struct platform_device *pdev) +static int __devexit vrtc_mrst_platform_remove(struct platform_device *pdev) { rtc_mrst_do_remove(&pdev->dev); return 0; @@ -525,7 +525,7 @@ MODULE_ALIAS("platform:vrtc_mrst"); static struct platform_driver vrtc_mrst_platform_driver = { .probe = vrtc_mrst_platform_probe, - .remove = __exit_p(vrtc_mrst_platform_remove), + .remove = __devexit_p(vrtc_mrst_platform_remove), .shutdown = vrtc_mrst_platform_shutdown, .driver = { .name = (char *) driver_name, diff --git a/drivers/scsi/ultrastor.c b/drivers/scsi/ultrastor.c index 0571ef9639c..9f4b58b7daa 100644 --- a/drivers/scsi/ultrastor.c +++ b/drivers/scsi/ultrastor.c @@ -138,6 +138,7 @@ #include <linux/spinlock.h> #include <linux/stat.h> #include <linux/bitops.h> +#include <linux/delay.h> #include <asm/io.h> #include <asm/system.h> diff --git a/drivers/sh/intc/internals.h b/drivers/sh/intc/internals.h index df36a421e67..5b934851efa 100644 --- a/drivers/sh/intc/internals.h +++ b/drivers/sh/intc/internals.h @@ -86,7 +86,7 @@ enum { MODE_ENABLE_REG = 0, /* Bit(s) set -> interrupt enabled */ static inline struct intc_desc_int *get_intc_desc(unsigned int irq) { - struct irq_chip *chip = get_irq_chip(irq); + struct irq_chip *chip = irq_get_chip(irq); return container_of(chip, struct intc_desc_int, chip); } @@ -103,7 +103,7 @@ static inline void activate_irq(int irq) set_irq_flags(irq, IRQF_VALID); #else /* same effect on other architectures */ - set_irq_noprobe(irq); + irq_set_noprobe(irq); #endif } diff --git a/drivers/staging/altera-stapl/altera-jtag.c b/drivers/staging/altera-stapl/altera-jtag.c index 6b633b179a7..876308858b8 100644 --- a/drivers/staging/altera-stapl/altera-jtag.c +++ b/drivers/staging/altera-stapl/altera-jtag.c @@ -23,6 +23,7 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#include <linux/delay.h> #include <linux/firmware.h> #include <linux/slab.h> #include <staging/altera.h> diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c index 428f4fe0b5f..0ad32888091 100644 --- a/drivers/tty/n_tty.c +++ b/drivers/tty/n_tty.c @@ -95,6 +95,7 @@ static void n_tty_set_room(struct tty_struct *tty) { /* tty->read_cnt is not read locked ? */ int left = N_TTY_BUF_SIZE - tty->read_cnt - 1; + int old_left; /* * If we are doing input canonicalization, and there are no @@ -104,7 +105,12 @@ static void n_tty_set_room(struct tty_struct *tty) */ if (left <= 0) left = tty->icanon && !tty->canon_data; + old_left = tty->receive_room; tty->receive_room = left; + + /* Did this open up the receive buffer? We may need to flip */ + if (left && !old_left) + schedule_work(&tty->buf.work); } static void put_tty_queue_nolock(unsigned char c, struct tty_struct *tty) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index e1aee37270f..80484af781e 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -1506,7 +1506,7 @@ config SERIAL_BCM63XX_CONSOLE config SERIAL_GRLIB_GAISLER_APBUART tristate "GRLIB APBUART serial support" - depends on OF + depends on OF && SPARC select SERIAL_CORE ---help--- Add support for the GRLIB APBUART serial port. diff --git a/drivers/tty/serial/apbuart.c b/drivers/tty/serial/apbuart.c index 1ab999b04ef..19a943693e4 100644 --- a/drivers/tty/serial/apbuart.c +++ b/drivers/tty/serial/apbuart.c @@ -555,10 +555,9 @@ static struct uart_driver grlib_apbuart_driver = { static int __devinit apbuart_probe(struct platform_device *op) { - int i = -1; + int i; struct uart_port *port = NULL; - i = 0; for (i = 0; i < grlib_apbuart_port_nr; i++) { if (op->dev.of_node == grlib_apbuart_nodes[i]) break; @@ -566,6 +565,7 @@ static int __devinit apbuart_probe(struct platform_device *op) port = &grlib_apbuart_ports[i]; port->dev = &op->dev; + port->irq = op->archdata.irqs[0]; uart_add_one_port(&grlib_apbuart_driver, (struct uart_port *) port); @@ -598,24 +598,12 @@ static struct platform_driver grlib_apbuart_of_driver = { static int grlib_apbuart_configure(void) { - struct device_node *np, *rp; - const u32 *prop; - int freq_khz, line = 0; - - /* Get bus frequency */ - rp = of_find_node_by_path("/"); - if (!rp) - return -ENODEV; - rp = of_get_next_child(rp, NULL); - if (!rp) - return -ENODEV; - prop = of_get_property(rp, "clock-frequency", NULL); - if (!prop) - return -ENODEV; - freq_khz = *prop; + struct device_node *np; + int line = 0; for_each_matching_node(np, apbuart_match) { - const int *irqs, *ampopts; + const int *ampopts; + const u32 *freq_hz; const struct amba_prom_registers *regs; struct uart_port *port; unsigned long addr; @@ -623,11 +611,11 @@ static int grlib_apbuart_configure(void) ampopts = of_get_property(np, "ampopts", NULL); if (ampopts && (*ampopts == 0)) continue; /* Ignore if used by another OS instance */ - - irqs = of_get_property(np, "interrupts", NULL); regs = of_get_property(np, "reg", NULL); + /* Frequency of APB Bus is frequency of UART */ + freq_hz = of_get_property(np, "freq", NULL); - if (!irqs || !regs) + if (!regs || !freq_hz || (*freq_hz == 0)) continue; grlib_apbuart_nodes[line] = np; @@ -638,12 +626,12 @@ static int grlib_apbuart_configure(void) port->mapbase = addr; port->membase = ioremap(addr, sizeof(struct grlib_apbuart_regs_map)); - port->irq = *irqs; + port->irq = 0; port->iotype = UPIO_MEM; port->ops = &grlib_apbuart_ops; port->flags = UPF_BOOT_AUTOCONF; port->line = line; - port->uartclk = freq_khz * 1000; + port->uartclk = *freq_hz; port->fifosize = apbuart_scan_fifo_size((struct uart_port *) port, line); line++; diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index b9451219528..f1a7918d71a 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c @@ -442,10 +442,8 @@ static void flush_to_ldisc(struct work_struct *work) line discipline as we want to empty the queue */ if (test_bit(TTY_FLUSHPENDING, &tty->flags)) break; - if (!tty->receive_room || seen_tail) { - schedule_work(&tty->buf.work); + if (!tty->receive_room || seen_tail) break; - } if (count > tty->receive_room) count = tty->receive_room; char_buf = head->char_buf_ptr + head->read; diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index b37f92cb71b..444b60aa15e 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c @@ -139,24 +139,6 @@ static const char ep0name [] = "ep0"; static void pxa25x_ep_fifo_flush (struct usb_ep *ep); static void nuke (struct pxa25x_ep *, int status); -/* one GPIO should be used to detect VBUS from the host */ -static int is_vbus_present(void) -{ - struct pxa2xx_udc_mach_info *mach = the_controller->mach; - - if (gpio_is_valid(mach->gpio_vbus)) { - int value = gpio_get_value(mach->gpio_vbus); - - if (mach->gpio_vbus_inverted) - return !value; - else - return !!value; - } - if (mach->udc_is_connected) - return mach->udc_is_connected(); - return 1; -} - /* one GPIO should control a D+ pullup, so host sees this device (or not) */ static void pullup_off(void) { @@ -1055,7 +1037,7 @@ udc_seq_show(struct seq_file *m, void *_d) "%s version: %s\nGadget driver: %s\nHost %s\n\n", driver_name, DRIVER_VERSION SIZE_STR "(pio)", dev->driver ? dev->driver->driver.name : "(none)", - is_vbus_present() ? "full speed" : "disconnected"); + dev->gadget.speed == USB_SPEED_FULL ? "full speed" : "disconnected"); /* registers for device and ep0 */ seq_printf(m, @@ -1094,7 +1076,7 @@ udc_seq_show(struct seq_file *m, void *_d) (tmp & UDCCFR_ACM) ? " acm" : ""); } - if (!is_vbus_present() || !dev->driver) + if (dev->gadget.speed != USB_SPEED_FULL || !dev->driver) goto done; seq_printf(m, "ep0 IN %lu/%lu, OUT %lu/%lu\nirqs %lu\n\n", @@ -1435,14 +1417,6 @@ lubbock_vbus_irq(int irq, void *_dev) #endif -static irqreturn_t udc_vbus_irq(int irq, void *_dev) -{ - struct pxa25x_udc *dev = _dev; - - pxa25x_udc_vbus_session(&dev->gadget, is_vbus_present()); - return IRQ_HANDLED; -} - /*-------------------------------------------------------------------------*/ @@ -1766,12 +1740,9 @@ pxa25x_udc_irq(int irq, void *_dev) if (unlikely(udccr & UDCCR_SUSIR)) { udc_ack_int_UDCCR(UDCCR_SUSIR); handled = 1; - DBG(DBG_VERBOSE, "USB suspend%s\n", is_vbus_present() - ? "" : "+disconnect"); + DBG(DBG_VERBOSE, "USB suspend\n"); - if (!is_vbus_present()) - stop_activity(dev, dev->driver); - else if (dev->gadget.speed != USB_SPEED_UNKNOWN + if (dev->gadget.speed != USB_SPEED_UNKNOWN && dev->driver && dev->driver->suspend) dev->driver->suspend(&dev->gadget); @@ -1786,8 +1757,7 @@ pxa25x_udc_irq(int irq, void *_dev) if (dev->gadget.speed != USB_SPEED_UNKNOWN && dev->driver - && dev->driver->resume - && is_vbus_present()) + && dev->driver->resume) dev->driver->resume(&dev->gadget); } @@ -2137,7 +2107,7 @@ static struct pxa25x_udc memory = { static int __init pxa25x_udc_probe(struct platform_device *pdev) { struct pxa25x_udc *dev = &memory; - int retval, vbus_irq, irq; + int retval, irq; u32 chiprev; /* insist on Intel/ARM/XScale */ @@ -2199,19 +2169,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) dev->transceiver = otg_get_transceiver(); - if (gpio_is_valid(dev->mach->gpio_vbus)) { - if ((retval = gpio_request(dev->mach->gpio_vbus, - "pxa25x_udc GPIO VBUS"))) { - dev_dbg(&pdev->dev, - "can't get vbus gpio %d, err: %d\n", - dev->mach->gpio_vbus, retval); - goto err_gpio_vbus; - } - gpio_direction_input(dev->mach->gpio_vbus); - vbus_irq = gpio_to_irq(dev->mach->gpio_vbus); - } else - vbus_irq = 0; - if (gpio_is_valid(dev->mach->gpio_pullup)) { if ((retval = gpio_request(dev->mach->gpio_pullup, "pca25x_udc GPIO PULLUP"))) { @@ -2237,7 +2194,7 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) udc_disable(dev); udc_reinit(dev); - dev->vbus = !!is_vbus_present(); + dev->vbus = 0; /* irq setup after old hardware state is cleaned up */ retval = request_irq(irq, pxa25x_udc_irq, @@ -2273,22 +2230,10 @@ lubbock_fail0: } } else #endif - if (vbus_irq) { - retval = request_irq(vbus_irq, udc_vbus_irq, - IRQF_DISABLED | IRQF_SAMPLE_RANDOM | - IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, - driver_name, dev); - if (retval != 0) { - pr_err("%s: can't get irq %i, err %d\n", - driver_name, vbus_irq, retval); - goto err_vbus_irq; - } - } create_debug_files(dev); return 0; - err_vbus_irq: #ifdef CONFIG_ARCH_LUBBOCK free_irq(LUBBOCK_USB_DISC_IRQ, dev); err_irq_lub: @@ -2298,9 +2243,6 @@ lubbock_fail0: if (gpio_is_valid(dev->mach->gpio_pullup)) gpio_free(dev->mach->gpio_pullup); err_gpio_pullup: - if (gpio_is_valid(dev->mach->gpio_vbus)) - gpio_free(dev->mach->gpio_vbus); - err_gpio_vbus: if (dev->transceiver) { otg_put_transceiver(dev->transceiver); dev->transceiver = NULL; @@ -2337,10 +2279,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev) free_irq(LUBBOCK_USB_IRQ, dev); } #endif - if (gpio_is_valid(dev->mach->gpio_vbus)) { - free_irq(gpio_to_irq(dev->mach->gpio_vbus), dev); - gpio_free(dev->mach->gpio_vbus); - } if (gpio_is_valid(dev->mach->gpio_pullup)) gpio_free(dev->mach->gpio_pullup); diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index d2c019637e4..ba0d28727cc 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c @@ -106,7 +106,7 @@ static void mct_u232_break_ctl(struct tty_struct *tty, int break_state); static int mct_u232_tiocmget(struct tty_struct *tty); static int mct_u232_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear); -static int mct_u232_ioctl(struct tty_struct *tty, struct file *file, +static int mct_u232_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg); static int mct_u232_get_icount(struct tty_struct *tty, struct serial_icounter_struct *icount); @@ -874,7 +874,7 @@ static void mct_u232_unthrottle(struct tty_struct *tty) } } -static int mct_u232_ioctl(struct tty_struct *tty, struct file *file, +static int mct_u232_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg) { DEFINE_WAIT(wait); diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index 201f6096844..a1dd4d4fa19 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c @@ -413,7 +413,7 @@ static int opticon_tiocmget(struct tty_struct *tty) return result; } -static int opticon_tiocmset(struct tty_struct *tty, struct file *file, +static int opticon_tiocmset(struct tty_struct *tty, unsigned int set, unsigned int clear) { struct usb_serial_port *port = tty->driver_data; diff --git a/drivers/video/fb-puv3.c b/drivers/video/fb-puv3.c index dbd2dc4745d..27f2c57e06e 100644 --- a/drivers/video/fb-puv3.c +++ b/drivers/video/fb-puv3.c @@ -13,7 +13,6 @@ #include <linux/module.h> #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/vmalloc.h> #include <linux/platform_device.h> #include <linux/clk.h> #include <linux/fb.h> @@ -531,7 +530,7 @@ static int unifb_set_par(struct fb_info *info) return -EINVAL; } - writel(PKUNITY_UNIGFX_MMAP_BASE, UDE_FSA); + writel(info->fix.smem_start, UDE_FSA); writel(info->var.yres, UDE_LS); writel(get_line_length(info->var.xres, info->var.bits_per_pixel) >> 3, UDE_PS); @@ -680,13 +679,27 @@ static int unifb_probe(struct platform_device *dev) struct fb_info *info; u32 unifb_regs[UNIFB_REGS_NUM]; int retval = -ENOMEM; - struct resource *iomem, *mapmem; + struct resource *iomem; + void *videomemory; + + videomemory = (void *)__get_free_pages(GFP_KERNEL | __GFP_COMP, + get_order(UNIFB_MEMSIZE)); + if (!videomemory) + goto err; + + memset(videomemory, 0, UNIFB_MEMSIZE); + + unifb_fix.smem_start = virt_to_phys(videomemory); + unifb_fix.smem_len = UNIFB_MEMSIZE; + + iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); + unifb_fix.mmio_start = iomem->start; info = framebuffer_alloc(sizeof(u32)*256, &dev->dev); if (!info) goto err; - info->screen_base = (char __iomem *)KUSER_UNIGFX_BASE; + info->screen_base = (char __iomem *)videomemory; info->fbops = &unifb_ops; retval = fb_find_mode(&info->var, info, NULL, @@ -695,13 +708,6 @@ static int unifb_probe(struct platform_device *dev) if (!retval || (retval == 4)) info->var = unifb_default; - iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); - unifb_fix.mmio_start = iomem->start; - - mapmem = platform_get_resource(dev, IORESOURCE_MEM, 1); - unifb_fix.smem_start = mapmem->start; - unifb_fix.smem_len = UNIFB_MEMSIZE; - info->fix = unifb_fix; info->pseudo_palette = info->par; info->par = NULL; diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c index 825b665245b..a2e5b5100ab 100644 --- a/drivers/video/pxafb.c +++ b/drivers/video/pxafb.c @@ -627,7 +627,12 @@ static void overlay1fb_enable(struct pxafb_layer *ofb) static void overlay1fb_disable(struct pxafb_layer *ofb) { - uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5); + uint32_t lccr5; + + if (!(lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN)) + return; + + lccr5 = lcd_readl(ofb->fbi, LCCR5); lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN); @@ -685,7 +690,12 @@ static void overlay2fb_enable(struct pxafb_layer *ofb) static void overlay2fb_disable(struct pxafb_layer *ofb) { - uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5); + uint32_t lccr5; + + if (!(lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN)) + return; + + lccr5 = lcd_readl(ofb->fbi, LCCR5); lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN); @@ -720,12 +730,10 @@ static int overlayfb_open(struct fb_info *info, int user) if (user == 0) return -ENODEV; - /* allow only one user at a time */ - if (atomic_inc_and_test(&ofb->usage)) - return -EBUSY; + if (ofb->usage++ == 0) + /* unblank the base framebuffer */ + fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK); - /* unblank the base framebuffer */ - fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK); return 0; } @@ -733,12 +741,15 @@ static int overlayfb_release(struct fb_info *info, int user) { struct pxafb_layer *ofb = (struct pxafb_layer*) info; - atomic_dec(&ofb->usage); - ofb->ops->disable(ofb); + if (ofb->usage == 1) { + ofb->ops->disable(ofb); + ofb->fb.var.height = -1; + ofb->fb.var.width = -1; + ofb->fb.var.xres = ofb->fb.var.xres_virtual = 0; + ofb->fb.var.yres = ofb->fb.var.yres_virtual = 0; - free_pages_exact(ofb->video_mem, ofb->video_mem_size); - ofb->video_mem = NULL; - ofb->video_mem_size = 0; + ofb->usage--; + } return 0; } @@ -750,7 +761,7 @@ static int overlayfb_check_var(struct fb_var_screeninfo *var, int xpos, ypos, pfor, bpp; xpos = NONSTD_TO_XPOS(var->nonstd); - ypos = NONSTD_TO_XPOS(var->nonstd); + ypos = NONSTD_TO_YPOS(var->nonstd); pfor = NONSTD_TO_PFOR(var->nonstd); bpp = pxafb_var_to_bpp(var); @@ -794,7 +805,7 @@ static int overlayfb_check_var(struct fb_var_screeninfo *var, return 0; } -static int overlayfb_map_video_memory(struct pxafb_layer *ofb) +static int overlayfb_check_video_memory(struct pxafb_layer *ofb) { struct fb_var_screeninfo *var = &ofb->fb.var; int pfor = NONSTD_TO_PFOR(var->nonstd); @@ -812,27 +823,11 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb) size = PAGE_ALIGN(ofb->fb.fix.line_length * var->yres_virtual); - /* don't re-allocate if the original video memory is enough */ if (ofb->video_mem) { if (ofb->video_mem_size >= size) return 0; - - free_pages_exact(ofb->video_mem, ofb->video_mem_size); } - - ofb->video_mem = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); - if (ofb->video_mem == NULL) - return -ENOMEM; - - ofb->video_mem_phys = virt_to_phys(ofb->video_mem); - ofb->video_mem_size = size; - - mutex_lock(&ofb->fb.mm_lock); - ofb->fb.fix.smem_start = ofb->video_mem_phys; - ofb->fb.fix.smem_len = ofb->fb.fix.line_length * var->yres_virtual; - mutex_unlock(&ofb->fb.mm_lock); - ofb->fb.screen_base = ofb->video_mem; - return 0; + return -EINVAL; } static int overlayfb_set_par(struct fb_info *info) @@ -841,13 +836,13 @@ static int overlayfb_set_par(struct fb_info *info) struct fb_var_screeninfo *var = &info->var; int xpos, ypos, pfor, bpp, ret; - ret = overlayfb_map_video_memory(ofb); + ret = overlayfb_check_video_memory(ofb); if (ret) return ret; bpp = pxafb_var_to_bpp(var); xpos = NONSTD_TO_XPOS(var->nonstd); - ypos = NONSTD_TO_XPOS(var->nonstd); + ypos = NONSTD_TO_YPOS(var->nonstd); pfor = NONSTD_TO_PFOR(var->nonstd); ofb->control[0] = OVLxC1_PPL(var->xres) | OVLxC1_LPO(var->yres) | @@ -891,7 +886,7 @@ static void __devinit init_pxafb_overlay(struct pxafb_info *fbi, ofb->id = id; ofb->ops = &ofb_ops[id]; - atomic_set(&ofb->usage, 0); + ofb->usage = 0; ofb->fbi = fbi; init_completion(&ofb->branch_done); } @@ -904,29 +899,60 @@ static inline int pxafb_overlay_supported(void) return 0; } -static int __devinit pxafb_overlay_init(struct pxafb_info *fbi) +static int __devinit pxafb_overlay_map_video_memory(struct pxafb_info *pxafb, + struct pxafb_layer *ofb) +{ + /* We assume that user will use at most video_mem_size for overlay fb, + * anyway, it's useless to use 16bpp main plane and 24bpp overlay + */ + ofb->video_mem = alloc_pages_exact(PAGE_ALIGN(pxafb->video_mem_size), + GFP_KERNEL | __GFP_ZERO); + if (ofb->video_mem == NULL) + return -ENOMEM; + + ofb->video_mem_phys = virt_to_phys(ofb->video_mem); + ofb->video_mem_size = PAGE_ALIGN(pxafb->video_mem_size); + + mutex_lock(&ofb->fb.mm_lock); + ofb->fb.fix.smem_start = ofb->video_mem_phys; + ofb->fb.fix.smem_len = pxafb->video_mem_size; + mutex_unlock(&ofb->fb.mm_lock); + + ofb->fb.screen_base = ofb->video_mem; + + return 0; +} + +static void __devinit pxafb_overlay_init(struct pxafb_info *fbi) { int i, ret; if (!pxafb_overlay_supported()) - return 0; + return; for (i = 0; i < 2; i++) { - init_pxafb_overlay(fbi, &fbi->overlay[i], i); - ret = register_framebuffer(&fbi->overlay[i].fb); + struct pxafb_layer *ofb = &fbi->overlay[i]; + init_pxafb_overlay(fbi, ofb, i); + ret = register_framebuffer(&ofb->fb); if (ret) { dev_err(fbi->dev, "failed to register overlay %d\n", i); - return ret; + continue; } + ret = pxafb_overlay_map_video_memory(fbi, ofb); + if (ret) { + dev_err(fbi->dev, + "failed to map video memory for overlay %d\n", + i); + unregister_framebuffer(&ofb->fb); + continue; + } + ofb->registered = 1; } /* mask all IU/BS/EOF/SOF interrupts */ lcd_writel(fbi, LCCR5, ~0); - /* place overlay(s) on top of base */ - fbi->lccr0 |= LCCR0_OUC; pr_info("PXA Overlay driver loaded successfully!\n"); - return 0; } static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi) @@ -936,8 +962,15 @@ static void __devexit pxafb_overlay_exit(struct pxafb_info *fbi) if (!pxafb_overlay_supported()) return; - for (i = 0; i < 2; i++) - unregister_framebuffer(&fbi->overlay[i].fb); + for (i = 0; i < 2; i++) { + struct pxafb_layer *ofb = &fbi->overlay[i]; + if (ofb->registered) { + if (ofb->video_mem) + free_pages_exact(ofb->video_mem, + ofb->video_mem_size); + unregister_framebuffer(&ofb->fb); + } + } } #else static inline void pxafb_overlay_init(struct pxafb_info *fbi) {} @@ -1368,7 +1401,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var, (lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) || (lcd_readl(fbi, LCCR4) != fbi->reg_lccr4) || (lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) || - (lcd_readl(fbi, FDADR1) != fbi->fdadr[1])) + ((fbi->lccr0 & LCCR0_SDS) && + (lcd_readl(fbi, FDADR1) != fbi->fdadr[1]))) pxafb_schedule_work(fbi, C_REENABLE); return 0; @@ -1420,7 +1454,8 @@ static void pxafb_enable_controller(struct pxafb_info *fbi) lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB); lcd_writel(fbi, FDADR0, fbi->fdadr[0]); - lcd_writel(fbi, FDADR1, fbi->fdadr[1]); + if (fbi->lccr0 & LCCR0_SDS) + lcd_writel(fbi, FDADR1, fbi->fdadr[1]); lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB); } @@ -1613,7 +1648,8 @@ pxafb_freq_transition(struct notifier_block *nb, unsigned long val, void *data) switch (val) { case CPUFREQ_PRECHANGE: - set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE); + if (!fbi->overlay[0].usage && !fbi->overlay[1].usage) + set_ctrlr_state(fbi, C_DISABLE_CLKCHANGE); break; case CPUFREQ_POSTCHANGE: @@ -1806,6 +1842,12 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev) pxafb_decode_mach_info(fbi, inf); +#ifdef CONFIG_FB_PXA_OVERLAY + /* place overlay(s) on top of base */ + if (pxafb_overlay_supported()) + fbi->lccr0 |= LCCR0_OUC; +#endif + init_waitqueue_head(&fbi->ctrlr_wait); INIT_WORK(&fbi->task, pxafb_task); mutex_init(&fbi->ctrlr_lock); diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h index 2353521c5c8..26ba9fa3f73 100644 --- a/drivers/video/pxafb.h +++ b/drivers/video/pxafb.h @@ -92,7 +92,8 @@ struct pxafb_layer_ops { struct pxafb_layer { struct fb_info fb; int id; - atomic_t usage; + int registered; + uint32_t usage; uint32_t control[2]; struct pxafb_layer_ops *ops; |