aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/ahci.c3
-rw-r--r--drivers/ata/libata-core.c12
-rw-r--r--drivers/ata/libata-eh.c6
-rw-r--r--drivers/ata/pata_atiixp.c2
-rw-r--r--drivers/ata/pata_sc1200.c3
-rw-r--r--drivers/ata/pata_via.c2
-rw-r--r--drivers/ata/sata_mv.c29
-rw-r--r--drivers/ata/sata_nv.c18
-rw-r--r--drivers/base/bus.c17
-rw-r--r--drivers/base/driver.c2
-rw-r--r--drivers/base/platform.c6
-rw-r--r--drivers/base/power/main.c1
-rw-r--r--drivers/base/power/runtime.c4
-rw-r--r--drivers/block/loop.c2
-rw-r--r--drivers/block/virtio_blk.c39
-rw-r--r--drivers/char/Kconfig6
-rw-r--r--drivers/char/hw_random/virtio-rng.c3
-rw-r--r--drivers/char/virtio_console.c1
-rw-r--r--drivers/cpuidle/cpuidle.c5
-rw-r--r--drivers/crypto/padlock-sha.c14
-rw-r--r--drivers/edac/amd64_edac.c8
-rw-r--r--drivers/edac/i5000_edac.c7
-rw-r--r--drivers/edac/i5400_edac.c89
-rw-r--r--drivers/edac/mpc85xx_edac.c2
-rw-r--r--drivers/gpio/twl4030-gpio.c5
-rw-r--r--drivers/gpu/drm/drm_edid.c15
-rw-r--r--drivers/gpu/drm/drm_fb_helper.c42
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c5
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c25
-rw-r--r--drivers/gpu/drm/radeon/radeon_device.c7
-rw-r--r--drivers/hwmon/dme1737.c29
-rw-r--r--drivers/hwmon/fschmd.c2
-rw-r--r--drivers/hwmon/hp_accel.c5
-rw-r--r--drivers/hwmon/it87.c5
-rw-r--r--drivers/i2c/busses/i2c-imx.c86
-rw-r--r--drivers/i2c/busses/i2c-mpc.c10
-rw-r--r--drivers/ide/atiixp.c2
-rw-r--r--drivers/ide/cmd64x.c6
-rw-r--r--drivers/input/input.c65
-rw-r--r--drivers/input/keyboard/atkbd.c132
-rw-r--r--drivers/input/keyboard/gpio_keys.c1
-rw-r--r--drivers/input/misc/Kconfig1
-rw-r--r--drivers/input/misc/hp_sdc_rtc.c2
-rw-r--r--drivers/input/mouse/logips2pp.c2
-rw-r--r--drivers/input/mouse/synaptics.c10
-rw-r--r--drivers/input/serio/i8042-x86ia64io.h13
-rw-r--r--drivers/input/serio/i8042.c35
-rw-r--r--drivers/isdn/i4l/isdn_net.h6
-rw-r--r--drivers/md/Makefile22
-rw-r--r--drivers/md/bitmap.c9
-rw-r--r--drivers/md/dm-exception-store.c38
-rw-r--r--drivers/md/dm-exception-store.h8
-rw-r--r--drivers/md/dm-log-userspace-base.c2
-rw-r--r--drivers/md/dm-snap-persistent.c16
-rw-r--r--drivers/md/dm-snap.c25
-rw-r--r--drivers/md/dm.c11
-rw-r--r--drivers/md/md.c2
-rw-r--r--drivers/md/raid1.c6
-rw-r--r--drivers/md/raid10.c5
-rw-r--r--drivers/md/raid5.c182
-rw-r--r--drivers/md/raid5.h14
-rw-r--r--drivers/md/raid6altivec.uc2
-rw-r--r--drivers/md/raid6int.uc2
-rw-r--r--drivers/md/raid6test/Makefile42
-rw-r--r--drivers/md/unroll.awk20
-rw-r--r--drivers/md/unroll.pl24
-rw-r--r--drivers/mfd/twl4030-core.c2
-rw-r--r--drivers/mfd/wm831x-irq.c3
-rw-r--r--drivers/mmc/host/at91_mci.c1
-rw-r--r--drivers/mmc/host/omap_hsmmc.c2
-rw-r--r--drivers/mtd/ubi/build.c3
-rw-r--r--drivers/mtd/ubi/scan.c7
-rw-r--r--drivers/mtd/ubi/scan.h2
-rw-r--r--drivers/net/au1000_eth.c1
-rw-r--r--drivers/net/benet/be_cmds.c33
-rw-r--r--drivers/net/benet/be_cmds.h5
-rw-r--r--drivers/net/benet/be_main.c27
-rw-r--r--drivers/net/bnx2.h9
-rw-r--r--drivers/net/bonding/bond_main.c10
-rw-r--r--drivers/net/cnic.c6
-rw-r--r--drivers/net/dm9000.h2
-rw-r--r--drivers/net/e100.c26
-rw-r--r--drivers/net/e1000e/defines.h2
-rw-r--r--drivers/net/e1000e/e1000.h26
-rw-r--r--drivers/net/e1000e/hw.h3
-rw-r--r--drivers/net/e1000e/ich8lan.c628
-rw-r--r--drivers/net/e1000e/phy.c476
-rw-r--r--drivers/net/ethoc.c21
-rw-r--r--drivers/net/fec.c2
-rw-r--r--drivers/net/ifb.c3
-rw-r--r--drivers/net/igb/igb_ethtool.c35
-rw-r--r--drivers/net/igbvf/ethtool.c30
-rw-r--r--drivers/net/ixgbe/ixgbe_ethtool.c22
-rw-r--r--drivers/net/ks8851.c42
-rw-r--r--drivers/net/ks8851.h1
-rw-r--r--drivers/net/mlx4/main.c1
-rw-r--r--drivers/net/myri10ge/myri10ge.c17
-rw-r--r--drivers/net/netxen/netxen_nic_hdr.h1
-rw-r--r--drivers/net/netxen/netxen_nic_hw.c14
-rw-r--r--drivers/net/netxen/netxen_nic_init.c8
-rw-r--r--drivers/net/netxen/netxen_nic_main.c1
-rw-r--r--drivers/net/niu.c2
-rw-r--r--drivers/net/pcmcia/pcnet_cs.c2
-rw-r--r--drivers/net/pppoe.c129
-rw-r--r--drivers/net/qlge/qlge.h1
-rw-r--r--drivers/net/qlge/qlge_main.c78
-rw-r--r--drivers/net/qlge/qlge_mpi.c23
-rw-r--r--drivers/net/r8169.c15
-rw-r--r--drivers/net/sfc/rx.c9
-rw-r--r--drivers/net/sh_eth.c1
-rw-r--r--drivers/net/sky2.c2
-rw-r--r--drivers/net/tokenring/ibmtr.c11
-rw-r--r--drivers/net/usb/dm9601.c4
-rw-r--r--drivers/net/usb/rndis_host.c6
-rw-r--r--drivers/net/virtio_net.c17
-rw-r--r--drivers/net/vmxnet3/vmxnet3_drv.c27
-rw-r--r--drivers/net/vmxnet3/vmxnet3_int.h2
-rw-r--r--drivers/net/wireless/airo.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c2
-rw-r--r--drivers/net/wireless/b43/dma.c15
-rw-r--r--drivers/net/wireless/b43/leds.h1
-rw-r--r--drivers/net/wireless/b43/main.c1
-rw-r--r--drivers/net/wireless/b43/rfkill.c3
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c5
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c2
-rw-r--r--drivers/net/wireless/ipw2x00/libipw.h1
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_module.c14
-rw-r--r--drivers/net/wireless/libertas/if_spi.c10
-rw-r--r--drivers/net/wireless/libertas/if_usb.c2
-rw-r--r--drivers/net/wireless/ray_cs.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c5
-rw-r--r--drivers/of/of_mdio.c13
-rw-r--r--drivers/pci/quirks.c6
-rw-r--r--drivers/pci/setup-bus.c13
-rw-r--r--drivers/pcmcia/cistpl.c20
-rw-r--r--drivers/pcmcia/cs.c69
-rw-r--r--drivers/pcmcia/cs_internal.h3
-rw-r--r--drivers/pcmcia/ds.c8
-rw-r--r--drivers/pcmcia/i82365.c4
-rw-r--r--drivers/pcmcia/m32r_cfc.c10
-rw-r--r--drivers/pcmcia/m32r_pcc.c10
-rw-r--r--drivers/pcmcia/m8xx_pcmcia.c15
-rw-r--r--drivers/pcmcia/pcmcia_ioctl.c2
-rw-r--r--drivers/pcmcia/pd6729.c6
-rw-r--r--drivers/pcmcia/rsrc_nonstatic.c3
-rw-r--r--drivers/pcmcia/soc_common.c5
-rw-r--r--drivers/pcmcia/socket_sysfs.c2
-rw-r--r--drivers/pcmcia/tcic.c4
-rw-r--r--drivers/pcmcia/yenta_socket.c12
-rw-r--r--drivers/s390/char/sclp_async.c47
-rw-r--r--drivers/s390/net/smsgiucv.c7
-rw-r--r--drivers/s390/scsi/zfcp_aux.c11
-rw-r--r--drivers/s390/scsi/zfcp_erp.c22
-rw-r--r--drivers/s390/scsi/zfcp_ext.h1
-rw-r--r--drivers/s390/scsi/zfcp_fc.c11
-rw-r--r--drivers/s390/scsi/zfcp_fsf.c13
-rw-r--r--drivers/s390/scsi/zfcp_sysfs.c1
-rw-r--r--drivers/scsi/dpt_i2o.c4
-rw-r--r--drivers/scsi/scsi_scan.c2
-rw-r--r--drivers/scsi/scsi_sysfs.c7
-rw-r--r--drivers/serial/8250_pci.c78
-rw-r--r--drivers/serial/atmel_serial.c2
-rw-r--r--drivers/serial/mpc52xx_uart.c2
-rw-r--r--drivers/serial/serial_cs.c8
-rw-r--r--drivers/staging/Kconfig2
-rw-r--r--drivers/staging/Makefile1
-rw-r--r--drivers/staging/android/Kconfig1
-rw-r--r--drivers/staging/hv/ChannelMgmt.h3
-rw-r--r--drivers/staging/hv/NetVsc.c10
-rw-r--r--drivers/staging/hv/TODO6
-rw-r--r--drivers/staging/hv/osd.h1
-rw-r--r--drivers/staging/hv/vmbus_drv.c28
-rw-r--r--drivers/staging/otus/Kconfig2
-rw-r--r--drivers/staging/panel/panel.c13
-rw-r--r--drivers/staging/rt2860/Kconfig2
-rw-r--r--drivers/staging/rt2870/Kconfig2
-rw-r--r--drivers/staging/rt3090/Kconfig2
-rw-r--r--drivers/staging/rtl8187se/Kconfig2
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c4
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_module.c4
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c12
-rw-r--r--drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c17
-rw-r--r--drivers/staging/rtl8192e/Kconfig2
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c8
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_module.c8
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c19
-rw-r--r--drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c21
-rw-r--r--drivers/staging/rtl8192su/Kconfig2
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c4
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_module.c4
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c15
-rw-r--r--drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c17
-rw-r--r--drivers/staging/stlc45xx/Kconfig8
-rw-r--r--drivers/staging/stlc45xx/Makefile1
-rw-r--r--drivers/staging/stlc45xx/stlc45xx.c2594
-rw-r--r--drivers/staging/stlc45xx/stlc45xx.h283
-rw-r--r--drivers/staging/stlc45xx/stlc45xx_lmac.h434
-rw-r--r--drivers/staging/vt6656/main_usb.c1
-rw-r--r--drivers/staging/winbond/Kconfig2
-rw-r--r--drivers/staging/wlan-ng/Kconfig2
-rw-r--r--drivers/usb/gadget/Kconfig1
-rw-r--r--drivers/usb/gadget/fsl_udc_core.c2
-rw-r--r--drivers/usb/host/r8a66597-hcd.c23
-rw-r--r--drivers/usb/serial/option.c4
-rw-r--r--drivers/usb/serial/sierra.c38
-rw-r--r--drivers/virtio/virtio_balloon.c3
-rw-r--r--drivers/virtio/virtio_pci.c27
-rw-r--r--drivers/virtio/virtio_ring.c3
210 files changed, 2461 insertions, 4693 deletions
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index b1a257746a19..a06f5d6375a8 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -575,7 +575,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(ATI, 0x4395), board_ahci_sb700 }, /* ATI SB700/800 */
/* AMD */
- { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD SB900 */
+ { PCI_VDEVICE(AMD, 0x7800), board_ahci }, /* AMD Hudson-2 */
/* AMD is using RAID class only for ahci controllers */
{ PCI_VENDOR_ID_AMD, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
PCI_CLASS_STORAGE_RAID << 8, 0xffffff, board_ahci },
@@ -605,6 +605,7 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci_yesncq }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci_yesncq }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci_yesncq }, /* MCP67 */
+ { PCI_VDEVICE(NVIDIA, 0x0580), board_ahci_yesncq }, /* Linux ID */
{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci_yesncq }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci_yesncq }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci_yesncq }, /* MCP73 */
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b525a0981348..d7f0f1b1ae3e 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -5028,12 +5028,14 @@ void ata_qc_complete(struct ata_queued_cmd *qc)
qc->flags |= ATA_QCFLAG_FAILED;
if (unlikely(qc->flags & ATA_QCFLAG_FAILED)) {
- if (!ata_tag_internal(qc->tag)) {
- /* always fill result TF for failed qc */
- fill_result_tf(qc);
+ /* always fill result TF for failed qc */
+ fill_result_tf(qc);
+
+ if (!ata_tag_internal(qc->tag))
ata_qc_schedule_eh(qc);
- return;
- }
+ else
+ __ata_qc_complete(qc);
+ return;
}
WARN_ON_ONCE(ap->pflags & ATA_PFLAG_FROZEN);
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 0a97822da211..bba2ae5df1c2 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2981,12 +2981,14 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
* device detection messages backwards.
*/
ata_for_each_dev(dev, link, ALL) {
- if (!(new_mask & (1 << dev->devno)) ||
- dev->class == ATA_DEV_PMP)
+ if (!(new_mask & (1 << dev->devno)))
continue;
dev->class = ehc->classes[dev->devno];
+ if (dev->class == ATA_DEV_PMP)
+ continue;
+
ehc->i.flags |= ATA_EHI_PRINTINFO;
rc = ata_dev_configure(dev);
ehc->i.flags &= ~ATA_EHI_PRINTINFO;
diff --git a/drivers/ata/pata_atiixp.c b/drivers/ata/pata_atiixp.c
index aa4b3f6ae771..ae4454d4e955 100644
--- a/drivers/ata/pata_atiixp.c
+++ b/drivers/ata/pata_atiixp.c
@@ -246,7 +246,7 @@ static const struct pci_device_id atiixp[] = {
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), },
- { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_SB900_IDE), },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_HUDSON2_IDE), },
{ },
};
diff --git a/drivers/ata/pata_sc1200.c b/drivers/ata/pata_sc1200.c
index f49814d6fd2e..3bbed8322ecf 100644
--- a/drivers/ata/pata_sc1200.c
+++ b/drivers/ata/pata_sc1200.c
@@ -235,8 +235,7 @@ static int sc1200_init_one(struct pci_dev *dev, const struct pci_device_id *id)
.udma_mask = ATA_UDMA2,
.port_ops = &sc1200_port_ops
};
- /* Can't enable port 2 yet, see top comments */
- const struct ata_port_info *ppi[] = { &info, };
+ const struct ata_port_info *ppi[] = { &info, NULL };
return ata_pci_sff_init_one(dev, ppi, &sc1200_sht, NULL);
}
diff --git a/drivers/ata/pata_via.c b/drivers/ata/pata_via.c
index 45657cacec43..88984b803d6d 100644
--- a/drivers/ata/pata_via.c
+++ b/drivers/ata/pata_via.c
@@ -111,7 +111,7 @@ static const struct via_isa_bridge {
{ "vt8251", PCI_DEVICE_ID_VIA_8251, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "cx700", PCI_DEVICE_ID_VIA_CX700, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_SATA_PATA },
{ "vt6410", PCI_DEVICE_ID_VIA_6410, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
- { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
+ { "vt6415", PCI_DEVICE_ID_VIA_6415, 0x00, 0xff, VIA_UDMA_133 | VIA_BAD_AST | VIA_NO_ENABLES },
{ "vt8237a", PCI_DEVICE_ID_VIA_8237A, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8237", PCI_DEVICE_ID_VIA_8237, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
{ "vt8235", PCI_DEVICE_ID_VIA_8235, 0x00, 0x2f, VIA_UDMA_133 | VIA_BAD_AST },
diff --git a/drivers/ata/sata_mv.c b/drivers/ata/sata_mv.c
index 17f9ff9067a2..6f5093b7c8c5 100644
--- a/drivers/ata/sata_mv.c
+++ b/drivers/ata/sata_mv.c
@@ -1382,6 +1382,25 @@ static int mv_qc_defer(struct ata_queued_cmd *qc)
*/
if (pp->pp_flags & MV_PP_FLAG_DELAYED_EH)
return ATA_DEFER_PORT;
+
+ /* PIO commands need exclusive link: no other commands [DMA or PIO]
+ * can run concurrently.
+ * set excl_link when we want to send a PIO command in DMA mode
+ * or a non-NCQ command in NCQ mode.
+ * When we receive a command from that link, and there are no
+ * outstanding commands, mark a flag to clear excl_link and let
+ * the command go through.
+ */
+ if (unlikely(ap->excl_link)) {
+ if (link == ap->excl_link) {
+ if (ap->nr_active_links)
+ return ATA_DEFER_PORT;
+ qc->flags |= ATA_QCFLAG_CLEAR_EXCL;
+ return 0;
+ } else
+ return ATA_DEFER_PORT;
+ }
+
/*
* If the port is completely idle, then allow the new qc.
*/
@@ -1395,8 +1414,14 @@ static int mv_qc_defer(struct ata_queued_cmd *qc)
* doesn't allow it.
*/
if ((pp->pp_flags & MV_PP_FLAG_EDMA_EN) &&
- (pp->pp_flags & MV_PP_FLAG_NCQ_EN) && ata_is_ncq(qc->tf.protocol))
- return 0;
+ (pp->pp_flags & MV_PP_FLAG_NCQ_EN)) {
+ if (ata_is_ncq(qc->tf.protocol))
+ return 0;
+ else {
+ ap->excl_link = link;
+ return ATA_DEFER_PORT;
+ }
+ }
return ATA_DEFER_PORT;
}
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c
index 86a40582999c..1eb4e020eb5c 100644
--- a/drivers/ata/sata_nv.c
+++ b/drivers/ata/sata_nv.c
@@ -1594,9 +1594,21 @@ static int nv_hardreset(struct ata_link *link, unsigned int *class,
!ata_dev_enabled(link->device))
sata_link_hardreset(link, sata_deb_timing_hotplug, deadline,
NULL, NULL);
- else if (!(ehc->i.flags & ATA_EHI_QUIET))
- ata_link_printk(link, KERN_INFO,
- "nv: skipping hardreset on occupied port\n");
+ else {
+ const unsigned long *timing = sata_ehc_deb_timing(ehc);
+ int rc;
+
+ if (!(ehc->i.flags & ATA_EHI_QUIET))
+ ata_link_printk(link, KERN_INFO, "nv: skipping "
+ "hardreset on occupied port\n");
+
+ /* make sure the link is online */
+ rc = sata_link_resume(link, timing, deadline);
+ /* whine about phy resume failure but proceed */
+ if (rc && rc != -EOPNOTSUPP)
+ ata_link_printk(link, KERN_WARNING, "failed to resume "
+ "link (errno=%d)\n", rc);
+ }
/* device signature acquisition is unreliable */
return -EAGAIN;
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 973bf2ad4e0d..63c143e54a57 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -689,15 +689,19 @@ int bus_add_driver(struct device_driver *drv)
printk(KERN_ERR "%s: driver_add_attrs(%s) failed\n",
__func__, drv->name);
}
- error = add_bind_files(drv);
- if (error) {
- /* Ditto */
- printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
- __func__, drv->name);
+
+ if (!drv->suppress_bind_attrs) {
+ error = add_bind_files(drv);
+ if (error) {
+ /* Ditto */
+ printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
+ __func__, drv->name);
+ }
}
kobject_uevent(&priv->kobj, KOBJ_ADD);
return 0;
+
out_unregister:
kfree(drv->p);
drv->p = NULL;
@@ -720,7 +724,8 @@ void bus_remove_driver(struct device_driver *drv)
if (!drv->bus)
return;
- remove_bind_files(drv);
+ if (!drv->suppress_bind_attrs)
+ remove_bind_files(drv);
driver_remove_attrs(drv->bus, drv);
driver_remove_file(drv, &driver_attr_uevent);
klist_remove(&drv->p->knode_bus);
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index ed2ebd3c287d..f367885a7646 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -236,7 +236,7 @@ int driver_register(struct device_driver *drv)
put_driver(other);
printk(KERN_ERR "Error: Driver '%s' is already registered, "
"aborting...\n", drv->name);
- return -EEXIST;
+ return -EBUSY;
}
ret = bus_add_driver(drv);
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index ed156a13aa40..4fa954b07ac4 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -521,11 +521,15 @@ int __init_or_module platform_driver_probe(struct platform_driver *drv,
{
int retval, code;
+ /* make sure driver won't have bind/unbind attributes */
+ drv->driver.suppress_bind_attrs = true;
+
/* temporary section violation during probe() */
drv->probe = probe;
retval = code = platform_driver_register(drv);
- /* Fixup that section violation, being paranoid about code scanning
+ /*
+ * Fixup that section violation, being paranoid about code scanning
* the list of drivers in order to probe new devices. Check to see
* if the probe was successful, and make sure any forced probes of
* new devices fail.
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index e0dc4071e088..8aa2443182d5 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -511,6 +511,7 @@ static void dpm_complete(pm_message_t state)
INIT_LIST_HEAD(&list);
mutex_lock(&dpm_list_mtx);
+ transition_started = false;
while (!list_empty(&dpm_list)) {
struct device *dev = to_device(dpm_list.prev);
diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 38556f6cc22d..a770498a74ec 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -51,8 +51,6 @@ static int __pm_runtime_idle(struct device *dev)
{
int retval = 0;
- dev_dbg(dev, "__pm_runtime_idle()!\n");
-
if (dev->power.runtime_error)
retval = -EINVAL;
else if (dev->power.idle_notification)
@@ -93,8 +91,6 @@ static int __pm_runtime_idle(struct device *dev)
wake_up_all(&dev->power.wait_queue);
out:
- dev_dbg(dev, "__pm_runtime_idle() returns %d!\n", retval);
-
return retval;
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index edda9ea7c626..bd112c8c7bcd 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -949,7 +949,7 @@ static int loop_clr_fd(struct loop_device *lo, struct block_device *bdev)
lo->lo_state = Lo_unbound;
/* This is safe: open() is still holding a reference. */
module_put(THIS_MODULE);
- if (max_part > 0)
+ if (max_part > 0 && bdev)
ioctl_by_bdev(bdev, BLKRRPART, 0);
mutex_unlock(&lo->lo_ctl_mutex);
/*
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 43f19389647a..51042f0ba7e1 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -3,7 +3,6 @@
#include <linux/blkdev.h>
#include <linux/hdreg.h>
#include <linux/virtio.h>
-#include <linux/virtio_ids.h>
#include <linux/virtio_blk.h>
#include <linux/scatterlist.h>
@@ -183,34 +182,6 @@ static void do_virtblk_request(struct request_queue *q)
vblk->vq->vq_ops->kick(vblk->vq);
}
-/* return ATA identify data
- */
-static int virtblk_identify(struct gendisk *disk, void *argp)
-{
- struct virtio_blk *vblk = disk->private_data;
- void *opaque;
- int err = -ENOMEM;
-
- opaque = kmalloc(VIRTIO_BLK_ID_BYTES, GFP_KERNEL);
- if (!opaque)
- goto out;
-
- err = virtio_config_buf(vblk->vdev, VIRTIO_BLK_F_IDENTIFY,
- offsetof(struct virtio_blk_config, identify), opaque,
- VIRTIO_BLK_ID_BYTES);
-
- if (err)
- goto out_kfree;
-
- if (copy_to_user(argp, opaque, VIRTIO_BLK_ID_BYTES))
- err = -EFAULT;
-
-out_kfree:
- kfree(opaque);
-out:
- return err;
-}
-
static void virtblk_prepare_flush(struct request_queue *q, struct request *req)
{
req->cmd_type = REQ_TYPE_LINUX_BLOCK;
@@ -222,10 +193,6 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
{
struct gendisk *disk = bdev->bd_disk;
struct virtio_blk *vblk = disk->private_data;
- void __user *argp = (void __user *)data;
-
- if (cmd == HDIO_GET_IDENTITY)
- return virtblk_identify(disk, argp);
/*
* Only allow the generic SCSI ioctls if the host can support it.
@@ -233,7 +200,8 @@ static int virtblk_ioctl(struct block_device *bdev, fmode_t mode,
if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI))
return -ENOTTY;
- return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp);
+ return scsi_cmd_ioctl(disk->queue, disk, mode, cmd,
+ (void __user *)data);
}
/* We provide getgeo only to please some old bootloader/partitioning tools */
@@ -332,7 +300,6 @@ static int __devinit virtblk_probe(struct virtio_device *vdev)
}
vblk->disk->queue->queuedata = vblk;
- queue_flag_set_unlocked(QUEUE_FLAG_VIRT, vblk->disk->queue);
if (index < 26) {
sprintf(vblk->disk->disk_name, "vd%c", 'a' + index % 26);
@@ -445,7 +412,7 @@ static struct virtio_device_id id_table[] = {
static unsigned int features[] = {
VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
- VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY, VIRTIO_BLK_F_FLUSH
+ VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_FLUSH
};
/*
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 08a6f50ae791..6aad99ec4e0f 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -323,7 +323,7 @@ config SPECIALIX
config SX
tristate "Specialix SX (and SI) card support"
- depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
+ depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN
help
This is a driver for the SX and SI multiport serial cards.
Please read the file <file:Documentation/serial/sx.txt> for details.
@@ -334,7 +334,7 @@ config SX
config RIO
tristate "Specialix RIO system support"
- depends on SERIAL_NONSTANDARD
+ depends on SERIAL_NONSTANDARD && BROKEN
help
This is a driver for the Specialix RIO, a smart serial card which
drives an outboard box that can support up to 128 ports. Product
@@ -395,7 +395,7 @@ config NOZOMI
config A2232
tristate "Commodore A2232 serial support (EXPERIMENTAL)"
- depends on EXPERIMENTAL && ZORRO && BROKEN_ON_SMP
+ depends on EXPERIMENTAL && ZORRO && BROKEN
---help---
This option supports the 2232 7-port serial card shipped with the
Amiga 2000 and other Zorro-bus machines, dating from 1989. At
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c
index 962968f05b94..915157fcff98 100644
--- a/drivers/char/hw_random/virtio-rng.c
+++ b/drivers/char/hw_random/virtio-rng.c
@@ -21,7 +21,6 @@
#include <linux/scatterlist.h>
#include <linux/spinlock.h>
#include <linux/virtio.h>
-#include <linux/virtio_ids.h>
#include <linux/virtio_rng.h>
/* The host will fill any buffer we give it with sweet, sweet randomness. We
@@ -117,7 +116,7 @@ static int virtrng_probe(struct virtio_device *vdev)
return 0;
}
-static void virtrng_remove(struct virtio_device *vdev)
+static void __devexit virtrng_remove(struct virtio_device *vdev)
{
vdev->config->reset(vdev);
hwrng_unregister(&virtio_hwrng);
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 0d328b59568d..a035ae39a359 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -31,7 +31,6 @@
#include <linux/err.h>
#include <linux/init.h>
#include <linux/virtio.h>
-#include <linux/virtio_ids.h>
#include <linux/virtio_console.h>
#include "hvc_console.h"
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index ad41f19b8e3f..12fdd3987a36 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -76,8 +76,11 @@ static void cpuidle_idle_call(void)
#endif
/* ask the governor for the next state */
next_state = cpuidle_curr_governor->select(dev);
- if (need_resched())
+ if (need_resched()) {
+ local_irq_enable();
return;
+ }
+
target_state = &dev->states[next_state];
/* enter the state and update stats */
diff --git a/drivers/crypto/padlock-sha.c b/drivers/crypto/padlock-sha.c
index 76cb6b345e7b..0af80577dc7b 100644
--- a/drivers/crypto/padlock-sha.c
+++ b/drivers/crypto/padlock-sha.c
@@ -24,6 +24,12 @@
#include <asm/i387.h>
#include "padlock.h"
+#ifdef CONFIG_64BIT
+#define STACK_ALIGN 16
+#else
+#define STACK_ALIGN 4
+#endif
+
struct padlock_sha_desc {
struct shash_desc fallback;
};
@@ -64,7 +70,9 @@ static int padlock_sha1_finup(struct shash_desc *desc, const u8 *in,
/* We can't store directly to *out as it may be unaligned. */
/* BTW Don't reduce the buffer size below 128 Bytes!
* PadLock microcode needs it that big. */
- char result[128] __attribute__ ((aligned(PADLOCK_ALIGNMENT)));
+ char buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__
+ ((aligned(STACK_ALIGN)));
+ char *result = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
struct padlock_sha_desc *dctx = shash_desc_ctx(desc);
struct sha1_state state;
unsigned int space;
@@ -128,7 +136,9 @@ static int padlock_sha256_finup(struct shash_desc *desc, const u8 *in,
/* We can't store directly to *out as it may be unaligned. */
/* BTW Don't reduce the buffer size below 128 Bytes!
* PadLock microcode needs it that big. */
- char result[128] __attribute__ ((aligned(PADLOCK_ALIGNMENT)));
+ char buf[128 + PADLOCK_ALIGNMENT - STACK_ALIGN] __attribute__
+ ((aligned(STACK_ALIGN)));
+ char *result = PTR_ALIGN(&buf[0], PADLOCK_ALIGNMENT);
struct padlock_sha_desc *dctx = shash_desc_ctx(desc);
struct sha256_state state;
unsigned int space;
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index 4f4ac82382f7..d4560d9d5a83 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -1122,7 +1122,7 @@ static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
debugf0("Reading K8_DRAM_BASE_LOW failed\n");
/* Extract parts into separate data entries */
- pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 24;
+ pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8;
pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7;
pvt->dram_rw_en[dram] = (low & 0x3);
@@ -1135,7 +1135,7 @@ static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
* Extract parts into separate data entries. Limit is the HIGHEST memory
* location of the region, so lower 24 bits need to be all ones
*/
- pvt->dram_limit[dram] = (((u64) low & 0xFFFF0000) << 24) | 0x00FFFFFF;
+ pvt->dram_limit[dram] = (((u64) low & 0xFFFF0000) << 8) | 0x00FFFFFF;
pvt->dram_IntlvSel[dram] = (low >> 8) & 0x7;
pvt->dram_DstNode[dram] = (low & 0x7);
}
@@ -1369,7 +1369,7 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
pvt->dram_IntlvEn[dram] = (low_base >> 8) & 0x7;
pvt->dram_base[dram] = (((u64)high_base & 0x000000FF) << 40) |
- (((u64)low_base & 0xFFFF0000) << 24);
+ (((u64)low_base & 0xFFFF0000) << 8);
low_offset = K8_DRAM_LIMIT_LOW + (dram << 3);
high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3);
@@ -1391,7 +1391,7 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
* memory location of the region, so low 24 bits need to be all ones.
*/
pvt->dram_limit[dram] = (((u64)high_limit & 0x000000FF) << 40) |
- (((u64) low_limit & 0xFFFF0000) << 24) |
+ (((u64) low_limit & 0xFFFF0000) << 8) |
0x00FFFFFF;
}
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c
index d335086f4a26..77a9579d7167 100644
--- a/drivers/edac/i5000_edac.c
+++ b/drivers/edac/i5000_edac.c
@@ -1173,7 +1173,7 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci)
pci_read_config_word(pvt->branch_1, where,
&pvt->b1_mtr[slot_row]);
debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row,
- where, pvt->b0_mtr[slot_row]);
+ where, pvt->b1_mtr[slot_row]);
} else {
pvt->b1_mtr[slot_row] = 0;
}
@@ -1232,7 +1232,7 @@ static int i5000_init_csrows(struct mem_ctl_info *mci)
struct csrow_info *p_csrow;
int empty, channel_count;
int max_csrows;
- int mtr;
+ int mtr, mtr1;
int csrow_megs;
int channel;
int csrow;
@@ -1251,9 +1251,10 @@ static int i5000_init_csrows(struct mem_ctl_info *mci)
/* use branch 0 for the basis */
mtr = pvt->b0_mtr[csrow >> 1];
+ mtr1 = pvt->b1_mtr[csrow >> 1];
/* if no DIMMS on this row, continue */
- if (!MTR_DIMMS_PRESENT(mtr))
+ if (!MTR_DIMMS_PRESENT(mtr) && !MTR_DIMMS_PRESENT(mtr1))
continue;
/* FAKE OUT VALUES, FIXME */
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c
index b08b6d8e2dc7..f99d10655ed4 100644
--- a/drivers/edac/i5400_edac.c
+++ b/drivers/edac/i5400_edac.c
@@ -46,9 +46,10 @@
/* Limits for i5400 */
#define NUM_MTRS_PER_BRANCH 4
#define CHANNELS_PER_BRANCH 2
+#define MAX_DIMMS_PER_CHANNEL NUM_MTRS_PER_BRANCH
#define MAX_CHANNELS 4
-#define MAX_DIMMS (MAX_CHANNELS * 4) /* Up to 4 DIMM's per channel */
-#define MAX_CSROWS (MAX_DIMMS * 2) /* max possible csrows per channel */
+/* max possible csrows per channel */
+#define MAX_CSROWS (MAX_DIMMS_PER_CHANNEL)
/* Device 16,
* Function 0: System Address
@@ -331,7 +332,6 @@ static const struct i5400_dev_info i5400_devs[] = {
struct i5400_dimm_info {
int megabytes; /* size, 0 means not present */
- int dual_rank;
};
/* driver private data structure */
@@ -849,11 +849,9 @@ static int determine_mtr(struct i5400_pvt *pvt, int csrow, int channel)
int n;
/* There is one MTR for each slot pair of FB-DIMMs,
- Each slot may have one or two ranks (2 csrows),
Each slot pair may be at branch 0 or branch 1.
- So, csrow should be divided by eight
*/
- n = csrow >> 3;
+ n = csrow;
if (n >= NUM_MTRS_PER_BRANCH) {
debugf0("ERROR: trying to access an invalid csrow: %d\n",
@@ -905,25 +903,22 @@ static void handle_channel(struct i5400_pvt *pvt, int csrow, int channel,
amb_present_reg = determine_amb_present_reg(pvt, channel);
/* Determine if there is a DIMM present in this DIMM slot */
- if (amb_present_reg & (1 << (csrow >> 1))) {
- dinfo->dual_rank = MTR_DIMM_RANK(mtr);
-
- if (!((dinfo->dual_rank == 0) &&
- ((csrow & 0x1) == 0x1))) {
- /* Start with the number of bits for a Bank
- * on the DRAM */
- addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr);
- /* Add thenumber of ROW bits */
- addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
- /* add the number of COLUMN bits */
- addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
-
- addrBits += 6; /* add 64 bits per DIMM */
- addrBits -= 20; /* divide by 2^^20 */
- addrBits -= 3; /* 8 bits per bytes */
-
- dinfo->megabytes = 1 << addrBits;
- }
+ if (amb_present_reg & (1 << csrow)) {
+ /* Start with the number of bits for a Bank
+ * on the DRAM */
+ addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr);
+ /* Add thenumber of ROW bits */
+ addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr);
+ /* add the number of COLUMN bits */
+ addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
+ /* add the number of RANK bits */
+ addrBits += MTR_DIMM_RANK(mtr);
+
+ addrBits += 6; /* add 64 bits per DIMM */
+ addrBits -= 20; /* divide by 2^^20 */
+ addrBits -= 3; /* 8 bits per bytes */
+
+ dinfo->megabytes = 1 << addrBits;
}
}
}
@@ -951,12 +946,12 @@ static void calculate_dimm_size(struct i5400_pvt *pvt)
return;
}
- /* Scan all the actual CSROWS (which is # of DIMMS * 2)
+ /* Scan all the actual CSROWS
* and calculate the information for each DIMM
* Start with the highest csrow first, to display it first
* and work toward the 0th csrow
*/
- max_csrows = pvt->maxdimmperch * 2;
+ max_csrows = pvt->maxdimmperch;
for (csrow = max_csrows - 1; csrow >= 0; csrow--) {
/* on an odd csrow, first output a 'boundary' marker,
@@ -1064,7 +1059,7 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci)
/* Get the set of MTR[0-3] regs by each branch */
for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++) {
- int where = MTR0 + (slot_row * sizeof(u32));
+ int where = MTR0 + (slot_row * sizeof(u16));
/* Branch 0 set of MTR registers */
pci_read_config_word(pvt->branch_0, where,
@@ -1146,7 +1141,7 @@ static int i5400_init_csrows(struct mem_ctl_info *mci)
pvt = mci->pvt_info;
channel_count = pvt->maxch;
- max_csrows = pvt->maxdimmperch * 2;
+ max_csrows = pvt->maxdimmperch;
empty = 1; /* Assume NO memory */
@@ -1215,28 +1210,6 @@ static void i5400_enable_error_reporting(struct mem_ctl_info *mci)
}
/*
- * i5400_get_dimm_and_channel_counts(pdev, &num_csrows, &num_channels)
- *
- * ask the device how many channels are present and how many CSROWS
- * as well
- */
-static void i5400_get_dimm_and_channel_counts(struct pci_dev *pdev,
- int *num_dimms_per_channel,
- int *num_channels)
-{
- u8 value;
-
- /* Need to retrieve just how many channels and dimms per channel are
- * supported on this memory controller
- */
- pci_read_config_byte(pdev, MAXDIMMPERCH, &value);
- *num_dimms_per_channel = (int)value * 2;
-
- pci_read_config_byte(pdev, MAXCH, &value);
- *num_channels = (int)value;
-}
-
-/*
* i5400_probe1 Probe for ONE instance of device to see if it is
* present.
* return:
@@ -1263,22 +1236,16 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx)
if (PCI_FUNC(pdev->devfn) != 0)
return -ENODEV;
- /* Ask the devices for the number of CSROWS and CHANNELS so
- * that we can calculate the memory resources, etc
- *
- * The Chipset will report what it can handle which will be greater
- * or equal to what the motherboard manufacturer will implement.
- *
- * As we don't have a motherboard identification routine to determine
+ /* As we don't have a motherboard identification routine to determine
* actual number of slots/dimms per channel, we thus utilize the
* resource as specified by the chipset. Thus, we might have
* have more DIMMs per channel than actually on the mobo, but this
* allows the driver to support upto the chipset max, without
* some fancy mobo determination.
*/
- i5400_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel,
- &num_channels);
- num_csrows = num_dimms_per_channel * 2;
+ num_dimms_per_channel = MAX_DIMMS_PER_CHANNEL;
+ num_channels = MAX_CHANNELS;
+ num_csrows = num_dimms_per_channel;
debugf0("MC: %s(): Number of - Channels= %d DIMMS= %d CSROWS= %d\n",
__func__, num_channels, num_dimms_per_channel, num_csrows);
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index 157f6504f25e..cf27402af97b 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -26,7 +26,9 @@
#include "mpc85xx_edac.h"
static int edac_dev_idx;
+#ifdef CONFIG_PCI
static int edac_pci_idx;
+#endif
static int edac_mc_idx;
static u32 orig_ddr_err_disable;
diff --git a/drivers/gpio/twl4030-gpio.c b/drivers/gpio/twl4030-gpio.c
index afad14792141..49384a7c5492 100644
--- a/drivers/gpio/twl4030-gpio.c
+++ b/drivers/gpio/twl4030-gpio.c
@@ -460,7 +460,8 @@ no_irqs:
return ret;
}
-static int __devexit gpio_twl4030_remove(struct platform_device *pdev)
+/* Cannot use __devexit as gpio_twl4030_probe() calls us */
+static int gpio_twl4030_remove(struct platform_device *pdev)
{
struct twl4030_gpio_platform_data *pdata = pdev->dev.platform_data;
int status;
@@ -493,7 +494,7 @@ static struct platform_driver gpio_twl4030_driver = {
.driver.name = "twl4030_gpio",
.driver.owner = THIS_MODULE,
.probe = gpio_twl4030_probe,
- .remove = __devexit_p(gpio_twl4030_remove),
+ .remove = gpio_twl4030_remove,
};
static int __init gpio_twl4030_init(void)
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index 3c0d2b3aed76..cea665d86dd3 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -626,6 +626,12 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
return NULL;
}
+ /* it is incorrect if hsync/vsync width is zero */
+ if (!hsync_pulse_width || !vsync_pulse_width) {
+ DRM_DEBUG_KMS("Incorrect Detailed timing. "
+ "Wrong Hsync/Vsync pulse width\n");
+ return NULL;
+ }
mode = drm_mode_create(dev);
if (!mode)
return NULL;
@@ -647,6 +653,15 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev,
mode->vsync_end = mode->vsync_start + vsync_pulse_width;
mode->vtotal = mode->vdisplay + vblank;
+ /* perform the basic check for the detailed timing */
+ if (mode->hsync_end > mode->htotal ||
+ mode->vsync_end > mode->vtotal) {
+ drm_mode_destroy(dev, mode);
+ DRM_DEBUG_KMS("Incorrect detailed timing. "
+ "Sync is beyond the blank.\n");
+ return NULL;
+ }
+
drm_mode_set_name(mode);
if (pt->misc & DRM_EDID_PT_INTERLACED)
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index 23dc9c115fd9..9c924614c418 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -454,22 +454,39 @@ out_free:
}
EXPORT_SYMBOL(drm_fb_helper_init_crtc_count);
-static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
+static int setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, u16 regno, struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
struct drm_framebuffer *fb = fb_helper->fb;
int pindex;
+ if (info->fix.visual == FB_VISUAL_TRUECOLOR) {
+ u32 *palette;
+ u32 value;
+ /* place color in psuedopalette */
+ if (regno > 16)
+ return -EINVAL;
+ palette = (u32 *)info->pseudo_palette;
+ red >>= (16 - info->var.red.length);
+ green >>= (16 - info->var.green.length);
+ blue >>= (16 - info->var.blue.length);
+ value = (red << info->var.red.offset) |
+ (green << info->var.green.offset) |
+ (blue << info->var.blue.offset);
+ palette[regno] = value;
+ return 0;
+ }
+
pindex = regno;
if (fb->bits_per_pixel == 16) {
pindex = regno << 3;
if (fb->depth == 16 && regno > 63)
- return;
+ return -EINVAL;
if (fb->depth == 15 && regno > 31)
- return;
+ return -EINVAL;
if (fb->depth == 16) {
u16 r, g, b;
@@ -493,13 +510,7 @@ static void setcolreg(struct drm_crtc *crtc, u16 red, u16 green,
if (fb->depth != 16)
fb_helper->funcs->gamma_set(crtc, red, green, blue, pindex);
-
- if (regno < 16 && info->fix.visual == FB_VISUAL_DIRECTCOLOR) {
- ((u32 *) fb->pseudo_palette)[regno] =
- (regno << info->var.red.offset) |
- (regno << info->var.green.offset) |
- (regno << info->var.blue.offset);
- }
+ return 0;
}
int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
@@ -536,7 +547,9 @@ int drm_fb_helper_setcmap(struct fb_cmap *cmap, struct fb_info *info)
if (transp)
htransp = *transp++;
- setcolreg(crtc, hred, hgreen, hblue, start++, info);
+ rc = setcolreg(crtc, hred, hgreen, hblue, start++, info);
+ if (rc)
+ return rc;
}
crtc_funcs->load_lut(crtc);
}
@@ -555,6 +568,7 @@ int drm_fb_helper_setcolreg(unsigned regno,
struct drm_device *dev = fb_helper->dev;
struct drm_crtc *crtc;
int i;
+ int ret;
if (regno > 255)
return 1;
@@ -568,8 +582,10 @@ int drm_fb_helper_setcolreg(unsigned regno,
if (i == fb_helper->crtc_count)
continue;
+ ret = setcolreg(crtc, red, green, blue, regno, info);
+ if (ret)
+ return ret;
- setcolreg(crtc, red, green, blue, regno, info);
crtc_funcs->load_lut(crtc);
}
return 0;
@@ -928,7 +944,7 @@ void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
{
info->fix.type = FB_TYPE_PACKED_PIXELS;
info->fix.visual = depth == 8 ? FB_VISUAL_PSEUDOCOLOR :
- FB_VISUAL_DIRECTCOLOR;
+ FB_VISUAL_TRUECOLOR;
info->fix.type_aux = 0;
info->fix.xpanstep = 1; /* doing it in hw */
info->fix.ypanstep = 1; /* doing it in hw */
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index b93814c0d3e2..7f436ec075f6 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -89,7 +89,8 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
pci_set_power_state(dev->pdev, PCI_D3hot);
}
- dev_priv->suspended = 1;
+ /* Modeset on resume, not lid events */
+ dev_priv->modeset_on_lid = 0;
return 0;
}
@@ -124,7 +125,7 @@ static int i915_resume(struct drm_device *dev)
drm_helper_resume_force_mode(dev);
}
- dev_priv->suspended = 0;
+ dev_priv->modeset_on_lid = 0;
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 6035d3dae851..c5df2234418d 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -274,7 +274,7 @@ typedef struct drm_i915_private {
struct drm_i915_display_funcs display;
/* Register state */
- bool suspended;
+ bool modeset_on_lid;
u8 saveLBB;
u32 saveDSPACNTR;
u32 saveDSPBCNTR;
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 98ae3d73577e..808bbe412ba8 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -656,6 +656,15 @@ static int intel_lvds_get_modes(struct drm_connector *connector)
return 0;
}
+/*
+ * Lid events. Note the use of 'modeset_on_lid':
+ * - we set it on lid close, and reset it on open
+ * - we use it as a "only once" bit (ie we ignore
+ * duplicate events where it was already properly
+ * set/reset)
+ * - the suspend/resume paths will also set it to
+ * zero, since they restore the mode ("lid open").
+ */
static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
void *unused)
{
@@ -663,13 +672,19 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
container_of(nb, struct drm_i915_private, lid_notifier);
struct drm_device *dev = dev_priv->dev;
- if (acpi_lid_open() && !dev_priv->suspended) {
- mutex_lock(&dev->mode_config.mutex);
- drm_helper_resume_force_mode(dev);
- mutex_unlock(&dev->mode_config.mutex);
+ if (!acpi_lid_open()) {
+ dev_priv->modeset_on_lid = 1;
+ return NOTIFY_OK;
}
- drm_sysfs_hotplug_event(dev_priv->dev);
+ if (!dev_priv->modeset_on_lid)
+ return NOTIFY_OK;
+
+ dev_priv->modeset_on_lid = 0;
+
+ mutex_lock(&dev->mode_config.mutex);
+ drm_helper_resume_force_mode(dev);
+ mutex_unlock(&dev->mode_config.mutex);
return NOTIFY_OK;
}
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index 3d667031de6e..df988142e6b0 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -582,10 +582,9 @@ int radeon_device_init(struct radeon_device *rdev,
DRM_INFO("register mmio size: %u\n", (unsigned)rdev->rmmio_size);
/* if we have > 1 VGA cards, then disable the radeon VGA resources */
- r = vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
- if (r) {
- return -EINVAL;
- }
+ /* this will fail for cards that aren't VGA class devices, just
+ * ignore it */
+ vga_client_register(rdev->pdev, rdev, NULL, radeon_vga_set_decode);
r = radeon_init(rdev);
if (r)
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
index 2c2cb1ec94c5..27d62574284f 100644
--- a/drivers/hwmon/dme1737.c
+++ b/drivers/hwmon/dme1737.c
@@ -572,7 +572,7 @@ static struct dme1737_data *dme1737_update_device(struct device *dev)
/* Sample register contents every 1 sec */
if (time_after(jiffies, data->last_update + HZ) || !data->valid) {
- if (data->type != sch5027) {
+ if (data->type == dme1737) {
data->vid = dme1737_read(data, DME1737_REG_VID) &
0x3f;
}
@@ -1621,9 +1621,6 @@ static struct attribute *dme1737_misc_attr[] = {
&sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr,
&sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr,
&sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr,
- /* Misc */
- &dev_attr_vrm.attr,
- &dev_attr_cpu0_vid.attr,
NULL
};
@@ -1631,6 +1628,18 @@ static const struct attribute_group dme1737_misc_group = {
.attrs = dme1737_misc_attr,
};
+/* The following struct holds VID-related attributes. Their creation
+ depends on the chip type which is determined during module load. */
+static struct attribute *dme1737_vid_attr[] = {
+ &dev_attr_vrm.attr,
+ &dev_attr_cpu0_vid.attr,
+ NULL
+};
+
+static const struct attribute_group dme1737_vid_group = {
+ .attrs = dme1737_vid_attr,
+};
+
/* The following structs hold the PWM attributes, some of which are optional.
* Their creation depends on the chip configuration which is determined during
* module load. */
@@ -1902,6 +1911,9 @@ static void dme1737_remove_files(struct device *dev)
if (data->type != sch5027) {
sysfs_remove_group(&dev->kobj, &dme1737_misc_group);
}
+ if (data->type == dme1737) {
+ sysfs_remove_group(&dev->kobj, &dme1737_vid_group);
+ }
sysfs_remove_group(&dev->kobj, &dme1737_group);
@@ -1933,6 +1945,13 @@ static int dme1737_create_files(struct device *dev)
goto exit_remove;
}
+ /* Create VID-related sysfs attributes */
+ if ((data->type == dme1737) &&
+ (err = sysfs_create_group(&dev->kobj,
+ &dme1737_vid_group))) {
+ goto exit_remove;
+ }
+
/* Create fan sysfs attributes */
for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {
if (data->has_fan & (1 << ix)) {
@@ -2127,7 +2146,7 @@ static int dme1737_init_device(struct device *dev)
data->pwm_acz[2] = 4; /* pwm3 -> zone3 */
/* Set VRM */
- if (data->type != sch5027) {
+ if (data->type == dme1737) {
data->vrm = vid_which_vrm();
}
diff --git a/drivers/hwmon/fschmd.c b/drivers/hwmon/fschmd.c
index 2a7a85a6dc36..da1b1f9488af 100644
--- a/drivers/hwmon/fschmd.c
+++ b/drivers/hwmon/fschmd.c
@@ -819,7 +819,7 @@ static int watchdog_release(struct inode *inode, struct file *filp)
static ssize_t watchdog_write(struct file *filp, const char __user *buf,
size_t count, loff_t *offset)
{
- size_t ret;
+ int ret;
struct fschmd_data *data = filp->private_data;
if (count) {
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c
index 6679854c85b0..be475e844c2a 100644
--- a/drivers/hwmon/hp_accel.c
+++ b/drivers/hwmon/hp_accel.c
@@ -197,11 +197,13 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
AXIS_DMI_MATCH("HP2133", "HP 2133", xy_rotated_left),
AXIS_DMI_MATCH("HP2140", "HP 2140", xy_swap_inverted),
AXIS_DMI_MATCH("NC653x", "HP Compaq 653", xy_rotated_left_usd),
- AXIS_DMI_MATCH("NC673x", "HP Compaq 673", xy_rotated_left_usd),
+ AXIS_DMI_MATCH("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd),
+ AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap),
AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
AXIS_DMI_MATCH("NC6710x", "HP Compaq 6710", xy_swap_yz_inverted),
AXIS_DMI_MATCH("NC6715x", "HP Compaq 6715", y_inverted),
AXIS_DMI_MATCH("NC693xx", "HP EliteBook 693", xy_rotated_right),
+ AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
/* Intel-based HP Pavilion dv5 */
AXIS_DMI_MATCH2("HPDV5_I",
PRODUCT_NAME, "HP Pavilion dv5",
@@ -214,6 +216,7 @@ static struct dmi_system_id lis3lv02d_dmi_ids[] = {
y_inverted),
AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted),
AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted),
+ AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted),
{ NULL, }
/* Laptop models without axis info (yet):
* "NC6910" "HP Compaq 6910"
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index ffeb2a10e1a7..a3749cb0f181 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -1028,12 +1028,11 @@ static int __init it87_find(unsigned short *address,
chip_type, *address, sio_data->revision);
/* Read GPIO config and VID value from LDN 7 (GPIO) */
- if (chip_type != IT8705F_DEVID) {
+ if (sio_data->type != it87) {
int reg;
superio_select(GPIO);
- if ((chip_type == it8718) ||
- (chip_type == it8720))
+ if (sio_data->type == it8718 || sio_data->type == it8720)
sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
reg = superio_inb(IT87_SIO_PINX2_REG);
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 4afba3ec2a61..e3654d683e15 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -120,19 +120,26 @@ struct imx_i2c_struct {
wait_queue_head_t queue;
unsigned long i2csr;
unsigned int disable_delay;
+ int stopped;
+ unsigned int ifdr; /* IMX_I2C_IFDR */
};
/** Functions for IMX I2C adapter driver ***************************************
*******************************************************************************/
-static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy)
{
unsigned long orig_jiffies = jiffies;
+ unsigned int temp;
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
- /* wait for bus not busy */
- while (readb(i2c_imx->base + IMX_I2C_I2SR) & I2SR_IBB) {
+ while (1) {
+ temp = readb(i2c_imx->base + IMX_I2C_I2SR);
+ if (for_busy && (temp & I2SR_IBB))
+ break;
+ if (!for_busy && !(temp & I2SR_IBB))
+ break;
if (signal_pending(current)) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> I2C Interrupted\n", __func__);
@@ -179,41 +186,62 @@ static int i2c_imx_acked(struct imx_i2c_struct *i2c_imx)
return 0;
}
-static void i2c_imx_start(struct imx_i2c_struct *i2c_imx)
+static int i2c_imx_start(struct imx_i2c_struct *i2c_imx)
{
unsigned int temp = 0;
+ int result;
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
+ clk_enable(i2c_imx->clk);
+ writeb(i2c_imx->ifdr, i2c_imx->base + IMX_I2C_IFDR);
/* Enable I2C controller */
+ writeb(0, i2c_imx->base + IMX_I2C_I2SR);
writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
+
+ /* Wait controller to be stable */
+ udelay(50);
+
/* Start I2C transaction */
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
temp |= I2CR_MSTA;
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ result = i2c_imx_bus_busy(i2c_imx, 1);
+ if (result)
+ return result;
+ i2c_imx->stopped = 0;
+
temp |= I2CR_IIEN | I2CR_MTX | I2CR_TXAK;
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ return result;
}
static void i2c_imx_stop(struct imx_i2c_struct *i2c_imx)
{
unsigned int temp = 0;
- /* Stop I2C transaction */
- dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
- temp = readb(i2c_imx->base + IMX_I2C_I2CR);
- temp &= ~I2CR_MSTA;
- writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
- /* setup chip registers to defaults */
- writeb(I2CR_IEN, i2c_imx->base + IMX_I2C_I2CR);
- writeb(0, i2c_imx->base + IMX_I2C_I2SR);
- /*
- * This delay caused by an i.MXL hardware bug.
- * If no (or too short) delay, no "STOP" bit will be generated.
- */
- udelay(i2c_imx->disable_delay);
+ if (!i2c_imx->stopped) {
+ /* Stop I2C transaction */
+ dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
+ temp = readb(i2c_imx->base + IMX_I2C_I2CR);
+ temp &= ~(I2CR_MSTA | I2CR_MTX);
+ writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ i2c_imx->stopped = 1;
+ }
+ if (cpu_is_mx1()) {
+ /*
+ * This delay caused by an i.MXL hardware bug.
+ * If no (or too short) delay, no "STOP" bit will be generated.
+ */
+ udelay(i2c_imx->disable_delay);
+ }
+
+ if (!i2c_imx->stopped)
+ i2c_imx_bus_busy(i2c_imx, 0);
+
/* Disable I2C controller */
writeb(0, i2c_imx->base + IMX_I2C_I2CR);
+ clk_disable(i2c_imx->clk);
}
static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
@@ -233,8 +261,8 @@ static void __init i2c_imx_set_clk(struct imx_i2c_struct *i2c_imx,
else
for (i = 0; i2c_clk_div[i][0] < div; i++);
- /* Write divider value to register */
- writeb(i2c_clk_div[i][1], i2c_imx->base + IMX_I2C_IFDR);
+ /* Store divider value */
+ i2c_imx->ifdr = i2c_clk_div[i][1];
/*
* There dummy delay is calculated.
@@ -341,11 +369,15 @@ static int i2c_imx_read(struct imx_i2c_struct *i2c_imx, struct i2c_msg *msgs)
if (result)
return result;
if (i == (msgs->len - 1)) {
+ /* It must generate STOP before read I2DR to prevent
+ controller from generating another clock cycle */
dev_dbg(&i2c_imx->adapter.dev,
"<%s> clear MSTA\n", __func__);
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
- temp &= ~I2CR_MSTA;
+ temp &= ~(I2CR_MSTA | I2CR_MTX);
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ i2c_imx_bus_busy(i2c_imx, 0);
+ i2c_imx->stopped = 1;
} else if (i == (msgs->len - 2)) {
dev_dbg(&i2c_imx->adapter.dev,
"<%s> set TXAK\n", __func__);
@@ -370,14 +402,11 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
dev_dbg(&i2c_imx->adapter.dev, "<%s>\n", __func__);
- /* Check if i2c bus is not busy */
- result = i2c_imx_bus_busy(i2c_imx);
+ /* Start I2C transfer */
+ result = i2c_imx_start(i2c_imx);
if (result)
goto fail0;
- /* Start I2C transfer */
- i2c_imx_start(i2c_imx);
-
/* read/write data */
for (i = 0; i < num; i++) {
if (i) {
@@ -386,6 +415,9 @@ static int i2c_imx_xfer(struct i2c_adapter *adapter,
temp = readb(i2c_imx->base + IMX_I2C_I2CR);
temp |= I2CR_RSTA;
writeb(temp, i2c_imx->base + IMX_I2C_I2CR);
+ result = i2c_imx_bus_busy(i2c_imx, 1);
+ if (result)
+ goto fail0;
}
dev_dbg(&i2c_imx->adapter.dev,
"<%s> transfer message: %d\n", __func__, i);
@@ -500,7 +532,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "can't get I2C clock\n");
goto fail3;
}
- clk_enable(i2c_imx->clk);
/* Request IRQ */
ret = request_irq(i2c_imx->irq, i2c_imx_isr, 0, pdev->name, i2c_imx);
@@ -549,7 +580,6 @@ static int __init i2c_imx_probe(struct platform_device *pdev)
fail5:
free_irq(i2c_imx->irq, i2c_imx);
fail4:
- clk_disable(i2c_imx->clk);
clk_put(i2c_imx->clk);
fail3:
release_mem_region(i2c_imx->res->start, resource_size(res));
@@ -586,8 +616,6 @@ static int __exit i2c_imx_remove(struct platform_device *pdev)
if (pdata && pdata->exit)
pdata->exit(&pdev->dev);
- /* Disable I2C clock */
- clk_disable(i2c_imx->clk);
clk_put(i2c_imx->clk);
release_mem_region(i2c_imx->res->start, resource_size(i2c_imx->res));
diff --git a/drivers/i2c/busses/i2c-mpc.c b/drivers/i2c/busses/i2c-mpc.c
index d325e86e3103..f627001108b8 100644
--- a/drivers/i2c/busses/i2c-mpc.c
+++ b/drivers/i2c/busses/i2c-mpc.c
@@ -365,9 +365,6 @@ static int mpc_write(struct mpc_i2c *i2c, int target,
unsigned timeout = i2c->adap.timeout;
u32 flags = restart ? CCR_RSTA : 0;
- /* Start with MEN */
- if (!restart)
- writeccr(i2c, CCR_MEN);
/* Start as master */
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
/* Write target byte */
@@ -396,9 +393,6 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
int i, result;
u32 flags = restart ? CCR_RSTA : 0;
- /* Start with MEN */
- if (!restart)
- writeccr(i2c, CCR_MEN);
/* Switch to read - restart */
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX | flags);
/* Write target address byte - this time with the read flag set */
@@ -425,9 +419,9 @@ static int mpc_read(struct mpc_i2c *i2c, int target,
/* Generate txack on next to last byte */
if (i == length - 2)
writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_TXAK);
- /* Generate stop on last byte */
+ /* Do not generate stop on last byte */
if (i == length - 1)
- writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_TXAK);
+ writeccr(i2c, CCR_MIEN | CCR_MEN | CCR_MSTA | CCR_MTX);
data[i] = readb(i2c->base + MPC_I2C_DR);
}
diff --git a/drivers/ide/atiixp.c b/drivers/ide/atiixp.c
index 6396c3ad3252..837322b10a4c 100644
--- a/drivers/ide/atiixp.c
+++ b/drivers/ide/atiixp.c
@@ -177,7 +177,7 @@ static const struct pci_device_id atiixp_pci_tbl[] = {
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP400_IDE), 0 },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP600_IDE), 1 },
{ PCI_VDEVICE(ATI, PCI_DEVICE_ID_ATI_IXP700_IDE), 0 },
- { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_SB900_IDE), 0 },
+ { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_HUDSON2_IDE), 0 },
{ 0, },
};
MODULE_DEVICE_TABLE(pci, atiixp_pci_tbl);
diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c
index 680e5975217f..ca0c46f6580a 100644
--- a/drivers/ide/cmd64x.c
+++ b/drivers/ide/cmd64x.c
@@ -379,7 +379,8 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.enablebits = {{0x00,0x00,0x00}, {0x51,0x08,0x08}},
.port_ops = &cmd64x_port_ops,
.host_flags = IDE_HFLAG_CLEAR_SIMPLEX |
- IDE_HFLAG_ABUSE_PREFETCH,
+ IDE_HFLAG_ABUSE_PREFETCH |
+ IDE_HFLAG_SERIALIZE,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = 0x00, /* no udma */
@@ -389,7 +390,8 @@ static const struct ide_port_info cmd64x_chipsets[] __devinitdata = {
.init_chipset = init_chipset_cmd64x,
.enablebits = {{0x51,0x04,0x04}, {0x51,0x08,0x08}},
.port_ops = &cmd648_port_ops,
- .host_flags = IDE_HFLAG_ABUSE_PREFETCH,
+ .host_flags = IDE_HFLAG_ABUSE_PREFETCH |
+ IDE_HFLAG_SERIALIZE,
.pio_mask = ATA_PIO5,
.mwdma_mask = ATA_MWDMA2,
.udma_mask = ATA_UDMA2,
diff --git a/drivers/input/input.c b/drivers/input/input.c
index c6f88ebb40c7..cc763c96fada 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -782,10 +782,29 @@ static unsigned int input_proc_devices_poll(struct file *file, poll_table *wait)
return 0;
}
+union input_seq_state {
+ struct {
+ unsigned short pos;
+ bool mutex_acquired;
+ };
+ void *p;
+};
+
static void *input_devices_seq_start(struct seq_file *seq, loff_t *pos)
{
- if (mutex_lock_interruptible(&input_mutex))
- return NULL;
+ union input_seq_state *state = (union input_seq_state *)&seq->private;
+ int error;
+
+ /* We need to fit into seq->private pointer */
+ BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private));
+
+ error = mutex_lock_interruptible(&input_mutex);
+ if (error) {
+ state->mutex_acquired = false;
+ return ERR_PTR(error);
+ }
+
+ state->mutex_acquired = true;
return seq_list_start(&input_dev_list, *pos);
}
@@ -795,9 +814,12 @@ static void *input_devices_seq_next(struct seq_file *seq, void *v, loff_t *pos)
return seq_list_next(v, &input_dev_list, pos);
}
-static void input_devices_seq_stop(struct seq_file *seq, void *v)
+static void input_seq_stop(struct seq_file *seq, void *v)
{
- mutex_unlock(&input_mutex);
+ union input_seq_state *state = (union input_seq_state *)&seq->private;
+
+ if (state->mutex_acquired)
+ mutex_unlock(&input_mutex);
}
static void input_seq_print_bitmap(struct seq_file *seq, const char *name,
@@ -861,7 +883,7 @@ static int input_devices_seq_show(struct seq_file *seq, void *v)
static const struct seq_operations input_devices_seq_ops = {
.start = input_devices_seq_start,
.next = input_devices_seq_next,
- .stop = input_devices_seq_stop,
+ .stop = input_seq_stop,
.show = input_devices_seq_show,
};
@@ -881,40 +903,49 @@ static const struct file_operations input_devices_fileops = {
static void *input_handlers_seq_start(struct seq_file *seq, loff_t *pos)
{
- if (mutex_lock_interruptible(&input_mutex))
- return NULL;
+ union input_seq_state *state = (union input_seq_state *)&seq->private;
+ int error;
+
+ /* We need to fit into seq->private pointer */
+ BUILD_BUG_ON(sizeof(union input_seq_state) != sizeof(seq->private));
+
+ error = mutex_lock_interruptible(&input_mutex);
+ if (error) {
+ state->mutex_acquired = false;
+ return ERR_PTR(error);
+ }
+
+ state->mutex_acquired = true;
+ state->pos = *pos;
- seq->private = (void *)(unsigned long)*pos;
return seq_list_start(&input_handler_list, *pos);
}
static void *input_handlers_seq_next(struct seq_file *seq, void *v, loff_t *pos)
{
- seq->private = (void *)(unsigned long)(*pos + 1);
- return seq_list_next(v, &input_handler_list, pos);
-}
+ union input_seq_state *state = (union input_seq_state *)&seq->private;
-static void input_handlers_seq_stop(struct seq_file *seq, void *v)
-{
- mutex_unlock(&input_mutex);
+ state->pos = *pos + 1;
+ return seq_list_next(v, &input_handler_list, pos);
}
static int input_handlers_seq_show(struct seq_file *seq, void *v)
{
struct input_handler *handler = container_of(v, struct input_handler, node);
+ union input_seq_state *state = (union input_seq_state *)&seq->private;
- seq_printf(seq, "N: Number=%ld Name=%s",
- (unsigned long)seq->private, handler->name);
+ seq_printf(seq, "N: Number=%u Name=%s", state->pos, handler->name);
if (handler->fops)
seq_printf(seq, " Minor=%d", handler->minor);
seq_putc(seq, '\n');
return 0;
}
+
static const struct seq_operations input_handlers_seq_ops = {
.start = input_handlers_seq_start,
.next = input_handlers_seq_next,
- .stop = input_handlers_seq_stop,
+ .stop = input_seq_stop,
.show = input_handlers_seq_show,
};
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index 4709e15af607..4452eabbee6d 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -233,6 +233,7 @@ struct atkbd {
*/
static void (*atkbd_platform_fixup)(struct atkbd *, const void *data);
static void *atkbd_platform_fixup_data;
+static unsigned int (*atkbd_platform_scancode_fixup)(struct atkbd *, unsigned int);
static ssize_t atkbd_attr_show_helper(struct device *dev, char *buf,
ssize_t (*handler)(struct atkbd *, char *));
@@ -393,6 +394,9 @@ static irqreturn_t atkbd_interrupt(struct serio *serio, unsigned char data,
input_event(dev, EV_MSC, MSC_RAW, code);
+ if (atkbd_platform_scancode_fixup)
+ code = atkbd_platform_scancode_fixup(atkbd, code);
+
if (atkbd->translated) {
if (atkbd->emul || atkbd_need_xlate(atkbd->xl_bit, code)) {
@@ -574,11 +578,22 @@ static void atkbd_event_work(struct work_struct *work)
mutex_lock(&atkbd->event_mutex);
- if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
- atkbd_set_leds(atkbd);
+ if (!atkbd->enabled) {
+ /*
+ * Serio ports are resumed asynchronously so while driver core
+ * thinks that device is already fully operational in reality
+ * it may not be ready yet. In this case we need to keep
+ * rescheduling till reconnect completes.
+ */
+ schedule_delayed_work(&atkbd->event_work,
+ msecs_to_jiffies(100));
+ } else {
+ if (test_and_clear_bit(ATKBD_LED_EVENT_BIT, &atkbd->event_mask))
+ atkbd_set_leds(atkbd);
- if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
- atkbd_set_repeat_rate(atkbd);
+ if (test_and_clear_bit(ATKBD_REP_EVENT_BIT, &atkbd->event_mask))
+ atkbd_set_repeat_rate(atkbd);
+ }
mutex_unlock(&atkbd->event_mutex);
}
@@ -770,6 +785,30 @@ static int atkbd_select_set(struct atkbd *atkbd, int target_set, int allow_extra
return 3;
}
+static int atkbd_reset_state(struct atkbd *atkbd)
+{
+ struct ps2dev *ps2dev = &atkbd->ps2dev;
+ unsigned char param[1];
+
+/*
+ * Set the LEDs to a predefined state (all off).
+ */
+
+ param[0] = 0;
+ if (ps2_command(ps2dev, param, ATKBD_CMD_SETLEDS))
+ return -1;
+
+/*
+ * Set autorepeat to fastest possible.
+ */
+
+ param[0] = 0;
+ if (ps2_command(ps2dev, param, ATKBD_CMD_SETREP))
+ return -1;
+
+ return 0;
+}
+
static int atkbd_activate(struct atkbd *atkbd)
{
struct ps2dev *ps2dev = &atkbd->ps2dev;
@@ -852,29 +891,6 @@ static unsigned int atkbd_hp_forced_release_keys[] = {
};
/*
- * Inventec system with broken key release on volume keys
- */
-static unsigned int atkbd_inventec_forced_release_keys[] = {
- 0xae, 0xb0, -1U
-};
-
-/*
- * Perform fixup for HP Pavilion ZV6100 laptop that doesn't generate release
- * for its volume buttons
- */
-static unsigned int atkbd_hp_zv6100_forced_release_keys[] = {
- 0xae, 0xb0, -1U
-};
-
-/*
- * Perform fixup for HP (Compaq) Presario R4000 R4100 R4200 that don't generate
- * release for their volume buttons
- */
-static unsigned int atkbd_hp_r4000_forced_release_keys[] = {
- 0xae, 0xb0, -1U
-};
-
-/*
* Samsung NC10,NC20 with Fn+F? key release not working
*/
static unsigned int atkbd_samsung_forced_release_keys[] = {
@@ -882,14 +898,6 @@ static unsigned int atkbd_samsung_forced_release_keys[] = {
};
/*
- * The volume up and volume down special keys on a Fujitsu Amilo PA 1510 laptop
- * do not generate release events so we have to do it ourselves.
- */
-static unsigned int atkbd_amilo_pa1510_forced_release_keys[] = {
- 0xb0, 0xae, -1U
-};
-
-/*
* Amilo Pi 3525 key release for Fn+Volume keys not working
*/
static unsigned int atkbd_amilo_pi3525_forced_release_keys[] = {
@@ -911,6 +919,30 @@ static unsigned int atkdb_soltech_ta12_forced_release_keys[] = {
};
/*
+ * Many notebooks don't send key release event for volume up/down
+ * keys, with key list below common among them
+ */
+static unsigned int atkbd_volume_forced_release_keys[] = {
+ 0xae, 0xb0, -1U
+};
+
+/*
+ * OQO 01+ multimedia keys (64--66) generate e0 6x upon release whereas
+ * they should be generating e4-e6 (0x80 | code).
+ */
+static unsigned int atkbd_oqo_01plus_scancode_fixup(struct atkbd *atkbd,
+ unsigned int code)
+{
+ if (atkbd->translated && atkbd->emul == 1 &&
+ (code == 0x64 || code == 0x65 || code == 0x66)) {
+ atkbd->emul = 0;
+ code |= 0x80;
+ }
+
+ return code;
+}
+
+/*
* atkbd_set_keycode_table() initializes keyboard's keycode table
* according to the selected scancode set
*/
@@ -1087,6 +1119,7 @@ static int atkbd_connect(struct serio *serio, struct serio_driver *drv)
}
atkbd->set = atkbd_select_set(atkbd, atkbd_set, atkbd_extra);
+ atkbd_reset_state(atkbd);
atkbd_activate(atkbd);
} else {
@@ -1267,6 +1300,7 @@ static ssize_t atkbd_set_extra(struct atkbd *atkbd, const char *buf, size_t coun
atkbd->dev = new_dev;
atkbd->set = atkbd_select_set(atkbd, atkbd->set, value);
+ atkbd_reset_state(atkbd);
atkbd_activate(atkbd);
atkbd_set_keycode_table(atkbd);
atkbd_set_device_attrs(atkbd);
@@ -1513,6 +1547,13 @@ static int __init atkbd_setup_forced_release(const struct dmi_system_id *id)
return 0;
}
+static int __init atkbd_setup_scancode_fixup(const struct dmi_system_id *id)
+{
+ atkbd_platform_scancode_fixup = id->driver_data;
+
+ return 0;
+}
+
static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
{
.ident = "Dell Laptop",
@@ -1548,7 +1589,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Pavilion ZV6100"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_hp_zv6100_forced_release_keys,
+ .driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "HP Presario R4000",
@@ -1557,7 +1598,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4000"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_hp_r4000_forced_release_keys,
+ .driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "HP Presario R4100",
@@ -1566,7 +1607,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4100"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_hp_r4000_forced_release_keys,
+ .driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "HP Presario R4200",
@@ -1575,7 +1616,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "Presario R4200"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_hp_r4000_forced_release_keys,
+ .driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "Inventec Symphony",
@@ -1584,7 +1625,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "SYMPHONY 6.0/7.0"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_inventec_forced_release_keys,
+ .driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "Samsung NC10",
@@ -1620,7 +1661,7 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "AMILO Pa 1510"),
},
.callback = atkbd_setup_forced_release,
- .driver_data = atkbd_amilo_pa1510_forced_release_keys,
+ .driver_data = atkbd_volume_forced_release_keys,
},
{
.ident = "Fujitsu Amilo Pi 3525",
@@ -1649,6 +1690,15 @@ static struct dmi_system_id atkbd_dmi_quirk_table[] __initdata = {
.callback = atkbd_setup_forced_release,
.driver_data = atkdb_soltech_ta12_forced_release_keys,
},
+ {
+ .ident = "OQO Model 01+",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "OQO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "ZEPTO"),
+ },
+ .callback = atkbd_setup_scancode_fixup,
+ .driver_data = atkbd_oqo_01plus_scancode_fixup,
+ },
{ }
};
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index a88aff3816a0..77d130914259 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -147,6 +147,7 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
}
error = request_irq(irq, gpio_keys_isr,
+ IRQF_SHARED |
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
button->desc ? button->desc : "gpio_keys",
bdata);
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
index 02f4f8f1db6f..a9bb2544b2de 100644
--- a/drivers/input/misc/Kconfig
+++ b/drivers/input/misc/Kconfig
@@ -227,6 +227,7 @@ config INPUT_WINBOND_CIR
depends on X86 && PNP
select NEW_LEDS
select LEDS_CLASS
+ select LEDS_TRIGGERS
select BITREVERSE
help
Say Y here if you want to use the IR remote functionality found
diff --git a/drivers/input/misc/hp_sdc_rtc.c b/drivers/input/misc/hp_sdc_rtc.c
index 216a559f55ea..ea821b546969 100644
--- a/drivers/input/misc/hp_sdc_rtc.c
+++ b/drivers/input/misc/hp_sdc_rtc.c
@@ -209,7 +209,7 @@ static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
/* Read the i8042 fast handshake timer */
static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
- uint64_t raw;
+ int64_t raw;
unsigned int tenms;
raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_FHS, 2);
diff --git a/drivers/input/mouse/logips2pp.c b/drivers/input/mouse/logips2pp.c
index de745d751162..ab5dc5f5fd83 100644
--- a/drivers/input/mouse/logips2pp.c
+++ b/drivers/input/mouse/logips2pp.c
@@ -219,7 +219,7 @@ static const struct ps2pp_info *get_model_info(unsigned char model)
PS2PP_WHEEL | PS2PP_SIDE_BTN | PS2PP_TASK_BTN |
PS2PP_EXTRA_BTN | PS2PP_NAV_BTN | PS2PP_HWHEEL },
{ 72, PS2PP_KIND_TRACKMAN, 0 }, /* T-CH11: TrackMan Marble */
- { 73, 0, PS2PP_SIDE_BTN },
+ { 73, PS2PP_KIND_TRACKMAN, PS2PP_SIDE_BTN }, /* TrackMan FX */
{ 75, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 76, PS2PP_KIND_WHEEL, PS2PP_WHEEL },
{ 79, PS2PP_KIND_TRACKMAN, PS2PP_WHEEL }, /* TrackMan with wheel */
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c
index b66ff1ac7dea..f4a61252bcc9 100644
--- a/drivers/input/mouse/synaptics.c
+++ b/drivers/input/mouse/synaptics.c
@@ -652,6 +652,16 @@ static const struct dmi_system_id toshiba_dmi_table[] = {
DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
DMI_MATCH(DMI_PRODUCT_NAME, "PORTEGE M300"),
},
+
+ },
+ {
+ .ident = "Toshiba Portege M300",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Portable PC"),
+ DMI_MATCH(DMI_PRODUCT_VERSION, "Version 1.0"),
+ },
+
},
{ }
};
diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h
index a39bc4eb902b..a537925f7651 100644
--- a/drivers/input/serio/i8042-x86ia64io.h
+++ b/drivers/input/serio/i8042-x86ia64io.h
@@ -327,6 +327,17 @@ static struct dmi_system_id __initdata i8042_dmi_nomux_table[] = {
},
},
{
+ /*
+ * Reset and GET ID commands issued via KBD port are
+ * sometimes being delivered to AUX3.
+ */
+ .ident = "Sony Vaio FZ-240E",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FZ240E"),
+ },
+ },
+ {
.ident = "Amoi M636/A737",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Amoi Electronics CO.,LTD."),
@@ -661,7 +672,7 @@ static void i8042_pnp_exit(void)
static int __init i8042_pnp_init(void)
{
char kbd_irq_str[4] = { 0 }, aux_irq_str[4] = { 0 };
- int pnp_data_busted = false;
+ bool pnp_data_busted = false;
int err;
#ifdef CONFIG_X86
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index a31578170ccc..1df02d25aca5 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -836,17 +836,32 @@ static int i8042_controller_selftest(void)
static int i8042_controller_init(void)
{
unsigned long flags;
+ int n = 0;
+ unsigned char ctr[2];
/*
- * Save the CTR for restoral on unload / reboot.
+ * Save the CTR for restore on unload / reboot.
*/
- if (i8042_command(&i8042_ctr, I8042_CMD_CTL_RCTR)) {
- printk(KERN_ERR "i8042.c: Can't read CTR while initializing i8042.\n");
- return -EIO;
- }
+ do {
+ if (n >= 10) {
+ printk(KERN_ERR
+ "i8042.c: Unable to get stable CTR read.\n");
+ return -EIO;
+ }
+
+ if (n != 0)
+ udelay(50);
+
+ if (i8042_command(&ctr[n++ % 2], I8042_CMD_CTL_RCTR)) {
+ printk(KERN_ERR
+ "i8042.c: Can't read CTR while initializing i8042.\n");
+ return -EIO;
+ }
- i8042_initial_ctr = i8042_ctr;
+ } while (n < 2 || ctr[0] != ctr[1]);
+
+ i8042_initial_ctr = i8042_ctr = ctr[0];
/*
* Disable the keyboard interface and interrupt.
@@ -895,6 +910,12 @@ static int i8042_controller_init(void)
return -EIO;
}
+/*
+ * Flush whatever accumulated while we were disabling keyboard port.
+ */
+
+ i8042_flush();
+
return 0;
}
@@ -914,7 +935,7 @@ static void i8042_controller_reset(void)
i8042_ctr |= I8042_CTR_KBDDIS | I8042_CTR_AUXDIS;
i8042_ctr &= ~(I8042_CTR_KBDINT | I8042_CTR_AUXINT);
- if (i8042_command(&i8042_initial_ctr, I8042_CMD_CTL_WCTR))
+ if (i8042_command(&i8042_ctr, I8042_CMD_CTL_WCTR))
printk(KERN_WARNING "i8042.c: Can't write CTR while resetting.\n");
/*
diff --git a/drivers/isdn/i4l/isdn_net.h b/drivers/isdn/i4l/isdn_net.h
index 74032d0881ef..7511f08effa5 100644
--- a/drivers/isdn/i4l/isdn_net.h
+++ b/drivers/isdn/i4l/isdn_net.h
@@ -83,19 +83,19 @@ static __inline__ isdn_net_local * isdn_net_get_locked_lp(isdn_net_dev *nd)
spin_lock_irqsave(&nd->queue_lock, flags);
lp = nd->queue; /* get lp on top of queue */
- spin_lock(&nd->queue->xmit_lock);
while (isdn_net_lp_busy(nd->queue)) {
- spin_unlock(&nd->queue->xmit_lock);
nd->queue = nd->queue->next;
if (nd->queue == lp) { /* not found -- should never happen */
lp = NULL;
goto errout;
}
- spin_lock(&nd->queue->xmit_lock);
}
lp = nd->queue;
nd->queue = nd->queue->next;
+ spin_unlock_irqrestore(&nd->queue_lock, flags);
+ spin_lock(&lp->xmit_lock);
local_bh_disable();
+ return lp;
errout:
spin_unlock_irqrestore(&nd->queue_lock, flags);
return lp;
diff --git a/drivers/md/Makefile b/drivers/md/Makefile
index 1dc4185bd781..e355e7f6a536 100644
--- a/drivers/md/Makefile
+++ b/drivers/md/Makefile
@@ -46,7 +46,7 @@ obj-$(CONFIG_DM_LOG_USERSPACE) += dm-log-userspace.o
obj-$(CONFIG_DM_ZERO) += dm-zero.o
quiet_cmd_unroll = UNROLL $@
- cmd_unroll = $(PERL) $(srctree)/$(src)/unroll.pl $(UNROLL) \
+ cmd_unroll = $(AWK) -f$(srctree)/$(src)/unroll.awk -vN=$(UNROLL) \
< $< > $@ || ( rm -f $@ && exit 1 )
ifeq ($(CONFIG_ALTIVEC),y)
@@ -59,56 +59,56 @@ endif
targets += raid6int1.c
$(obj)/raid6int1.c: UNROLL := 1
-$(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int1.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
targets += raid6int2.c
$(obj)/raid6int2.c: UNROLL := 2
-$(obj)/raid6int2.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int2.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
targets += raid6int4.c
$(obj)/raid6int4.c: UNROLL := 4
-$(obj)/raid6int4.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int4.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
targets += raid6int8.c
$(obj)/raid6int8.c: UNROLL := 8
-$(obj)/raid6int8.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int8.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
targets += raid6int16.c
$(obj)/raid6int16.c: UNROLL := 16
-$(obj)/raid6int16.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int16.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
targets += raid6int32.c
$(obj)/raid6int32.c: UNROLL := 32
-$(obj)/raid6int32.c: $(src)/raid6int.uc $(src)/unroll.pl FORCE
+$(obj)/raid6int32.c: $(src)/raid6int.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
CFLAGS_raid6altivec1.o += $(altivec_flags)
targets += raid6altivec1.c
$(obj)/raid6altivec1.c: UNROLL := 1
-$(obj)/raid6altivec1.c: $(src)/raid6altivec.uc $(src)/unroll.pl FORCE
+$(obj)/raid6altivec1.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
CFLAGS_raid6altivec2.o += $(altivec_flags)
targets += raid6altivec2.c
$(obj)/raid6altivec2.c: UNROLL := 2
-$(obj)/raid6altivec2.c: $(src)/raid6altivec.uc $(src)/unroll.pl FORCE
+$(obj)/raid6altivec2.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
CFLAGS_raid6altivec4.o += $(altivec_flags)
targets += raid6altivec4.c
$(obj)/raid6altivec4.c: UNROLL := 4
-$(obj)/raid6altivec4.c: $(src)/raid6altivec.uc $(src)/unroll.pl FORCE
+$(obj)/raid6altivec4.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
CFLAGS_raid6altivec8.o += $(altivec_flags)
targets += raid6altivec8.c
$(obj)/raid6altivec8.c: UNROLL := 8
-$(obj)/raid6altivec8.c: $(src)/raid6altivec.uc $(src)/unroll.pl FORCE
+$(obj)/raid6altivec8.c: $(src)/raid6altivec.uc $(src)/unroll.awk FORCE
$(call if_changed,unroll)
quiet_cmd_mktable = TABLE $@
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c
index 6986b0059d23..60e2b322db11 100644
--- a/drivers/md/bitmap.c
+++ b/drivers/md/bitmap.c
@@ -1624,10 +1624,11 @@ int bitmap_create(mddev_t *mddev)
bitmap->offset = mddev->bitmap_offset;
if (file) {
get_file(file);
- do_sync_mapping_range(file->f_mapping, 0, LLONG_MAX,
- SYNC_FILE_RANGE_WAIT_BEFORE |
- SYNC_FILE_RANGE_WRITE |
- SYNC_FILE_RANGE_WAIT_AFTER);
+ /* As future accesses to this file will use bmap,
+ * and bypass the page cache, we must sync the file
+ * first.
+ */
+ vfs_fsync(file, file->f_dentry, 1);
}
/* read superblock from bitmap file (this sets bitmap->chunksize) */
err = bitmap_read_sb(bitmap);
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c
index 556acff3952f..7dbe652efb5a 100644
--- a/drivers/md/dm-exception-store.c
+++ b/drivers/md/dm-exception-store.c
@@ -138,16 +138,6 @@ int dm_exception_store_type_unregister(struct dm_exception_store_type *type)
}
EXPORT_SYMBOL(dm_exception_store_type_unregister);
-/*
- * Round a number up to the nearest 'size' boundary. size must
- * be a power of 2.
- */
-static ulong round_up(ulong n, ulong size)
-{
- size--;
- return (n + size) & ~size;
-}
-
static int set_chunk_size(struct dm_exception_store *store,
const char *chunk_size_arg, char **error)
{
@@ -155,7 +145,8 @@ static int set_chunk_size(struct dm_exception_store *store,
char *value;
chunk_size_ulong = simple_strtoul(chunk_size_arg, &value, 10);
- if (*chunk_size_arg == '\0' || *value != '\0') {
+ if (*chunk_size_arg == '\0' || *value != '\0' ||
+ chunk_size_ulong > UINT_MAX) {
*error = "Invalid chunk size";
return -EINVAL;
}
@@ -165,40 +156,35 @@ static int set_chunk_size(struct dm_exception_store *store,
return 0;
}
- /*
- * Chunk size must be multiple of page size. Silently
- * round up if it's not.
- */
- chunk_size_ulong = round_up(chunk_size_ulong, PAGE_SIZE >> 9);
-
- return dm_exception_store_set_chunk_size(store, chunk_size_ulong,
+ return dm_exception_store_set_chunk_size(store,
+ (unsigned) chunk_size_ulong,
error);
}
int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
- unsigned long chunk_size_ulong,
+ unsigned chunk_size,
char **error)
{
/* Check chunk_size is a power of 2 */
- if (!is_power_of_2(chunk_size_ulong)) {
+ if (!is_power_of_2(chunk_size)) {
*error = "Chunk size is not a power of 2";
return -EINVAL;
}
/* Validate the chunk size against the device block size */
- if (chunk_size_ulong % (bdev_logical_block_size(store->cow->bdev) >> 9)) {
+ if (chunk_size % (bdev_logical_block_size(store->cow->bdev) >> 9)) {
*error = "Chunk size is not a multiple of device blocksize";
return -EINVAL;
}
- if (chunk_size_ulong > INT_MAX >> SECTOR_SHIFT) {
+ if (chunk_size > INT_MAX >> SECTOR_SHIFT) {
*error = "Chunk size is too high";
return -EINVAL;
}
- store->chunk_size = chunk_size_ulong;
- store->chunk_mask = chunk_size_ulong - 1;
- store->chunk_shift = ffs(chunk_size_ulong) - 1;
+ store->chunk_size = chunk_size;
+ store->chunk_mask = chunk_size - 1;
+ store->chunk_shift = ffs(chunk_size) - 1;
return 0;
}
@@ -251,7 +237,7 @@ int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
r = set_chunk_size(tmp_store, argv[2], &ti->error);
if (r)
- goto bad_cow;
+ goto bad_ctr;
r = type->ctr(tmp_store, 0, NULL);
if (r) {
diff --git a/drivers/md/dm-exception-store.h b/drivers/md/dm-exception-store.h
index 812c71872ba0..8a223a48802c 100644
--- a/drivers/md/dm-exception-store.h
+++ b/drivers/md/dm-exception-store.h
@@ -101,9 +101,9 @@ struct dm_exception_store {
struct dm_dev *cow;
/* Size of data blocks saved - must be a power of 2 */
- chunk_t chunk_size;
- chunk_t chunk_mask;
- chunk_t chunk_shift;
+ unsigned chunk_size;
+ unsigned chunk_mask;
+ unsigned chunk_shift;
void *context;
};
@@ -169,7 +169,7 @@ int dm_exception_store_type_register(struct dm_exception_store_type *type);
int dm_exception_store_type_unregister(struct dm_exception_store_type *type);
int dm_exception_store_set_chunk_size(struct dm_exception_store *store,
- unsigned long chunk_size_ulong,
+ unsigned chunk_size,
char **error);
int dm_exception_store_create(struct dm_target *ti, int argc, char **argv,
diff --git a/drivers/md/dm-log-userspace-base.c b/drivers/md/dm-log-userspace-base.c
index 652bd33109e3..7ac2c1450d10 100644
--- a/drivers/md/dm-log-userspace-base.c
+++ b/drivers/md/dm-log-userspace-base.c
@@ -156,7 +156,7 @@ static int userspace_ctr(struct dm_dirty_log *log, struct dm_target *ti,
}
/* The ptr value is sufficient for local unique id */
- lc->luid = (uint64_t)lc;
+ lc->luid = (unsigned long)lc;
lc->ti = ti;
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c
index d5b2e08750d5..0c746420c008 100644
--- a/drivers/md/dm-snap-persistent.c
+++ b/drivers/md/dm-snap-persistent.c
@@ -284,12 +284,13 @@ static int read_header(struct pstore *ps, int *new_snapshot)
{
int r;
struct disk_header *dh;
- chunk_t chunk_size;
+ unsigned chunk_size;
int chunk_size_supplied = 1;
char *chunk_err;
/*
- * Use default chunk size (or hardsect_size, if larger) if none supplied
+ * Use default chunk size (or logical_block_size, if larger)
+ * if none supplied
*/
if (!ps->store->chunk_size) {
ps->store->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS,
@@ -334,10 +335,9 @@ static int read_header(struct pstore *ps, int *new_snapshot)
return 0;
if (chunk_size_supplied)
- DMWARN("chunk size %llu in device metadata overrides "
- "table chunk size of %llu.",
- (unsigned long long)chunk_size,
- (unsigned long long)ps->store->chunk_size);
+ DMWARN("chunk size %u in device metadata overrides "
+ "table chunk size of %u.",
+ chunk_size, ps->store->chunk_size);
/* We had a bogus chunk_size. Fix stuff up. */
free_area(ps);
@@ -345,8 +345,8 @@ static int read_header(struct pstore *ps, int *new_snapshot)
r = dm_exception_store_set_chunk_size(ps->store, chunk_size,
&chunk_err);
if (r) {
- DMERR("invalid on-disk chunk size %llu: %s.",
- (unsigned long long)chunk_size, chunk_err);
+ DMERR("invalid on-disk chunk size %u: %s.",
+ chunk_size, chunk_err);
return r;
}
diff --git a/drivers/md/dm-snap.c b/drivers/md/dm-snap.c
index 57f1bf7f3b7a..3a3ba46e6d4b 100644
--- a/drivers/md/dm-snap.c
+++ b/drivers/md/dm-snap.c
@@ -296,6 +296,7 @@ static void __insert_origin(struct origin *o)
*/
static int register_snapshot(struct dm_snapshot *snap)
{
+ struct dm_snapshot *l;
struct origin *o, *new_o;
struct block_device *bdev = snap->origin->bdev;
@@ -319,7 +320,11 @@ static int register_snapshot(struct dm_snapshot *snap)
__insert_origin(o);
}
- list_add_tail(&snap->list, &o->snapshots);
+ /* Sort the list according to chunk size, largest-first smallest-last */
+ list_for_each_entry(l, &o->snapshots, list)
+ if (l->store->chunk_size < snap->store->chunk_size)
+ break;
+ list_add_tail(&snap->list, &l->list);
up_write(&_origins_lock);
return 0;
@@ -668,6 +673,11 @@ static int snapshot_ctr(struct dm_target *ti, unsigned int argc, char **argv)
bio_list_init(&s->queued_bios);
INIT_WORK(&s->queued_bios_work, flush_queued_bios);
+ if (!s->store->chunk_size) {
+ ti->error = "Chunk size not set";
+ goto bad_load_and_register;
+ }
+
/* Add snapshot to the list of snapshots for this origin */
/* Exceptions aren't triggered till snapshot_resume() is called */
if (register_snapshot(s)) {
@@ -951,7 +961,7 @@ static void start_copy(struct dm_snap_pending_exception *pe)
src.bdev = bdev;
src.sector = chunk_to_sector(s->store, pe->e.old_chunk);
- src.count = min(s->store->chunk_size, dev_size - src.sector);
+ src.count = min((sector_t)s->store->chunk_size, dev_size - src.sector);
dest.bdev = s->store->cow->bdev;
dest.sector = chunk_to_sector(s->store, pe->e.new_chunk);
@@ -1142,6 +1152,8 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
unsigned sz = 0;
struct dm_snapshot *snap = ti->private;
+ down_write(&snap->lock);
+
switch (type) {
case STATUSTYPE_INFO:
if (!snap->valid)
@@ -1173,6 +1185,8 @@ static int snapshot_status(struct dm_target *ti, status_type_t type,
break;
}
+ up_write(&snap->lock);
+
return 0;
}
@@ -1388,7 +1402,7 @@ static void origin_resume(struct dm_target *ti)
struct dm_dev *dev = ti->private;
struct dm_snapshot *snap;
struct origin *o;
- chunk_t chunk_size = 0;
+ unsigned chunk_size = 0;
down_read(&_origins_lock);
o = __lookup_origin(dev->bdev);
@@ -1465,7 +1479,7 @@ static int __init dm_snapshot_init(void)
r = dm_register_target(&snapshot_target);
if (r) {
DMERR("snapshot target register failed %d", r);
- return r;
+ goto bad_register_snapshot_target;
}
r = dm_register_target(&origin_target);
@@ -1522,6 +1536,9 @@ bad2:
dm_unregister_target(&origin_target);
bad1:
dm_unregister_target(&snapshot_target);
+
+bad_register_snapshot_target:
+ dm_exception_store_exit();
return r;
}
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 376f1ab48a24..724efc63904d 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -47,6 +47,7 @@ struct dm_io {
atomic_t io_count;
struct bio *bio;
unsigned long start_time;
+ spinlock_t endio_lock;
};
/*
@@ -578,8 +579,12 @@ static void dec_pending(struct dm_io *io, int error)
struct mapped_device *md = io->md;
/* Push-back supersedes any I/O errors */
- if (error && !(io->error > 0 && __noflush_suspending(md)))
- io->error = error;
+ if (unlikely(error)) {
+ spin_lock_irqsave(&io->endio_lock, flags);
+ if (!(io->error > 0 && __noflush_suspending(md)))
+ io->error = error;
+ spin_unlock_irqrestore(&io->endio_lock, flags);
+ }
if (atomic_dec_and_test(&io->io_count)) {
if (io->error == DM_ENDIO_REQUEUE) {
@@ -1226,6 +1231,7 @@ static void __split_and_process_bio(struct mapped_device *md, struct bio *bio)
atomic_set(&ci.io->io_count, 1);
ci.io->bio = bio;
ci.io->md = md;
+ spin_lock_init(&ci.io->endio_lock);
ci.sector = bio->bi_sector;
ci.sector_count = bio_sectors(bio);
if (unlikely(bio_empty_barrier(bio)))
@@ -1822,6 +1828,7 @@ static struct mapped_device *alloc_dev(int minor)
bad_bdev:
destroy_workqueue(md->wq);
bad_thread:
+ del_gendisk(md->disk);
put_disk(md->disk);
bad_disk:
blk_cleanup_queue(md->queue);
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 26ba42a79129..10eb1fce975e 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2631,7 +2631,7 @@ static void analyze_sbs(mddev_t * mddev)
rdev->desc_nr = i++;
rdev->raid_disk = rdev->desc_nr;
set_bit(In_sync, &rdev->flags);
- } else if (rdev->raid_disk >= mddev->raid_disks) {
+ } else if (rdev->raid_disk >= (mddev->raid_disks - min(0, mddev->delta_disks))) {
rdev->raid_disk = -1;
clear_bit(In_sync, &rdev->flags);
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index d1b9bd5fd4f6..a053423785c9 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -64,7 +64,7 @@ static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
/* allocate a r1bio with room for raid_disks entries in the bios array */
r1_bio = kzalloc(size, gfp_flags);
- if (!r1_bio)
+ if (!r1_bio && pi->mddev)
unplug_slaves(pi->mddev);
return r1_bio;
@@ -1683,6 +1683,7 @@ static void raid1d(mddev_t *mddev)
generic_make_request(bio);
}
}
+ cond_resched();
}
if (unplug)
unplug_slaves(mddev);
@@ -1978,13 +1979,14 @@ static int run(mddev_t *mddev)
conf->poolinfo = kmalloc(sizeof(*conf->poolinfo), GFP_KERNEL);
if (!conf->poolinfo)
goto out_no_mem;
- conf->poolinfo->mddev = mddev;
+ conf->poolinfo->mddev = NULL;
conf->poolinfo->raid_disks = mddev->raid_disks;
conf->r1bio_pool = mempool_create(NR_RAID1_BIOS, r1bio_pool_alloc,
r1bio_pool_free,
conf->poolinfo);
if (!conf->r1bio_pool)
goto out_no_mem;
+ conf->poolinfo->mddev = mddev;
spin_lock_init(&conf->device_lock);
mddev->queue->queue_lock = &conf->device_lock;
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 51c4c5c4d87a..c2cb7b87b440 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -68,7 +68,7 @@ static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
/* allocate a r10bio with room for raid_disks entries in the bios array */
r10_bio = kzalloc(size, gfp_flags);
- if (!r10_bio)
+ if (!r10_bio && conf->mddev)
unplug_slaves(conf->mddev);
return r10_bio;
@@ -1632,6 +1632,7 @@ static void raid10d(mddev_t *mddev)
generic_make_request(bio);
}
}
+ cond_resched();
}
if (unplug)
unplug_slaves(mddev);
@@ -2095,7 +2096,6 @@ static int run(mddev_t *mddev)
if (!conf->tmppage)
goto out_free_conf;
- conf->mddev = mddev;
conf->raid_disks = mddev->raid_disks;
conf->near_copies = nc;
conf->far_copies = fc;
@@ -2132,6 +2132,7 @@ static int run(mddev_t *mddev)
goto out_free_conf;
}
+ conf->mddev = mddev;
spin_lock_init(&conf->device_lock);
mddev->queue->queue_lock = &conf->device_lock;
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 94829804ab7f..81abefc172d9 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -156,13 +156,16 @@ static inline int raid6_next_disk(int disk, int raid_disks)
static int raid6_idx_to_slot(int idx, struct stripe_head *sh,
int *count, int syndrome_disks)
{
- int slot;
+ int slot = *count;
+ if (sh->ddf_layout)
+ (*count)++;
if (idx == sh->pd_idx)
return syndrome_disks;
if (idx == sh->qd_idx)
return syndrome_disks + 1;
- slot = (*count)++;
+ if (!sh->ddf_layout)
+ (*count)++;
return slot;
}
@@ -717,7 +720,7 @@ static int set_syndrome_sources(struct page **srcs, struct stripe_head *sh)
int i;
for (i = 0; i < disks; i++)
- srcs[i] = (void *)raid6_empty_zero_page;
+ srcs[i] = NULL;
count = 0;
i = d0_idx;
@@ -727,9 +730,8 @@ static int set_syndrome_sources(struct page **srcs, struct stripe_head *sh)
srcs[slot] = sh->dev[i].page;
i = raid6_next_disk(i, disks);
} while (i != d0_idx);
- BUG_ON(count != syndrome_disks);
- return count;
+ return syndrome_disks;
}
static struct dma_async_tx_descriptor *
@@ -814,7 +816,7 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)
* slot number conversion for 'faila' and 'failb'
*/
for (i = 0; i < disks ; i++)
- blocks[i] = (void *)raid6_empty_zero_page;
+ blocks[i] = NULL;
count = 0;
i = d0_idx;
do {
@@ -828,7 +830,6 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)
failb = slot;
i = raid6_next_disk(i, disks);
} while (i != d0_idx);
- BUG_ON(count != syndrome_disks);
BUG_ON(faila == failb);
if (failb < faila)
@@ -845,7 +846,7 @@ ops_run_compute6_2(struct stripe_head *sh, struct raid5_percpu *percpu)
init_async_submit(&submit, ASYNC_TX_FENCE, NULL,
ops_complete_compute, sh,
to_addr_conv(sh, percpu));
- return async_gen_syndrome(blocks, 0, count+2,
+ return async_gen_syndrome(blocks, 0, syndrome_disks+2,
STRIPE_SIZE, &submit);
} else {
struct page *dest;
@@ -1139,7 +1140,7 @@ static void ops_run_check_pq(struct stripe_head *sh, struct raid5_percpu *percpu
&sh->ops.zero_sum_result, percpu->spare_page, &submit);
}
-static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
+static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
{
int overlap_clear = 0, i, disks = sh->disks;
struct dma_async_tx_descriptor *tx = NULL;
@@ -1204,22 +1205,55 @@ static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
put_cpu();
}
+#ifdef CONFIG_MULTICORE_RAID456
+static void async_run_ops(void *param, async_cookie_t cookie)
+{
+ struct stripe_head *sh = param;
+ unsigned long ops_request = sh->ops.request;
+
+ clear_bit_unlock(STRIPE_OPS_REQ_PENDING, &sh->state);
+ wake_up(&sh->ops.wait_for_ops);
+
+ __raid_run_ops(sh, ops_request);
+ release_stripe(sh);
+}
+
+static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request)
+{
+ /* since handle_stripe can be called outside of raid5d context
+ * we need to ensure sh->ops.request is de-staged before another
+ * request arrives
+ */
+ wait_event(sh->ops.wait_for_ops,
+ !test_and_set_bit_lock(STRIPE_OPS_REQ_PENDING, &sh->state));
+ sh->ops.request = ops_request;
+
+ atomic_inc(&sh->count);
+ async_schedule(async_run_ops, sh);
+}
+#else
+#define raid_run_ops __raid_run_ops
+#endif
+
static int grow_one_stripe(raid5_conf_t *conf)
{
struct stripe_head *sh;
+ int disks = max(conf->raid_disks, conf->previous_raid_disks);
sh = kmem_cache_alloc(conf->slab_cache, GFP_KERNEL);
if (!sh)
return 0;
- memset(sh, 0, sizeof(*sh) + (conf->raid_disks-1)*sizeof(struct r5dev));
+ memset(sh, 0, sizeof(*sh) + (disks-1)*sizeof(struct r5dev));
sh->raid_conf = conf;
spin_lock_init(&sh->lock);
+ #ifdef CONFIG_MULTICORE_RAID456
+ init_waitqueue_head(&sh->ops.wait_for_ops);
+ #endif
- if (grow_buffers(sh, conf->raid_disks)) {
- shrink_buffers(sh, conf->raid_disks);
+ if (grow_buffers(sh, disks)) {
+ shrink_buffers(sh, disks);
kmem_cache_free(conf->slab_cache, sh);
return 0;
}
- sh->disks = conf->raid_disks;
/* we just created an active stripe so... */
atomic_set(&sh->count, 1);
atomic_inc(&conf->active_stripes);
@@ -1231,7 +1265,7 @@ static int grow_one_stripe(raid5_conf_t *conf)
static int grow_stripes(raid5_conf_t *conf, int num)
{
struct kmem_cache *sc;
- int devs = conf->raid_disks;
+ int devs = max(conf->raid_disks, conf->previous_raid_disks);
sprintf(conf->cache_name[0],
"raid%d-%s", conf->level, mdname(conf->mddev));
@@ -1329,6 +1363,9 @@ static int resize_stripes(raid5_conf_t *conf, int newsize)
nsh->raid_conf = conf;
spin_lock_init(&nsh->lock);
+ #ifdef CONFIG_MULTICORE_RAID456
+ init_waitqueue_head(&nsh->ops.wait_for_ops);
+ #endif
list_add(&nsh->lru, &newstripes);
}
@@ -1899,10 +1936,15 @@ static sector_t compute_blocknr(struct stripe_head *sh, int i, int previous)
case ALGORITHM_PARITY_N:
break;
case ALGORITHM_ROTATING_N_CONTINUE:
+ /* Like left_symmetric, but P is before Q */
if (sh->pd_idx == 0)
i--; /* P D D D Q */
- else if (i > sh->pd_idx)
- i -= 2; /* D D Q P D */
+ else {
+ /* D D Q P D */
+ if (i < sh->pd_idx)
+ i += raid_disks;
+ i -= (sh->pd_idx + 1);
+ }
break;
case ALGORITHM_LEFT_ASYMMETRIC_6:
case ALGORITHM_RIGHT_ASYMMETRIC_6:
@@ -2896,7 +2938,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh,
*
*/
-static bool handle_stripe5(struct stripe_head *sh)
+static void handle_stripe5(struct stripe_head *sh)
{
raid5_conf_t *conf = sh->raid_conf;
int disks = sh->disks, i;
@@ -3167,11 +3209,9 @@ static bool handle_stripe5(struct stripe_head *sh)
ops_run_io(sh, &s);
return_io(return_bi);
-
- return blocked_rdev == NULL;
}
-static bool handle_stripe6(struct stripe_head *sh)
+static void handle_stripe6(struct stripe_head *sh)
{
raid5_conf_t *conf = sh->raid_conf;
int disks = sh->disks;
@@ -3455,17 +3495,14 @@ static bool handle_stripe6(struct stripe_head *sh)
ops_run_io(sh, &s);
return_io(return_bi);
-
- return blocked_rdev == NULL;
}
-/* returns true if the stripe was handled */
-static bool handle_stripe(struct stripe_head *sh)
+static void handle_stripe(struct stripe_head *sh)
{
if (sh->raid_conf->level == 6)
- return handle_stripe6(sh);
+ handle_stripe6(sh);
else
- return handle_stripe5(sh);
+ handle_stripe5(sh);
}
static void raid5_activate_delayed(raid5_conf_t *conf)
@@ -3503,9 +3540,10 @@ static void unplug_slaves(mddev_t *mddev)
{
raid5_conf_t *conf = mddev->private;
int i;
+ int devs = max(conf->raid_disks, conf->previous_raid_disks);
rcu_read_lock();
- for (i = 0; i < conf->raid_disks; i++) {
+ for (i = 0; i < devs; i++) {
mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) {
struct request_queue *r_queue = bdev_get_queue(rdev->bdev);
@@ -4277,9 +4315,7 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski
clear_bit(STRIPE_INSYNC, &sh->state);
spin_unlock(&sh->lock);
- /* wait for any blocked device to be handled */
- while (unlikely(!handle_stripe(sh)))
- ;
+ handle_stripe(sh);
release_stripe(sh);
return STRIPE_SECTORS;
@@ -4349,37 +4385,6 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio)
return handled;
}
-#ifdef CONFIG_MULTICORE_RAID456
-static void __process_stripe(void *param, async_cookie_t cookie)
-{
- struct stripe_head *sh = param;
-
- handle_stripe(sh);
- release_stripe(sh);
-}
-
-static void process_stripe(struct stripe_head *sh, struct list_head *domain)
-{
- async_schedule_domain(__process_stripe, sh, domain);
-}
-
-static void synchronize_stripe_processing(struct list_head *domain)
-{
- async_synchronize_full_domain(domain);
-}
-#else
-static void process_stripe(struct stripe_head *sh, struct list_head *domain)
-{
- handle_stripe(sh);
- release_stripe(sh);
- cond_resched();
-}
-
-static void synchronize_stripe_processing(struct list_head *domain)
-{
-}
-#endif
-
/*
* This is our raid5 kernel thread.
@@ -4393,7 +4398,6 @@ static void raid5d(mddev_t *mddev)
struct stripe_head *sh;
raid5_conf_t *conf = mddev->private;
int handled;
- LIST_HEAD(raid_domain);
pr_debug("+++ raid5d active\n");
@@ -4430,7 +4434,9 @@ static void raid5d(mddev_t *mddev)
spin_unlock_irq(&conf->device_lock);
handled++;
- process_stripe(sh, &raid_domain);
+ handle_stripe(sh);
+ release_stripe(sh);
+ cond_resched();
spin_lock_irq(&conf->device_lock);
}
@@ -4438,7 +4444,6 @@ static void raid5d(mddev_t *mddev)
spin_unlock_irq(&conf->device_lock);
- synchronize_stripe_processing(&raid_domain);
async_tx_issue_pending_all();
unplug_slaves(mddev);
@@ -4558,13 +4563,9 @@ raid5_size(mddev_t *mddev, sector_t sectors, int raid_disks)
if (!sectors)
sectors = mddev->dev_sectors;
- if (!raid_disks) {
+ if (!raid_disks)
/* size is defined by the smallest of previous and new size */
- if (conf->raid_disks < conf->previous_raid_disks)
- raid_disks = conf->raid_disks;
- else
- raid_disks = conf->previous_raid_disks;
- }
+ raid_disks = min(conf->raid_disks, conf->previous_raid_disks);
sectors &= ~((sector_t)mddev->chunk_sectors - 1);
sectors &= ~((sector_t)mddev->new_chunk_sectors - 1);
@@ -4665,7 +4666,7 @@ static int raid5_alloc_percpu(raid5_conf_t *conf)
}
per_cpu_ptr(conf->percpu, cpu)->spare_page = spare_page;
}
- scribble = kmalloc(scribble_len(conf->raid_disks), GFP_KERNEL);
+ scribble = kmalloc(conf->scribble_len, GFP_KERNEL);
if (!scribble) {
err = -ENOMEM;
break;
@@ -4686,7 +4687,7 @@ static int raid5_alloc_percpu(raid5_conf_t *conf)
static raid5_conf_t *setup_conf(mddev_t *mddev)
{
raid5_conf_t *conf;
- int raid_disk, memory;
+ int raid_disk, memory, max_disks;
mdk_rdev_t *rdev;
struct disk_info *disk;
@@ -4722,15 +4723,28 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
conf = kzalloc(sizeof(raid5_conf_t), GFP_KERNEL);
if (conf == NULL)
goto abort;
+ spin_lock_init(&conf->device_lock);
+ init_waitqueue_head(&conf->wait_for_stripe);
+ init_waitqueue_head(&conf->wait_for_overlap);
+ INIT_LIST_HEAD(&conf->handle_list);
+ INIT_LIST_HEAD(&conf->hold_list);
+ INIT_LIST_HEAD(&conf->delayed_list);
+ INIT_LIST_HEAD(&conf->bitmap_list);
+ INIT_LIST_HEAD(&conf->inactive_list);
+ atomic_set(&conf->active_stripes, 0);
+ atomic_set(&conf->preread_active_stripes, 0);
+ atomic_set(&conf->active_aligned_reads, 0);
+ conf->bypass_threshold = BYPASS_THRESHOLD;
conf->raid_disks = mddev->raid_disks;
- conf->scribble_len = scribble_len(conf->raid_disks);
if (mddev->reshape_position == MaxSector)
conf->previous_raid_disks = mddev->raid_disks;
else
conf->previous_raid_disks = mddev->raid_disks - mddev->delta_disks;
+ max_disks = max(conf->raid_disks, conf->previous_raid_disks);
+ conf->scribble_len = scribble_len(max_disks);
- conf->disks = kzalloc(conf->raid_disks * sizeof(struct disk_info),
+ conf->disks = kzalloc(max_disks * sizeof(struct disk_info),
GFP_KERNEL);
if (!conf->disks)
goto abort;
@@ -4744,24 +4758,11 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
if (raid5_alloc_percpu(conf) != 0)
goto abort;
- spin_lock_init(&conf->device_lock);
- init_waitqueue_head(&conf->wait_for_stripe);
- init_waitqueue_head(&conf->wait_for_overlap);
- INIT_LIST_HEAD(&conf->handle_list);
- INIT_LIST_HEAD(&conf->hold_list);
- INIT_LIST_HEAD(&conf->delayed_list);
- INIT_LIST_HEAD(&conf->bitmap_list);
- INIT_LIST_HEAD(&conf->inactive_list);
- atomic_set(&conf->active_stripes, 0);
- atomic_set(&conf->preread_active_stripes, 0);
- atomic_set(&conf->active_aligned_reads, 0);
- conf->bypass_threshold = BYPASS_THRESHOLD;
-
pr_debug("raid5: run(%s) called.\n", mdname(mddev));
list_for_each_entry(rdev, &mddev->disks, same_set) {
raid_disk = rdev->raid_disk;
- if (raid_disk >= conf->raid_disks
+ if (raid_disk >= max_disks
|| raid_disk < 0)
continue;
disk = conf->disks + raid_disk;
@@ -4793,7 +4794,7 @@ static raid5_conf_t *setup_conf(mddev_t *mddev)
}
memory = conf->max_nr_stripes * (sizeof(struct stripe_head) +
- conf->raid_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024;
+ max_disks * ((sizeof(struct bio) + PAGE_SIZE))) / 1024;
if (grow_stripes(conf, conf->max_nr_stripes)) {
printk(KERN_ERR
"raid5: couldn't allocate %dkB for buffers\n", memory);
@@ -4918,7 +4919,8 @@ static int run(mddev_t *mddev)
test_bit(In_sync, &rdev->flags))
working_disks++;
- mddev->degraded = conf->raid_disks - working_disks;
+ mddev->degraded = (max(conf->raid_disks, conf->previous_raid_disks)
+ - working_disks);
if (mddev->degraded > conf->max_degraded) {
printk(KERN_ERR "raid5: not enough operational devices for %s"
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h
index 2390e0e83daf..dd708359b451 100644
--- a/drivers/md/raid5.h
+++ b/drivers/md/raid5.h
@@ -214,12 +214,20 @@ struct stripe_head {
int disks; /* disks in stripe */
enum check_states check_state;
enum reconstruct_states reconstruct_state;
- /* stripe_operations
+ /**
+ * struct stripe_operations
* @target - STRIPE_OP_COMPUTE_BLK target
+ * @target2 - 2nd compute target in the raid6 case
+ * @zero_sum_result - P and Q verification flags
+ * @request - async service request flags for raid_run_ops
*/
struct stripe_operations {
int target, target2;
enum sum_check_flags zero_sum_result;
+ #ifdef CONFIG_MULTICORE_RAID456
+ unsigned long request;
+ wait_queue_head_t wait_for_ops;
+ #endif
} ops;
struct r5dev {
struct bio req;
@@ -294,6 +302,8 @@ struct r6_state {
#define STRIPE_FULL_WRITE 13 /* all blocks are set to be overwritten */
#define STRIPE_BIOFILL_RUN 14
#define STRIPE_COMPUTE_RUN 15
+#define STRIPE_OPS_REQ_PENDING 16
+
/*
* Operation request flags
*/
@@ -478,7 +488,7 @@ static inline int algorithm_valid_raid6(int layout)
{
return (layout >= 0 && layout <= 5)
||
- (layout == 8 || layout == 10)
+ (layout >= 8 && layout <= 10)
||
(layout >= 16 && layout <= 20);
}
diff --git a/drivers/md/raid6altivec.uc b/drivers/md/raid6altivec.uc
index 699dfeee4944..2654d5c854be 100644
--- a/drivers/md/raid6altivec.uc
+++ b/drivers/md/raid6altivec.uc
@@ -15,7 +15,7 @@
*
* $#-way unrolled portable integer math RAID-6 instruction set
*
- * This file is postprocessed using unroll.pl
+ * This file is postprocessed using unroll.awk
*
* <benh> hpa: in process,
* you can just "steal" the vec unit with enable_kernel_altivec() (but
diff --git a/drivers/md/raid6int.uc b/drivers/md/raid6int.uc
index f9bf9cba357f..d1e276a14fab 100644
--- a/drivers/md/raid6int.uc
+++ b/drivers/md/raid6int.uc
@@ -15,7 +15,7 @@
*
* $#-way unrolled portable integer math RAID-6 instruction set
*
- * This file is postprocessed using unroll.pl
+ * This file is postprocessed using unroll.awk
*/
#include <linux/raid/pq.h>
diff --git a/drivers/md/raid6test/Makefile b/drivers/md/raid6test/Makefile
index 58ffdf4f5161..2874cbef529d 100644
--- a/drivers/md/raid6test/Makefile
+++ b/drivers/md/raid6test/Makefile
@@ -7,7 +7,7 @@ CC = gcc
OPTFLAGS = -O2 # Adjust as desired
CFLAGS = -I.. -I ../../../include -g $(OPTFLAGS)
LD = ld
-PERL = perl
+AWK = awk
AR = ar
RANLIB = ranlib
@@ -35,35 +35,35 @@ raid6.a: raid6int1.o raid6int2.o raid6int4.o raid6int8.o raid6int16.o \
raid6test: test.c raid6.a
$(CC) $(CFLAGS) -o raid6test $^
-raid6altivec1.c: raid6altivec.uc ../unroll.pl
- $(PERL) ../unroll.pl 1 < raid6altivec.uc > $@
+raid6altivec1.c: raid6altivec.uc ../unroll.awk
+ $(AWK) ../unroll.awk -vN=1 < raid6altivec.uc > $@
-raid6altivec2.c: raid6altivec.uc ../unroll.pl
- $(PERL) ../unroll.pl 2 < raid6altivec.uc > $@
+raid6altivec2.c: raid6altivec.uc ../unroll.awk
+ $(AWK) ../unroll.awk -vN=2 < raid6altivec.uc > $@
-raid6altivec4.c: raid6altivec.uc ../unroll.pl
- $(PERL) ../unroll.pl 4 < raid6altivec.uc > $@
+raid6altivec4.c: raid6altivec.uc ../unroll.awk
+ $(AWK) ../unroll.awk -vN=4 < raid6altivec.uc > $@
-raid6altivec8.c: raid6altivec.uc ../unroll.pl
- $(PERL) ../unroll.pl 8 < raid6altivec.uc > $@
+raid6altivec8.c: raid6altivec.uc ../unroll.awk
+ $(AWK) ../unroll.awk -vN=8 < raid6altivec.uc > $@
-raid6int1.c: raid6int.uc ../unroll.pl
- $(PERL) ../unroll.pl 1 < raid6int.uc > $@
+raid6int1.c: raid6int.uc ../unroll.awk
+ $(AWK) ../unroll.awk -vN=1 < raid6int.uc > $@
-raid6int2.c: raid6int.uc ../unroll.pl
- $(PERL) ../unroll.pl 2 < raid6int.uc > $@
+raid6int2.c: raid6int.uc ../unroll.awk
+ $(AWK) ../unroll.awk -vN=2 < raid6int.uc > $@
-raid6int4.c: raid6int.uc ../unroll.pl
- $(PERL) ../unroll.pl 4 < raid6int.uc > $@
+raid6int4.c: raid6int.uc ../unroll.awk
+ $(AWK) ../unroll.awk -vN=4 < raid6int.uc > $@
-raid6int8.c: raid6int.uc ../unroll.pl
- $(PERL) ../unroll.pl 8 < raid6int.uc > $@
+raid6int8.c: raid6int.uc ../unroll.awk
+ $(AWK) ../unroll.awk -vN=8 < raid6int.uc > $@
-raid6int16.c: raid6int.uc ../unroll.pl
- $(PERL) ../unroll.pl 16 < raid6int.uc > $@
+raid6int16.c: raid6int.uc ../unroll.awk
+ $(AWK) ../unroll.awk -vN=16 < raid6int.uc > $@
-raid6int32.c: raid6int.uc ../unroll.pl
- $(PERL) ../unroll.pl 32 < raid6int.uc > $@
+raid6int32.c: raid6int.uc ../unroll.awk
+ $(AWK) ../unroll.awk -vN=32 < raid6int.uc > $@
raid6tables.c: mktables
./mktables > raid6tables.c
diff --git a/drivers/md/unroll.awk b/drivers/md/unroll.awk
new file mode 100644
index 000000000000..c6aa03631df8
--- /dev/null
+++ b/drivers/md/unroll.awk
@@ -0,0 +1,20 @@
+
+# This filter requires one command line option of form -vN=n
+# where n must be a decimal number.
+#
+# Repeat each input line containing $$ n times, replacing $$ with 0...n-1.
+# Replace each $# with n, and each $* with a single $.
+
+BEGIN {
+ n = N + 0
+}
+{
+ if (/\$\$/) { rep = n } else { rep = 1 }
+ for (i = 0; i < rep; ++i) {
+ tmp = $0
+ gsub(/\$\$/, i, tmp)
+ gsub(/\$\#/, n, tmp)
+ gsub(/\$\*/, "$", tmp)
+ print tmp
+ }
+}
diff --git a/drivers/md/unroll.pl b/drivers/md/unroll.pl
deleted file mode 100644
index 3acc710a20ea..000000000000
--- a/drivers/md/unroll.pl
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/usr/bin/perl
-#
-# Take a piece of C code and for each line which contains the sequence $$
-# repeat n times with $ replaced by 0...n-1; the sequence $# is replaced
-# by the unrolling factor, and $* with a single $
-#
-
-($n) = @ARGV;
-$n += 0;
-
-while ( defined($line = <STDIN>) ) {
- if ( $line =~ /\$\$/ ) {
- $rep = $n;
- } else {
- $rep = 1;
- }
- for ( $i = 0 ; $i < $rep ; $i++ ) {
- $tmp = $line;
- $tmp =~ s/\$\$/$i/g;
- $tmp =~ s/\$\#/$n/g;
- $tmp =~ s/\$\*/\$/g;
- print $tmp;
- }
-}
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c
index efa00ea97725..6cb12502e306 100644
--- a/drivers/mfd/twl4030-core.c
+++ b/drivers/mfd/twl4030-core.c
@@ -795,7 +795,7 @@ twl4030_probe(struct i2c_client *client, const struct i2c_device_id *id)
twl->client = i2c_new_dummy(client->adapter,
twl->address);
if (!twl->client) {
- dev_err(&twl->client->dev,
+ dev_err(&client->dev,
"can't attach client %d\n", i);
status = -ENOMEM;
goto fail;
diff --git a/drivers/mfd/wm831x-irq.c b/drivers/mfd/wm831x-irq.c
index d3015dfb9134..ac056ea6b66e 100644
--- a/drivers/mfd/wm831x-irq.c
+++ b/drivers/mfd/wm831x-irq.c
@@ -507,6 +507,8 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
{
int i, ret;
+ mutex_init(&wm831x->irq_lock);
+
if (!irq) {
dev_warn(wm831x->dev,
"No interrupt specified - functionality limited\n");
@@ -521,7 +523,6 @@ int wm831x_irq_init(struct wm831x *wm831x, int irq)
}
wm831x->irq = irq;
- mutex_init(&wm831x->irq_lock);
INIT_WORK(&wm831x->irq_work, wm831x_irq_worker);
/* Mask the individual interrupt sources */
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c
index e556d42cc45a..63924e0c7ea9 100644
--- a/drivers/mmc/host/at91_mci.c
+++ b/drivers/mmc/host/at91_mci.c
@@ -72,7 +72,6 @@
#include <asm/irq.h>
#include <asm/gpio.h>
-#include <asm/mach/mmc.h>
#include <mach/board.h>
#include <mach/cpu.h>
#include <mach/at91_mci.h>
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index c8f3e0245f1d..4b2322518909 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -2013,7 +2013,7 @@ static struct platform_driver omap_hsmmc_driver = {
static int __init omap_hsmmc_init(void)
{
/* Register the MMC driver */
- return platform_driver_register(&omap_hsmmc_driver);
+ return platform_driver_probe(&omap_hsmmc_driver, omap_hsmmc_probe);
}
static void __exit omap_hsmmc_cleanup(void)
diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
index e1f7d0a78b9d..14cec04c34f9 100644
--- a/drivers/mtd/ubi/build.c
+++ b/drivers/mtd/ubi/build.c
@@ -42,6 +42,7 @@
#include <linux/log2.h>
#include <linux/kthread.h>
#include <linux/reboot.h>
+#include <linux/kernel.h>
#include "ubi.h"
/* Maximum length of the 'mtd=' parameter */
@@ -1257,7 +1258,7 @@ static int __init bytes_str_to_int(const char *str)
unsigned long result;
result = simple_strtoul(str, &endp, 0);
- if (str == endp || result < 0) {
+ if (str == endp || result >= INT_MAX) {
printk(KERN_ERR "UBI error: incorrect bytes count: \"%s\"\n",
str);
return -EINVAL;
diff --git a/drivers/mtd/ubi/scan.c b/drivers/mtd/ubi/scan.c
index e7161adc419d..90af61a2c3e4 100644
--- a/drivers/mtd/ubi/scan.c
+++ b/drivers/mtd/ubi/scan.c
@@ -794,16 +794,15 @@ static int process_eb(struct ubi_device *ubi, struct ubi_scan_info *si,
* number.
*/
image_seq = be32_to_cpu(ech->image_seq);
- if (!si->image_seq_set) {
+ if (!ubi->image_seq && image_seq)
ubi->image_seq = image_seq;
- si->image_seq_set = 1;
- } else if (ubi->image_seq && ubi->image_seq != image_seq) {
+ if (ubi->image_seq && image_seq &&
+ ubi->image_seq != image_seq) {
ubi_err("bad image sequence number %d in PEB %d, "
"expected %d", image_seq, pnum, ubi->image_seq);
ubi_dbg_dump_ec_hdr(ech);
return -EINVAL;
}
-
}
/* OK, we've done with the EC header, let's look at the VID header */
diff --git a/drivers/mtd/ubi/scan.h b/drivers/mtd/ubi/scan.h
index bab31695dace..ff179ad7ca55 100644
--- a/drivers/mtd/ubi/scan.h
+++ b/drivers/mtd/ubi/scan.h
@@ -103,7 +103,6 @@ struct ubi_scan_volume {
* @ec_sum: a temporary variable used when calculating @mean_ec
* @ec_count: a temporary variable used when calculating @mean_ec
* @corr_count: count of corrupted PEBs
- * @image_seq_set: indicates @ubi->image_seq is known
*
* This data structure contains the result of scanning and may be used by other
* UBI sub-systems to build final UBI data structures, further error-recovery
@@ -127,7 +126,6 @@ struct ubi_scan_info {
uint64_t ec_sum;
int ec_count;
int corr_count;
- int image_seq_set;
};
struct ubi_device;
diff --git a/drivers/net/au1000_eth.c b/drivers/net/au1000_eth.c
index 04f63c77071d..ce6f1ac25df8 100644
--- a/drivers/net/au1000_eth.c
+++ b/drivers/net/au1000_eth.c
@@ -34,6 +34,7 @@
*
*
*/
+#include <linux/capability.h>
#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/kernel.h>
diff --git a/drivers/net/benet/be_cmds.c b/drivers/net/benet/be_cmds.c
index 89876ade5e33..28a0eda92680 100644
--- a/drivers/net/benet/be_cmds.c
+++ b/drivers/net/benet/be_cmds.c
@@ -243,15 +243,26 @@ static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage)
int be_cmd_POST(struct be_adapter *adapter)
{
- u16 stage, error;
+ u16 stage;
+ int status, timeout = 0;
- error = be_POST_stage_get(adapter, &stage);
- if (error || stage != POST_STAGE_ARMFW_RDY) {
- dev_err(&adapter->pdev->dev, "POST failed.\n");
- return -1;
- }
+ do {
+ status = be_POST_stage_get(adapter, &stage);
+ if (status) {
+ dev_err(&adapter->pdev->dev, "POST error; stage=0x%x\n",
+ stage);
+ return -1;
+ } else if (stage != POST_STAGE_ARMFW_RDY) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule_timeout(2 * HZ);
+ timeout += 2;
+ } else {
+ return 0;
+ }
+ } while (timeout < 20);
- return 0;
+ dev_err(&adapter->pdev->dev, "POST timeout; stage=0x%x\n", stage);
+ return -1;
}
static inline void *embedded_payload(struct be_mcc_wrb *wrb)
@@ -729,8 +740,8 @@ int be_cmd_q_destroy(struct be_adapter *adapter, struct be_queue_info *q,
/* Create an rx filtering policy configuration on an i/f
* Uses mbox
*/
-int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac,
- bool pmac_invalid, u32 *if_handle, u32 *pmac_id)
+int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags, u32 en_flags,
+ u8 *mac, bool pmac_invalid, u32 *if_handle, u32 *pmac_id)
{
struct be_mcc_wrb *wrb;
struct be_cmd_req_if_create *req;
@@ -746,8 +757,8 @@ int be_cmd_if_create(struct be_adapter *adapter, u32 flags, u8 *mac,
be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
OPCODE_COMMON_NTWK_INTERFACE_CREATE, sizeof(*req));
- req->capability_flags = cpu_to_le32(flags);
- req->enable_flags = cpu_to_le32(flags);
+ req->capability_flags = cpu_to_le32(cap_flags);
+ req->enable_flags = cpu_to_le32(en_flags);
req->pmac_invalid = pmac_invalid;
if (!pmac_invalid)
memcpy(req->mac_addr, mac, ETH_ALEN);
diff --git a/drivers/net/benet/be_cmds.h b/drivers/net/benet/be_cmds.h
index a86f917f85f4..49953787e41c 100644
--- a/drivers/net/benet/be_cmds.h
+++ b/drivers/net/benet/be_cmds.h
@@ -720,8 +720,9 @@ extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
u32 if_id, u32 *pmac_id);
extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id);
-extern int be_cmd_if_create(struct be_adapter *adapter, u32 if_flags, u8 *mac,
- bool pmac_invalid, u32 *if_handle, u32 *pmac_id);
+extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags,
+ u32 en_flags, u8 *mac, bool pmac_invalid,
+ u32 *if_handle, u32 *pmac_id);
extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle);
extern int be_cmd_eq_create(struct be_adapter *adapter,
struct be_queue_info *eq, int eq_delay);
diff --git a/drivers/net/benet/be_main.c b/drivers/net/benet/be_main.c
index 6d5e81f7046f..1f941f027718 100644
--- a/drivers/net/benet/be_main.c
+++ b/drivers/net/benet/be_main.c
@@ -1620,19 +1620,22 @@ static int be_open(struct net_device *netdev)
static int be_setup(struct be_adapter *adapter)
{
struct net_device *netdev = adapter->netdev;
- u32 if_flags;
+ u32 cap_flags, en_flags;
int status;
- if_flags = BE_IF_FLAGS_BROADCAST | BE_IF_FLAGS_PROMISCUOUS |
- BE_IF_FLAGS_MCAST_PROMISCUOUS | BE_IF_FLAGS_UNTAGGED |
- BE_IF_FLAGS_PASS_L3L4_ERRORS;
- status = be_cmd_if_create(adapter, if_flags, netdev->dev_addr,
- false/* pmac_invalid */, &adapter->if_handle,
- &adapter->pmac_id);
+ cap_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+ BE_IF_FLAGS_MCAST_PROMISCUOUS |
+ BE_IF_FLAGS_PROMISCUOUS |
+ BE_IF_FLAGS_PASS_L3L4_ERRORS;
+ en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST |
+ BE_IF_FLAGS_PASS_L3L4_ERRORS;
+
+ status = be_cmd_if_create(adapter, cap_flags, en_flags,
+ netdev->dev_addr, false/* pmac_invalid */,
+ &adapter->if_handle, &adapter->pmac_id);
if (status != 0)
goto do_none;
-
status = be_tx_queues_create(adapter);
if (status != 0)
goto if_destroy;
@@ -2055,6 +2058,10 @@ static int be_hw_up(struct be_adapter *adapter)
if (status)
return status;
+ status = be_cmd_reset_function(adapter);
+ if (status)
+ return status;
+
status = be_cmd_get_fw_ver(adapter, adapter->fw_ver);
if (status)
return status;
@@ -2108,10 +2115,6 @@ static int __devinit be_probe(struct pci_dev *pdev,
if (status)
goto free_netdev;
- status = be_cmd_reset_function(adapter);
- if (status)
- goto ctrl_clean;
-
status = be_stats_init(adapter);
if (status)
goto ctrl_clean;
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h
index 6c7f795d12de..a4d83409f205 100644
--- a/drivers/net/bnx2.h
+++ b/drivers/net/bnx2.h
@@ -361,9 +361,12 @@ struct l2_fhdr {
#define BNX2_L2CTX_CTX_TYPE_CTX_BD_CHN_TYPE_VALUE (1<<28)
#define BNX2_L2CTX_HOST_BDIDX 0x00000004
-#define BNX2_L2CTX_STATUSB_NUM_SHIFT 16
-#define BNX2_L2CTX_STATUSB_NUM(sb_id) \
- (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_STATUSB_NUM_SHIFT) : 0)
+#define BNX2_L2CTX_L5_STATUSB_NUM_SHIFT 16
+#define BNX2_L2CTX_L2_STATUSB_NUM_SHIFT 24
+#define BNX2_L2CTX_L5_STATUSB_NUM(sb_id) \
+ (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L5_STATUSB_NUM_SHIFT) : 0)
+#define BNX2_L2CTX_L2_STATUSB_NUM(sb_id) \
+ (((sb_id) > 0) ? (((sb_id) + 7) << BNX2_L2CTX_L2_STATUSB_NUM_SHIFT) : 0)
#define BNX2_L2CTX_HOST_BSEQ 0x00000008
#define BNX2_L2CTX_NX_BSEQ 0x0000000c
#define BNX2_L2CTX_NX_BDHADDR_HI 0x00000010
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 69c5b15e22da..40fb5eefc72e 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -691,7 +691,7 @@ static int bond_check_dev_link(struct bonding *bond,
struct net_device *slave_dev, int reporting)
{
const struct net_device_ops *slave_ops = slave_dev->netdev_ops;
- static int (*ioctl)(struct net_device *, struct ifreq *, int);
+ int (*ioctl)(struct net_device *, struct ifreq *, int);
struct ifreq ifr;
struct mii_ioctl_data *mii;
@@ -3665,10 +3665,10 @@ static int bond_xmit_hash_policy_l23(struct sk_buff *skb,
if (skb->protocol == htons(ETH_P_IP)) {
return ((ntohl(iph->saddr ^ iph->daddr) & 0xffff) ^
- (data->h_dest[5] ^ bond_dev->dev_addr[5])) % count;
+ (data->h_dest[5] ^ data->h_source[5])) % count;
}
- return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+ return (data->h_dest[5] ^ data->h_source[5]) % count;
}
/*
@@ -3695,7 +3695,7 @@ static int bond_xmit_hash_policy_l34(struct sk_buff *skb,
}
- return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+ return (data->h_dest[5] ^ data->h_source[5]) % count;
}
/*
@@ -3706,7 +3706,7 @@ static int bond_xmit_hash_policy_l2(struct sk_buff *skb,
{
struct ethhdr *data = (struct ethhdr *)skb->data;
- return (data->h_dest[5] ^ bond_dev->dev_addr[5]) % count;
+ return (data->h_dest[5] ^ data->h_source[5]) % count;
}
/*-------------------------- Device entry points ----------------------------*/
diff --git a/drivers/net/cnic.c b/drivers/net/cnic.c
index 46c87ec7960c..3bf1b04f2cab 100644
--- a/drivers/net/cnic.c
+++ b/drivers/net/cnic.c
@@ -2264,9 +2264,9 @@ static void cnic_init_bnx2_rx_ring(struct cnic_dev *dev)
cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_CTX_TYPE, val);
if (sb_id == 0)
- val = 2 << BNX2_L2CTX_STATUSB_NUM_SHIFT;
+ val = 2 << BNX2_L2CTX_L2_STATUSB_NUM_SHIFT;
else
- val = BNX2_L2CTX_STATUSB_NUM(sb_id);
+ val = BNX2_L2CTX_L2_STATUSB_NUM(sb_id);
cnic_ctx_wr(dev, cid_addr, BNX2_L2CTX_HOST_BDIDX, val);
rxbd = (struct rx_bd *) (cp->l2_ring + BCM_PAGE_SIZE);
@@ -2423,7 +2423,7 @@ static int cnic_start_bnx2_hw(struct cnic_dev *dev)
cp->int_num = 0;
if (ethdev->drv_state & CNIC_DRV_STATE_USING_MSIX) {
u32 sb_id = cp->status_blk_num;
- u32 sb = BNX2_L2CTX_STATUSB_NUM(sb_id);
+ u32 sb = BNX2_L2CTX_L5_STATUSB_NUM(sb_id);
cp->int_num = sb_id << BNX2_PCICFG_INT_ACK_CMD_INT_NUM_SHIFT;
cnic_ctx_wr(dev, cp->kwq_cid_addr, L5_KRNLQ_HOST_QIDX, sb);
diff --git a/drivers/net/dm9000.h b/drivers/net/dm9000.h
index 80817c2edfb3..fb1c924d79b4 100644
--- a/drivers/net/dm9000.h
+++ b/drivers/net/dm9000.h
@@ -50,7 +50,7 @@
#define DM9000_RCSR 0x32
#define CHIPR_DM9000A 0x19
-#define CHIPR_DM9000B 0x1B
+#define CHIPR_DM9000B 0x1A
#define DM9000_MRCMDX 0xF0
#define DM9000_MRCMD 0xF2
diff --git a/drivers/net/e100.c b/drivers/net/e100.c
index 5d2f48f02251..3c29a20b751e 100644
--- a/drivers/net/e100.c
+++ b/drivers/net/e100.c
@@ -1427,19 +1427,31 @@ static int e100_phy_init(struct nic *nic)
} else
DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
- /* Isolate all the PHY ids */
- for (addr = 0; addr < 32; addr++)
- mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
- /* Select the discovered PHY */
- bmcr &= ~BMCR_ISOLATE;
- mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);
-
/* Get phy ID */
id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2);
nic->phy = (u32)id_hi << 16 | (u32)id_lo;
DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy);
+ /* Select the phy and isolate the rest */
+ for (addr = 0; addr < 32; addr++) {
+ if (addr != nic->mii.phy_id) {
+ mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
+ } else if (nic->phy != phy_82552_v) {
+ bmcr = mdio_read(netdev, addr, MII_BMCR);
+ mdio_write(netdev, addr, MII_BMCR,
+ bmcr & ~BMCR_ISOLATE);
+ }
+ }
+ /*
+ * Workaround for 82552:
+ * Clear the ISOLATE bit on selected phy_id last (mirrored on all
+ * other phy_id's) using bmcr value from addr discovery loop above.
+ */
+ if (nic->phy == phy_82552_v)
+ mdio_write(netdev, nic->mii.phy_id, MII_BMCR,
+ bmcr & ~BMCR_ISOLATE);
+
/* Handle National tx phys */
#define NCS_PHY_MODEL_MASK 0xFFF0FFFF
if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
diff --git a/drivers/net/e1000e/defines.h b/drivers/net/e1000e/defines.h
index c0f185beb8bc..1190167a8b3d 100644
--- a/drivers/net/e1000e/defines.h
+++ b/drivers/net/e1000e/defines.h
@@ -76,6 +76,7 @@
/* Extended Device Control */
#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */
#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */
+#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */
#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
@@ -347,6 +348,7 @@
/* Extended Configuration Control and Size */
#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020
#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
+#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008
#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h
index 981936c1fb46..189dfa2d6c76 100644
--- a/drivers/net/e1000e/e1000.h
+++ b/drivers/net/e1000e/e1000.h
@@ -141,6 +141,20 @@ struct e1000_info;
#define HV_TNCRS_UPPER PHY_REG(778, 29) /* Transmit with no CRS */
#define HV_TNCRS_LOWER PHY_REG(778, 30)
+/* BM PHY Copper Specific Status */
+#define BM_CS_STATUS 17
+#define BM_CS_STATUS_LINK_UP 0x0400
+#define BM_CS_STATUS_RESOLVED 0x0800
+#define BM_CS_STATUS_SPEED_MASK 0xC000
+#define BM_CS_STATUS_SPEED_1000 0x8000
+
+/* 82577 Mobile Phy Status Register */
+#define HV_M_STATUS 26
+#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000
+#define HV_M_STATUS_SPEED_MASK 0x0300
+#define HV_M_STATUS_SPEED_1000 0x0200
+#define HV_M_STATUS_LINK_UP 0x0040
+
enum e1000_boards {
board_82571,
board_82572,
@@ -519,9 +533,13 @@ extern s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw);
extern s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw);
extern s32 e1000e_get_phy_info_igp(struct e1000_hw *hw);
extern s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset,
+ u16 *data);
extern s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw);
extern s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active);
extern s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
+extern s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset,
+ u16 data);
extern s32 e1000e_phy_sw_reset(struct e1000_hw *hw);
extern s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw);
extern s32 e1000e_get_cfg_done(struct e1000_hw *hw);
@@ -538,7 +556,11 @@ extern s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
extern void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl);
extern s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data);
+extern s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset,
+ u16 data);
extern s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset,
+ u16 *data);
extern s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
u32 usec_interval, bool *success);
extern s32 e1000e_phy_reset_dsp(struct e1000_hw *hw);
@@ -546,7 +568,11 @@ extern s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
extern s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
extern s32 e1000e_check_downshift(struct e1000_hw *hw);
extern s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
+extern s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
+ u16 *data);
extern s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
+extern s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset,
+ u16 data);
extern s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow);
extern s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw);
extern s32 e1000_copper_link_setup_82577(struct e1000_hw *hw);
diff --git a/drivers/net/e1000e/hw.h b/drivers/net/e1000e/hw.h
index fd44d9f90769..aaea41ef794d 100644
--- a/drivers/net/e1000e/hw.h
+++ b/drivers/net/e1000e/hw.h
@@ -764,11 +764,13 @@ struct e1000_phy_operations {
s32 (*get_cable_length)(struct e1000_hw *);
s32 (*get_phy_info)(struct e1000_hw *);
s32 (*read_phy_reg)(struct e1000_hw *, u32, u16 *);
+ s32 (*read_phy_reg_locked)(struct e1000_hw *, u32, u16 *);
void (*release_phy)(struct e1000_hw *);
s32 (*reset_phy)(struct e1000_hw *);
s32 (*set_d0_lplu_state)(struct e1000_hw *, bool);
s32 (*set_d3_lplu_state)(struct e1000_hw *, bool);
s32 (*write_phy_reg)(struct e1000_hw *, u32, u16);
+ s32 (*write_phy_reg_locked)(struct e1000_hw *, u32, u16);
s32 (*cfg_on_link_up)(struct e1000_hw *);
};
@@ -901,6 +903,7 @@ struct e1000_shadow_ram {
struct e1000_dev_spec_ich8lan {
bool kmrn_lock_loss_workaround_enabled;
struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
+ bool nvm_k1_enabled;
};
struct e1000_hw {
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c
index 99df2abf82a9..51ddb04ab195 100644
--- a/drivers/net/e1000e/ich8lan.c
+++ b/drivers/net/e1000e/ich8lan.c
@@ -122,6 +122,27 @@
#define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */
+#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in milliseconds */
+
+/* SMBus Address Phy Register */
+#define HV_SMB_ADDR PHY_REG(768, 26)
+#define HV_SMB_ADDR_PEC_EN 0x0200
+#define HV_SMB_ADDR_VALID 0x0080
+
+/* Strapping Option Register - RO */
+#define E1000_STRAP 0x0000C
+#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
+#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17
+
+/* OEM Bits Phy Register */
+#define HV_OEM_BITS PHY_REG(768, 25)
+#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */
+#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */
+#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */
+
+#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
+#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */
+
/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
/* Offset 04h HSFSTS */
union ich8_hws_flash_status {
@@ -200,6 +221,10 @@ static s32 e1000_setup_led_pchlan(struct e1000_hw *hw);
static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw);
static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
+static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
+static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
+static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
+static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
{
@@ -242,7 +267,11 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
phy->ops.check_polarity = e1000_check_polarity_ife_ich8lan;
phy->ops.read_phy_reg = e1000_read_phy_reg_hv;
+ phy->ops.read_phy_reg_locked = e1000_read_phy_reg_hv_locked;
+ phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan;
+ phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan;
phy->ops.write_phy_reg = e1000_write_phy_reg_hv;
+ phy->ops.write_phy_reg_locked = e1000_write_phy_reg_hv_locked;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
phy->id = e1000_phy_unknown;
@@ -303,6 +332,8 @@ static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
case IGP03E1000_E_PHY_ID:
phy->type = e1000_phy_igp_3;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
+ phy->ops.read_phy_reg_locked = e1000e_read_phy_reg_igp_locked;
+ phy->ops.write_phy_reg_locked = e1000e_write_phy_reg_igp_locked;
break;
case IFE_E_PHY_ID:
case IFE_PLUS_E_PHY_ID:
@@ -469,14 +500,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
goto out;
}
- if (hw->mac.type == e1000_pchlan) {
- ret_val = e1000e_write_kmrn_reg(hw,
- E1000_KMRNCTRLSTA_K1_CONFIG,
- E1000_KMRNCTRLSTA_K1_ENABLE);
- if (ret_val)
- goto out;
- }
-
/*
* First we want to see if the MII Status Register reports
* link. If so, then we want to get the current speed/duplex
@@ -486,6 +509,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
if (ret_val)
goto out;
+ if (hw->mac.type == e1000_pchlan) {
+ ret_val = e1000_k1_gig_workaround_hv(hw, link);
+ if (ret_val)
+ goto out;
+ }
+
if (!link)
goto out; /* No link detected */
@@ -568,12 +597,39 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
static DEFINE_MUTEX(nvm_mutex);
/**
+ * e1000_acquire_nvm_ich8lan - Acquire NVM mutex
+ * @hw: pointer to the HW structure
+ *
+ * Acquires the mutex for performing NVM operations.
+ **/
+static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw)
+{
+ mutex_lock(&nvm_mutex);
+
+ return 0;
+}
+
+/**
+ * e1000_release_nvm_ich8lan - Release NVM mutex
+ * @hw: pointer to the HW structure
+ *
+ * Releases the mutex used while performing NVM operations.
+ **/
+static void e1000_release_nvm_ich8lan(struct e1000_hw *hw)
+{
+ mutex_unlock(&nvm_mutex);
+
+ return;
+}
+
+static DEFINE_MUTEX(swflag_mutex);
+
+/**
* e1000_acquire_swflag_ich8lan - Acquire software control flag
* @hw: pointer to the HW structure
*
- * Acquires the software control flag for performing NVM and PHY
- * operations. This is a function pointer entry point only called by
- * read/write routines for the PHY and NVM parts.
+ * Acquires the software control flag for performing PHY and select
+ * MAC CSR accesses.
**/
static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
{
@@ -582,7 +638,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
might_sleep();
- mutex_lock(&nvm_mutex);
+ mutex_lock(&swflag_mutex);
while (timeout) {
extcnf_ctrl = er32(EXTCNF_CTRL);
@@ -599,7 +655,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
goto out;
}
- timeout = PHY_CFG_TIMEOUT * 2;
+ timeout = SW_FLAG_TIMEOUT;
extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
@@ -623,7 +679,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
out:
if (ret_val)
- mutex_unlock(&nvm_mutex);
+ mutex_unlock(&swflag_mutex);
return ret_val;
}
@@ -632,9 +688,8 @@ out:
* e1000_release_swflag_ich8lan - Release software control flag
* @hw: pointer to the HW structure
*
- * Releases the software control flag for performing NVM and PHY operations.
- * This is a function pointer entry point only called by read/write
- * routines for the PHY and NVM parts.
+ * Releases the software control flag for performing PHY and select
+ * MAC CSR accesses.
**/
static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
{
@@ -644,7 +699,9 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
- mutex_unlock(&nvm_mutex);
+ mutex_unlock(&swflag_mutex);
+
+ return;
}
/**
@@ -752,6 +809,326 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw)
}
/**
+ * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration
+ * @hw: pointer to the HW structure
+ *
+ * SW should configure the LCD from the NVM extended configuration region
+ * as a workaround for certain parts.
+ **/
+static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
+{
+ struct e1000_phy_info *phy = &hw->phy;
+ u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
+ s32 ret_val;
+ u16 word_addr, reg_data, reg_addr, phy_page = 0;
+
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+
+ /*
+ * Initialize the PHY from the NVM on ICH platforms. This
+ * is needed due to an issue where the NVM configuration is
+ * not properly autoloaded after power transitions.
+ * Therefore, after each PHY reset, we will load the
+ * configuration data out of the NVM manually.
+ */
+ if ((hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) ||
+ (hw->mac.type == e1000_pchlan)) {
+ struct e1000_adapter *adapter = hw->adapter;
+
+ /* Check if SW needs to configure the PHY */
+ if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
+ (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) ||
+ (hw->mac.type == e1000_pchlan))
+ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
+ else
+ sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
+
+ data = er32(FEXTNVM);
+ if (!(data & sw_cfg_mask))
+ goto out;
+
+ /* Wait for basic configuration completes before proceeding */
+ e1000_lan_init_done_ich8lan(hw);
+
+ /*
+ * Make sure HW does not configure LCD from PHY
+ * extended configuration before SW configuration
+ */
+ data = er32(EXTCNF_CTRL);
+ if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
+ goto out;
+
+ cnf_size = er32(EXTCNF_SIZE);
+ cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
+ cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
+ if (!cnf_size)
+ goto out;
+
+ cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
+ cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
+
+ if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
+ (hw->mac.type == e1000_pchlan)) {
+ /*
+ * HW configures the SMBus address and LEDs when the
+ * OEM and LCD Write Enable bits are set in the NVM.
+ * When both NVM bits are cleared, SW will configure
+ * them instead.
+ */
+ data = er32(STRAP);
+ data &= E1000_STRAP_SMBUS_ADDRESS_MASK;
+ reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT;
+ reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
+ ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR,
+ reg_data);
+ if (ret_val)
+ goto out;
+
+ data = er32(LEDCTL);
+ ret_val = e1000_write_phy_reg_hv_locked(hw,
+ HV_LED_CONFIG,
+ (u16)data);
+ if (ret_val)
+ goto out;
+ }
+ /* Configure LCD from extended configuration region. */
+
+ /* cnf_base_addr is in DWORD */
+ word_addr = (u16)(cnf_base_addr << 1);
+
+ for (i = 0; i < cnf_size; i++) {
+ ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1,
+ &reg_data);
+ if (ret_val)
+ goto out;
+
+ ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1),
+ 1, &reg_addr);
+ if (ret_val)
+ goto out;
+
+ /* Save off the PHY page for future writes. */
+ if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
+ phy_page = reg_data;
+ continue;
+ }
+
+ reg_addr &= PHY_REG_MASK;
+ reg_addr |= phy_page;
+
+ ret_val = phy->ops.write_phy_reg_locked(hw,
+ (u32)reg_addr,
+ reg_data);
+ if (ret_val)
+ goto out;
+ }
+ }
+
+out:
+ hw->phy.ops.release_phy(hw);
+ return ret_val;
+}
+
+/**
+ * e1000_k1_gig_workaround_hv - K1 Si workaround
+ * @hw: pointer to the HW structure
+ * @link: link up bool flag
+ *
+ * If K1 is enabled for 1Gbps, the MAC might stall when transitioning
+ * from a lower speed. This workaround disables K1 whenever link is at 1Gig
+ * If link is down, the function will restore the default K1 setting located
+ * in the NVM.
+ **/
+static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
+{
+ s32 ret_val = 0;
+ u16 status_reg = 0;
+ bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled;
+
+ if (hw->mac.type != e1000_pchlan)
+ goto out;
+
+ /* Wrap the whole flow with the sw flag */
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ goto out;
+
+ /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
+ if (link) {
+ if (hw->phy.type == e1000_phy_82578) {
+ ret_val = hw->phy.ops.read_phy_reg_locked(hw,
+ BM_CS_STATUS,
+ &status_reg);
+ if (ret_val)
+ goto release;
+
+ status_reg &= BM_CS_STATUS_LINK_UP |
+ BM_CS_STATUS_RESOLVED |
+ BM_CS_STATUS_SPEED_MASK;
+
+ if (status_reg == (BM_CS_STATUS_LINK_UP |
+ BM_CS_STATUS_RESOLVED |
+ BM_CS_STATUS_SPEED_1000))
+ k1_enable = false;
+ }
+
+ if (hw->phy.type == e1000_phy_82577) {
+ ret_val = hw->phy.ops.read_phy_reg_locked(hw,
+ HV_M_STATUS,
+ &status_reg);
+ if (ret_val)
+ goto release;
+
+ status_reg &= HV_M_STATUS_LINK_UP |
+ HV_M_STATUS_AUTONEG_COMPLETE |
+ HV_M_STATUS_SPEED_MASK;
+
+ if (status_reg == (HV_M_STATUS_LINK_UP |
+ HV_M_STATUS_AUTONEG_COMPLETE |
+ HV_M_STATUS_SPEED_1000))
+ k1_enable = false;
+ }
+
+ /* Link stall fix for link up */
+ ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19),
+ 0x0100);
+ if (ret_val)
+ goto release;
+
+ } else {
+ /* Link stall fix for link down */
+ ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19),
+ 0x4100);
+ if (ret_val)
+ goto release;
+ }
+
+ ret_val = e1000_configure_k1_ich8lan(hw, k1_enable);
+
+release:
+ hw->phy.ops.release_phy(hw);
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_configure_k1_ich8lan - Configure K1 power state
+ * @hw: pointer to the HW structure
+ * @enable: K1 state to configure
+ *
+ * Configure the K1 power state based on the provided parameter.
+ * Assumes semaphore already acquired.
+ *
+ * Success returns 0, Failure returns -E1000_ERR_PHY (-2)
+ **/
+static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
+{
+ s32 ret_val = 0;
+ u32 ctrl_reg = 0;
+ u32 ctrl_ext = 0;
+ u32 reg = 0;
+ u16 kmrn_reg = 0;
+
+ ret_val = e1000e_read_kmrn_reg_locked(hw,
+ E1000_KMRNCTRLSTA_K1_CONFIG,
+ &kmrn_reg);
+ if (ret_val)
+ goto out;
+
+ if (k1_enable)
+ kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE;
+ else
+ kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE;
+
+ ret_val = e1000e_write_kmrn_reg_locked(hw,
+ E1000_KMRNCTRLSTA_K1_CONFIG,
+ kmrn_reg);
+ if (ret_val)
+ goto out;
+
+ udelay(20);
+ ctrl_ext = er32(CTRL_EXT);
+ ctrl_reg = er32(CTRL);
+
+ reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
+ reg |= E1000_CTRL_FRCSPD;
+ ew32(CTRL, reg);
+
+ ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS);
+ udelay(20);
+ ew32(CTRL, ctrl_reg);
+ ew32(CTRL_EXT, ctrl_ext);
+ udelay(20);
+
+out:
+ return ret_val;
+}
+
+/**
+ * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration
+ * @hw: pointer to the HW structure
+ * @d0_state: boolean if entering d0 or d3 device state
+ *
+ * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are
+ * collectively called OEM bits. The OEM Write Enable bit and SW Config bit
+ * in NVM determines whether HW should configure LPLU and Gbe Disable.
+ **/
+static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
+{
+ s32 ret_val = 0;
+ u32 mac_reg;
+ u16 oem_reg;
+
+ if (hw->mac.type != e1000_pchlan)
+ return ret_val;
+
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+
+ mac_reg = er32(EXTCNF_CTRL);
+ if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
+ goto out;
+
+ mac_reg = er32(FEXTNVM);
+ if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
+ goto out;
+
+ mac_reg = er32(PHY_CTRL);
+
+ ret_val = hw->phy.ops.read_phy_reg_locked(hw, HV_OEM_BITS, &oem_reg);
+ if (ret_val)
+ goto out;
+
+ oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU);
+
+ if (d0_state) {
+ if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE)
+ oem_reg |= HV_OEM_BITS_GBE_DIS;
+
+ if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
+ oem_reg |= HV_OEM_BITS_LPLU;
+ } else {
+ if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE)
+ oem_reg |= HV_OEM_BITS_GBE_DIS;
+
+ if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU)
+ oem_reg |= HV_OEM_BITS_LPLU;
+ }
+ /* Restart auto-neg to activate the bits */
+ oem_reg |= HV_OEM_BITS_RESTART_AN;
+ ret_val = hw->phy.ops.write_phy_reg_locked(hw, HV_OEM_BITS, oem_reg);
+
+out:
+ hw->phy.ops.release_phy(hw);
+
+ return ret_val;
+}
+
+
+/**
* e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
* done after every PHY reset.
**/
@@ -791,10 +1168,20 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
ret_val = hw->phy.ops.acquire_phy(hw);
if (ret_val)
return ret_val;
+
hw->phy.addr = 1;
- e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
+ ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
+ if (ret_val)
+ goto out;
hw->phy.ops.release_phy(hw);
+ /*
+ * Configure the K1 Si workaround during phy reset assuming there is
+ * link so that it disables K1 if link is in 1Gbps.
+ */
+ ret_val = e1000_k1_gig_workaround_hv(hw, true);
+
+out:
return ret_val;
}
@@ -840,11 +1227,8 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
**/
static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
{
- struct e1000_phy_info *phy = &hw->phy;
- u32 i;
- u32 data, cnf_size, cnf_base_addr, sw_cfg_mask;
- s32 ret_val;
- u16 word_addr, reg_data, reg_addr, phy_page = 0;
+ s32 ret_val = 0;
+ u16 reg;
ret_val = e1000e_phy_hw_reset_generic(hw);
if (ret_val)
@@ -859,81 +1243,20 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
return ret_val;
}
- /*
- * Initialize the PHY from the NVM on ICH platforms. This
- * is needed due to an issue where the NVM configuration is
- * not properly autoloaded after power transitions.
- * Therefore, after each PHY reset, we will load the
- * configuration data out of the NVM manually.
- */
- if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) {
- struct e1000_adapter *adapter = hw->adapter;
-
- /* Check if SW needs configure the PHY */
- if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
- (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M))
- sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
- else
- sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
-
- data = er32(FEXTNVM);
- if (!(data & sw_cfg_mask))
- return 0;
-
- /* Wait for basic configuration completes before proceeding */
- e1000_lan_init_done_ich8lan(hw);
-
- /*
- * Make sure HW does not configure LCD from PHY
- * extended configuration before SW configuration
- */
- data = er32(EXTCNF_CTRL);
- if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
- return 0;
-
- cnf_size = er32(EXTCNF_SIZE);
- cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
- cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
- if (!cnf_size)
- return 0;
-
- cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
- cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
-
- /* Configure LCD from extended configuration region. */
-
- /* cnf_base_addr is in DWORD */
- word_addr = (u16)(cnf_base_addr << 1);
-
- for (i = 0; i < cnf_size; i++) {
- ret_val = e1000_read_nvm(hw,
- (word_addr + i * 2),
- 1,
- &reg_data);
- if (ret_val)
- return ret_val;
-
- ret_val = e1000_read_nvm(hw,
- (word_addr + i * 2 + 1),
- 1,
- &reg_addr);
- if (ret_val)
- return ret_val;
-
- /* Save off the PHY page for future writes. */
- if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
- phy_page = reg_data;
- continue;
- }
+ /* Dummy read to clear the phy wakeup bit after lcd reset */
+ if (hw->mac.type == e1000_pchlan)
+ e1e_rphy(hw, BM_WUC, &reg);
- reg_addr |= phy_page;
+ /* Configure the LCD with the extended configuration region in NVM */
+ ret_val = e1000_sw_lcd_config_ich8lan(hw);
+ if (ret_val)
+ goto out;
- ret_val = e1e_wphy(hw, (u32)reg_addr, reg_data);
- if (ret_val)
- return ret_val;
- }
- }
+ /* Configure the LCD with the OEM bits in NVM */
+ if (hw->mac.type == e1000_pchlan)
+ ret_val = e1000_oem_bits_config_ich8lan(hw, true);
+out:
return 0;
}
@@ -1054,6 +1377,38 @@ static s32 e1000_check_polarity_ife_ich8lan(struct e1000_hw *hw)
}
/**
+ * e1000_set_lplu_state_pchlan - Set Low Power Link Up state
+ * @hw: pointer to the HW structure
+ * @active: true to enable LPLU, false to disable
+ *
+ * Sets the LPLU state according to the active flag. For PCH, if OEM write
+ * bit are disabled in the NVM, writing the LPLU bits in the MAC will not set
+ * the phy speed. This function will manually set the LPLU bit and restart
+ * auto-neg as hw would do. D3 and D0 LPLU will call the same function
+ * since it configures the same bit.
+ **/
+static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active)
+{
+ s32 ret_val = 0;
+ u16 oem_reg;
+
+ ret_val = e1e_rphy(hw, HV_OEM_BITS, &oem_reg);
+ if (ret_val)
+ goto out;
+
+ if (active)
+ oem_reg |= HV_OEM_BITS_LPLU;
+ else
+ oem_reg &= ~HV_OEM_BITS_LPLU;
+
+ oem_reg |= HV_OEM_BITS_RESTART_AN;
+ ret_val = e1e_wphy(hw, HV_OEM_BITS, oem_reg);
+
+out:
+ return ret_val;
+}
+
+/**
* e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state
* @hw: pointer to the HW structure
* @active: TRUE to enable LPLU, FALSE to disable
@@ -1314,12 +1669,11 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
(words == 0)) {
hw_dbg(hw, "nvm parameter(s) out of bounds\n");
- return -E1000_ERR_NVM;
+ ret_val = -E1000_ERR_NVM;
+ goto out;
}
- ret_val = e1000_acquire_swflag_ich8lan(hw);
- if (ret_val)
- goto out;
+ nvm->ops.acquire_nvm(hw);
ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
if (ret_val) {
@@ -1345,7 +1699,7 @@ static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
}
}
- e1000_release_swflag_ich8lan(hw);
+ nvm->ops.release_nvm(hw);
out:
if (ret_val)
@@ -1603,11 +1957,15 @@ static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
return -E1000_ERR_NVM;
}
+ nvm->ops.acquire_nvm(hw);
+
for (i = 0; i < words; i++) {
dev_spec->shadow_ram[offset+i].modified = 1;
dev_spec->shadow_ram[offset+i].value = data[i];
}
+ nvm->ops.release_nvm(hw);
+
return 0;
}
@@ -1637,9 +1995,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
if (nvm->type != e1000_nvm_flash_sw)
goto out;
- ret_val = e1000_acquire_swflag_ich8lan(hw);
- if (ret_val)
- goto out;
+ nvm->ops.acquire_nvm(hw);
/*
* We're writing to the opposite bank so if we're on bank 1,
@@ -1657,7 +2013,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
old_bank_offset = 0;
ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
if (ret_val) {
- e1000_release_swflag_ich8lan(hw);
+ nvm->ops.release_nvm(hw);
goto out;
}
} else {
@@ -1665,7 +2021,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
new_bank_offset = 0;
ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
if (ret_val) {
- e1000_release_swflag_ich8lan(hw);
+ nvm->ops.release_nvm(hw);
goto out;
}
}
@@ -1723,7 +2079,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
if (ret_val) {
/* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */
hw_dbg(hw, "Flash commit failed.\n");
- e1000_release_swflag_ich8lan(hw);
+ nvm->ops.release_nvm(hw);
goto out;
}
@@ -1736,7 +2092,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data);
if (ret_val) {
- e1000_release_swflag_ich8lan(hw);
+ nvm->ops.release_nvm(hw);
goto out;
}
data &= 0xBFFF;
@@ -1744,7 +2100,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
act_offset * 2 + 1,
(u8)(data >> 8));
if (ret_val) {
- e1000_release_swflag_ich8lan(hw);
+ nvm->ops.release_nvm(hw);
goto out;
}
@@ -1757,7 +2113,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
if (ret_val) {
- e1000_release_swflag_ich8lan(hw);
+ nvm->ops.release_nvm(hw);
goto out;
}
@@ -1767,7 +2123,7 @@ static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
dev_spec->shadow_ram[i].value = 0xFFFF;
}
- e1000_release_swflag_ich8lan(hw);
+ nvm->ops.release_nvm(hw);
/*
* Reload the EEPROM, or else modifications will not appear
@@ -1831,14 +2187,12 @@ static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
**/
void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
{
+ struct e1000_nvm_info *nvm = &hw->nvm;
union ich8_flash_protected_range pr0;
union ich8_hws_flash_status hsfsts;
u32 gfpreg;
- s32 ret_val;
- ret_val = e1000_acquire_swflag_ich8lan(hw);
- if (ret_val)
- return;
+ nvm->ops.acquire_nvm(hw);
gfpreg = er32flash(ICH_FLASH_GFPREG);
@@ -1859,7 +2213,7 @@ void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw)
hsfsts.hsf_status.flockdn = true;
ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval);
- e1000_release_swflag_ich8lan(hw);
+ nvm->ops.release_nvm(hw);
}
/**
@@ -2229,6 +2583,8 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
**/
static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
{
+ struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
+ u16 reg;
u32 ctrl, icr, kab;
s32 ret_val;
@@ -2263,6 +2619,18 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
ew32(PBS, E1000_PBS_16K);
}
+ if (hw->mac.type == e1000_pchlan) {
+ /* Save the NVM K1 bit setting*/
+ ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &reg);
+ if (ret_val)
+ return ret_val;
+
+ if (reg & E1000_NVM_K1_ENABLE)
+ dev_spec->nvm_k1_enabled = true;
+ else
+ dev_spec->nvm_k1_enabled = false;
+ }
+
ctrl = er32(CTRL);
if (!e1000_check_reset_block(hw)) {
@@ -2304,7 +2672,19 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
hw_dbg(hw, "Auto Read Done did not complete\n");
}
}
+ /* Dummy read to clear the phy wakeup bit after lcd reset */
+ if (hw->mac.type == e1000_pchlan)
+ e1e_rphy(hw, BM_WUC, &reg);
+ ret_val = e1000_sw_lcd_config_ich8lan(hw);
+ if (ret_val)
+ goto out;
+
+ if (hw->mac.type == e1000_pchlan) {
+ ret_val = e1000_oem_bits_config_ich8lan(hw, true);
+ if (ret_val)
+ goto out;
+ }
/*
* For PCH, this write will make sure that any noise
* will be detected as a CRC error and be dropped rather than show up
@@ -2323,6 +2703,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
if (hw->mac.type == e1000_pchlan)
ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
+out:
return ret_val;
}
@@ -2627,14 +3008,6 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
if (ret_val)
return ret_val;
- if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) {
- ret_val = e1000e_write_kmrn_reg(hw,
- E1000_KMRNCTRLSTA_K1_CONFIG,
- E1000_KMRNCTRLSTA_K1_DISABLE);
- if (ret_val)
- return ret_val;
- }
-
if ((hw->mac.type == e1000_ich8lan) &&
(hw->phy.type == e1000_phy_igp_3) &&
(*speed == SPEED_1000)) {
@@ -2843,9 +3216,8 @@ void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw)
E1000_PHY_CTRL_GBE_DISABLE;
ew32(PHY_CTRL, phy_ctrl);
- /* Workaround SWFLAG unexpectedly set during S0->Sx */
if (hw->mac.type == e1000_pchlan)
- udelay(500);
+ e1000_phy_hw_reset_ich8lan(hw);
default:
break;
}
@@ -3113,9 +3485,9 @@ static struct e1000_phy_operations ich8_phy_ops = {
};
static struct e1000_nvm_operations ich8_nvm_ops = {
- .acquire_nvm = e1000_acquire_swflag_ich8lan,
+ .acquire_nvm = e1000_acquire_nvm_ich8lan,
.read_nvm = e1000_read_nvm_ich8lan,
- .release_nvm = e1000_release_swflag_ich8lan,
+ .release_nvm = e1000_release_nvm_ich8lan,
.update_nvm = e1000_update_nvm_checksum_ich8lan,
.valid_led_default = e1000_valid_led_default_ich8lan,
.validate_nvm = e1000_validate_nvm_checksum_ich8lan,
diff --git a/drivers/net/e1000e/phy.c b/drivers/net/e1000e/phy.c
index 994401fd0664..03175b3a2c9e 100644
--- a/drivers/net/e1000e/phy.c
+++ b/drivers/net/e1000e/phy.c
@@ -95,13 +95,6 @@ static const u16 e1000_igp_2_cable_length_table[] =
/* BM PHY Copper Specific Control 1 */
#define BM_CS_CTRL1 16
-/* BM PHY Copper Specific Status */
-#define BM_CS_STATUS 17
-#define BM_CS_STATUS_LINK_UP 0x0400
-#define BM_CS_STATUS_RESOLVED 0x0800
-#define BM_CS_STATUS_SPEED_MASK 0xC000
-#define BM_CS_STATUS_SPEED_1000 0x8000
-
#define HV_MUX_DATA_CTRL PHY_REG(776, 16)
#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400
#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004
@@ -164,16 +157,25 @@ s32 e1000e_get_phy_id(struct e1000_hw *hw)
* MDIC mode. No harm in trying again in this case since
* the PHY ID is unknown at this point anyway
*/
+ ret_val = phy->ops.acquire_phy(hw);
+ if (ret_val)
+ goto out;
ret_val = e1000_set_mdio_slow_mode_hv(hw, true);
if (ret_val)
goto out;
+ phy->ops.release_phy(hw);
retry_count++;
}
out:
/* Revert to MDIO fast mode, if applicable */
- if (retry_count)
+ if (retry_count) {
+ ret_val = phy->ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
+ phy->ops.release_phy(hw);
+ }
return ret_val;
}
@@ -354,94 +356,173 @@ s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
}
/**
- * e1000e_read_phy_reg_igp - Read igp PHY register
+ * __e1000e_read_phy_reg_igp - Read igp PHY register
* @hw: pointer to the HW structure
* @offset: register offset to be read
* @data: pointer to the read data
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary, then reads the PHY register at offset
- * and storing the retrieved information in data. Release any acquired
+ * and stores the retrieved information in data. Release any acquired
* semaphores before exiting.
**/
-s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
+ bool locked)
{
- s32 ret_val;
+ s32 ret_val = 0;
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- return ret_val;
+ if (!locked) {
+ if (!(hw->phy.ops.acquire_phy))
+ goto out;
+
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ goto out;
+ }
if (offset > MAX_PHY_MULTI_PAGE_REG) {
ret_val = e1000e_write_phy_reg_mdic(hw,
IGP01E1000_PHY_PAGE_SELECT,
(u16)offset);
- if (ret_val) {
- hw->phy.ops.release_phy(hw);
- return ret_val;
- }
+ if (ret_val)
+ goto release;
}
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
- data);
-
- hw->phy.ops.release_phy(hw);
+ data);
+release:
+ if (!locked)
+ hw->phy.ops.release_phy(hw);
+out:
return ret_val;
}
/**
+ * e1000e_read_phy_reg_igp - Read igp PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Acquires semaphore then reads the PHY register at offset and stores the
+ * retrieved information in data.
+ * Release the acquired semaphore before exiting.
+ **/
+s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return __e1000e_read_phy_reg_igp(hw, offset, data, false);
+}
+
+/**
+ * e1000e_read_phy_reg_igp_locked - Read igp PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Reads the PHY register at offset and stores the retrieved information
+ * in data. Assumes semaphore already acquired.
+ **/
+s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return __e1000e_read_phy_reg_igp(hw, offset, data, true);
+}
+
+/**
* e1000e_write_phy_reg_igp - Write igp PHY register
* @hw: pointer to the HW structure
* @offset: register offset to write to
* @data: data to write at register offset
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary, then writes the data to PHY register
* at the offset. Release any acquired semaphores before exiting.
**/
-s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
+static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
+ bool locked)
{
- s32 ret_val;
+ s32 ret_val = 0;
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- return ret_val;
+ if (!locked) {
+ if (!(hw->phy.ops.acquire_phy))
+ goto out;
+
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ goto out;
+ }
if (offset > MAX_PHY_MULTI_PAGE_REG) {
ret_val = e1000e_write_phy_reg_mdic(hw,
IGP01E1000_PHY_PAGE_SELECT,
(u16)offset);
- if (ret_val) {
- hw->phy.ops.release_phy(hw);
- return ret_val;
- }
+ if (ret_val)
+ goto release;
}
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
- hw->phy.ops.release_phy(hw);
+release:
+ if (!locked)
+ hw->phy.ops.release_phy(hw);
+out:
return ret_val;
}
/**
- * e1000e_read_kmrn_reg - Read kumeran register
+ * e1000e_write_phy_reg_igp - Write igp PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore then writes the data to PHY register
+ * at the offset. Release any acquired semaphores before exiting.
+ **/
+s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return __e1000e_write_phy_reg_igp(hw, offset, data, false);
+}
+
+/**
+ * e1000e_write_phy_reg_igp_locked - Write igp PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Writes the data to PHY register at the offset.
+ * Assumes semaphore already acquired.
+ **/
+s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return __e1000e_write_phy_reg_igp(hw, offset, data, true);
+}
+
+/**
+ * __e1000_read_kmrn_reg - Read kumeran register
* @hw: pointer to the HW structure
* @offset: register offset to be read
* @data: pointer to the read data
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary. Then reads the PHY register at offset
* using the kumeran interface. The information retrieved is stored in data.
* Release any acquired semaphores before exiting.
**/
-s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
+ bool locked)
{
u32 kmrnctrlsta;
- s32 ret_val;
+ s32 ret_val = 0;
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- return ret_val;
+ if (!locked) {
+ if (!(hw->phy.ops.acquire_phy))
+ goto out;
+
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ goto out;
+ }
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
@@ -452,41 +533,111 @@ s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
kmrnctrlsta = er32(KMRNCTRLSTA);
*data = (u16)kmrnctrlsta;
- hw->phy.ops.release_phy(hw);
+ if (!locked)
+ hw->phy.ops.release_phy(hw);
+out:
return ret_val;
}
/**
- * e1000e_write_kmrn_reg - Write kumeran register
+ * e1000e_read_kmrn_reg - Read kumeran register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Acquires semaphore then reads the PHY register at offset using the
+ * kumeran interface. The information retrieved is stored in data.
+ * Release the acquired semaphore before exiting.
+ **/
+s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return __e1000_read_kmrn_reg(hw, offset, data, false);
+}
+
+/**
+ * e1000e_read_kmrn_reg_locked - Read kumeran register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Reads the PHY register at offset using the kumeran interface. The
+ * information retrieved is stored in data.
+ * Assumes semaphore already acquired.
+ **/
+s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return __e1000_read_kmrn_reg(hw, offset, data, true);
+}
+
+/**
+ * __e1000_write_kmrn_reg - Write kumeran register
* @hw: pointer to the HW structure
* @offset: register offset to write to
* @data: data to write at register offset
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary. Then write the data to PHY register
* at the offset using the kumeran interface. Release any acquired semaphores
* before exiting.
**/
-s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data)
+static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
+ bool locked)
{
u32 kmrnctrlsta;
- s32 ret_val;
+ s32 ret_val = 0;
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- return ret_val;
+ if (!locked) {
+ if (!(hw->phy.ops.acquire_phy))
+ goto out;
+
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ goto out;
+ }
kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
E1000_KMRNCTRLSTA_OFFSET) | data;
ew32(KMRNCTRLSTA, kmrnctrlsta);
udelay(2);
- hw->phy.ops.release_phy(hw);
+ if (!locked)
+ hw->phy.ops.release_phy(hw);
+
+out:
return ret_val;
}
/**
+ * e1000e_write_kmrn_reg - Write kumeran register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore then writes the data to the PHY register at the offset
+ * using the kumeran interface. Release the acquired semaphore before exiting.
+ **/
+s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return __e1000_write_kmrn_reg(hw, offset, data, false);
+}
+
+/**
+ * e1000e_write_kmrn_reg_locked - Write kumeran register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Write the data to PHY register at the offset using the kumeran interface.
+ * Assumes semaphore already acquired.
+ **/
+s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return __e1000_write_kmrn_reg(hw, offset, data, true);
+}
+
+/**
* e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
* @hw: pointer to the HW structure
*
@@ -2105,6 +2256,10 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
u32 page = offset >> IGP_PAGE_SHIFT;
u32 page_shift = 0;
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
@@ -2112,10 +2267,6 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
goto out;
}
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- goto out;
-
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
if (offset > MAX_PHY_MULTI_PAGE_REG) {
@@ -2135,18 +2286,15 @@ s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
(page << page_shift));
- if (ret_val) {
- hw->phy.ops.release_phy(hw);
+ if (ret_val)
goto out;
- }
}
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
- hw->phy.ops.release_phy(hw);
-
out:
+ hw->phy.ops.release_phy(hw);
return ret_val;
}
@@ -2167,6 +2315,10 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
u32 page = offset >> IGP_PAGE_SHIFT;
u32 page_shift = 0;
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
@@ -2174,10 +2326,6 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
goto out;
}
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- goto out;
-
hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
if (offset > MAX_PHY_MULTI_PAGE_REG) {
@@ -2197,17 +2345,14 @@ s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
/* Page is shifted left, PHY expects (page x 32) */
ret_val = e1000e_write_phy_reg_mdic(hw, page_select,
(page << page_shift));
- if (ret_val) {
- hw->phy.ops.release_phy(hw);
+ if (ret_val)
goto out;
- }
}
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
- hw->phy.ops.release_phy(hw);
-
out:
+ hw->phy.ops.release_phy(hw);
return ret_val;
}
@@ -2226,17 +2371,17 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
s32 ret_val;
u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
true);
- return ret_val;
+ goto out;
}
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- return ret_val;
-
hw->phy.addr = 1;
if (offset > MAX_PHY_MULTI_PAGE_REG) {
@@ -2245,16 +2390,14 @@ s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
page);
- if (ret_val) {
- hw->phy.ops.release_phy(hw);
- return ret_val;
- }
+ if (ret_val)
+ goto out;
}
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
+out:
hw->phy.ops.release_phy(hw);
-
return ret_val;
}
@@ -2272,17 +2415,17 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
s32 ret_val;
u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+
/* Page 800 works differently than the rest so it has its own func */
if (page == BM_WUC_PAGE) {
ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
false);
- return ret_val;
+ goto out;
}
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- return ret_val;
-
hw->phy.addr = 1;
if (offset > MAX_PHY_MULTI_PAGE_REG) {
@@ -2290,17 +2433,15 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
page);
- if (ret_val) {
- hw->phy.ops.release_phy(hw);
- return ret_val;
- }
+ if (ret_val)
+ goto out;
}
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
data);
+out:
hw->phy.ops.release_phy(hw);
-
return ret_val;
}
@@ -2320,6 +2461,8 @@ s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
* 3) Write the address using the address opcode (0x11)
* 4) Read or write the data using the data opcode (0x12)
* 5) Restore 769_17.2 to its original value
+ *
+ * Assumes semaphore already acquired.
**/
static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
u16 *data, bool read)
@@ -2327,20 +2470,12 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
s32 ret_val;
u16 reg = BM_PHY_REG_NUM(offset);
u16 phy_reg = 0;
- u8 phy_acquired = 1;
-
/* Gig must be disabled for MDIO accesses to page 800 */
if ((hw->mac.type == e1000_pchlan) &&
(!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
hw_dbg(hw, "Attempting to access page 800 while gig enabled\n");
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val) {
- phy_acquired = 0;
- goto out;
- }
-
/* All operations in this function are phy address 1 */
hw->phy.addr = 1;
@@ -2397,8 +2532,6 @@ static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
out:
- if (phy_acquired == 1)
- hw->phy.ops.release_phy(hw);
return ret_val;
}
@@ -2439,52 +2572,63 @@ static s32 e1000_set_d0_lplu_state(struct e1000_hw *hw, bool active)
return 0;
}
+/**
+ * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
+ * @hw: pointer to the HW structure
+ * @slow: true for slow mode, false for normal mode
+ *
+ * Assumes semaphore already acquired.
+ **/
s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow)
{
s32 ret_val = 0;
u16 data = 0;
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- return ret_val;
-
/* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */
hw->phy.addr = 1;
ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
(BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
- if (ret_val) {
- hw->phy.ops.release_phy(hw);
- return ret_val;
- }
+ if (ret_val)
+ goto out;
+
ret_val = e1000e_write_phy_reg_mdic(hw, BM_CS_CTRL1,
(0x2180 | (slow << 10)));
+ if (ret_val)
+ goto out;
/* dummy read when reverting to fast mode - throw away result */
if (!slow)
- e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data);
-
- hw->phy.ops.release_phy(hw);
+ ret_val = e1000e_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data);
+out:
return ret_val;
}
/**
- * e1000_read_phy_reg_hv - Read HV PHY register
+ * __e1000_read_phy_reg_hv - Read HV PHY register
* @hw: pointer to the HW structure
* @offset: register offset to be read
* @data: pointer to the read data
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary, then reads the PHY register at offset
- * and storing the retrieved information in data. Release any acquired
+ * and stores the retrieved information in data. Release any acquired
* semaphore before exiting.
**/
-s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
+ bool locked)
{
s32 ret_val;
u16 page = BM_PHY_REG_PAGE(offset);
u16 reg = BM_PHY_REG_NUM(offset);
bool in_slow_mode = false;
+ if (!locked) {
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+ }
+
/* Workaround failure in MDIO access while cable is disconnected */
if ((hw->phy.type == e1000_phy_82577) &&
!(er32(STATUS) & E1000_STATUS_LU)) {
@@ -2508,10 +2652,6 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
goto out;
}
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- goto out;
-
hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
if (page == HV_INTC_FC_PAGE_START)
@@ -2529,42 +2669,76 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
ret_val = e1000e_write_phy_reg_mdic(hw,
IGP01E1000_PHY_PAGE_SELECT,
(page << IGP_PAGE_SHIFT));
- if (ret_val) {
- hw->phy.ops.release_phy(hw);
- goto out;
- }
hw->phy.addr = phy_addr;
}
}
ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
data);
- hw->phy.ops.release_phy(hw);
-
out:
/* Revert to MDIO fast mode, if applicable */
if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
+ if (!locked)
+ hw->phy.ops.release_phy(hw);
+
return ret_val;
}
/**
- * e1000_write_phy_reg_hv - Write HV PHY register
+ * e1000_read_phy_reg_hv - Read HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Acquires semaphore then reads the PHY register at offset and stores
+ * the retrieved information in data. Release the acquired semaphore
+ * before exiting.
+ **/
+s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return __e1000_read_phy_reg_hv(hw, offset, data, false);
+}
+
+/**
+ * e1000_read_phy_reg_hv_locked - Read HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to be read
+ * @data: pointer to the read data
+ *
+ * Reads the PHY register at offset and stores the retrieved information
+ * in data. Assumes semaphore already acquired.
+ **/
+s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+ return __e1000_read_phy_reg_hv(hw, offset, data, true);
+}
+
+/**
+ * __e1000_write_phy_reg_hv - Write HV PHY register
* @hw: pointer to the HW structure
* @offset: register offset to write to
* @data: data to write at register offset
+ * @locked: semaphore has already been acquired or not
*
* Acquires semaphore, if necessary, then writes the data to PHY register
* at the offset. Release any acquired semaphores before exiting.
**/
-s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
+static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
+ bool locked)
{
s32 ret_val;
u16 page = BM_PHY_REG_PAGE(offset);
u16 reg = BM_PHY_REG_NUM(offset);
bool in_slow_mode = false;
+ if (!locked) {
+ ret_val = hw->phy.ops.acquire_phy(hw);
+ if (ret_val)
+ return ret_val;
+ }
+
/* Workaround failure in MDIO access while cable is disconnected */
if ((hw->phy.type == e1000_phy_82577) &&
!(er32(STATUS) & E1000_STATUS_LU)) {
@@ -2588,10 +2762,6 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
goto out;
}
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- goto out;
-
hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
if (page == HV_INTC_FC_PAGE_START)
@@ -2607,15 +2777,10 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
((MAX_PHY_REG_ADDRESS & reg) == 0) &&
(data & (1 << 11))) {
u16 data2 = 0x7EFF;
- hw->phy.ops.release_phy(hw);
ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
&data2, false);
if (ret_val)
goto out;
-
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val)
- goto out;
}
if (reg > MAX_PHY_MULTI_PAGE_REG) {
@@ -2630,27 +2795,53 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
ret_val = e1000e_write_phy_reg_mdic(hw,
IGP01E1000_PHY_PAGE_SELECT,
(page << IGP_PAGE_SHIFT));
- if (ret_val) {
- hw->phy.ops.release_phy(hw);
- goto out;
- }
hw->phy.addr = phy_addr;
}
}
ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
data);
- hw->phy.ops.release_phy(hw);
out:
/* Revert to MDIO fast mode, if applicable */
if ((hw->phy.type == e1000_phy_82577) && in_slow_mode)
ret_val = e1000_set_mdio_slow_mode_hv(hw, false);
+ if (!locked)
+ hw->phy.ops.release_phy(hw);
+
return ret_val;
}
/**
+ * e1000_write_phy_reg_hv - Write HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Acquires semaphore then writes the data to PHY register at the offset.
+ * Release the acquired semaphores before exiting.
+ **/
+s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return __e1000_write_phy_reg_hv(hw, offset, data, false);
+}
+
+/**
+ * e1000_write_phy_reg_hv_locked - Write HV PHY register
+ * @hw: pointer to the HW structure
+ * @offset: register offset to write to
+ * @data: data to write at register offset
+ *
+ * Writes the data to PHY register at the offset. Assumes semaphore
+ * already acquired.
+ **/
+s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
+{
+ return __e1000_write_phy_reg_hv(hw, offset, data, true);
+}
+
+/**
* e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page
* @page: page to be accessed
**/
@@ -2671,10 +2862,9 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page)
* @data: pointer to the data to be read or written
* @read: determines if operation is read or written
*
- * Acquires semaphore, if necessary, then reads the PHY register at offset
- * and storing the retreived information in data. Release any acquired
- * semaphores before exiting. Note that the procedure to read these regs
- * uses the address port and data port to read/write.
+ * Reads the PHY register at offset and stores the retreived information
+ * in data. Assumes semaphore already acquired. Note that the procedure
+ * to read these regs uses the address port and data port to read/write.
**/
static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
u16 *data, bool read)
@@ -2682,20 +2872,12 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
s32 ret_val;
u32 addr_reg = 0;
u32 data_reg = 0;
- u8 phy_acquired = 1;
/* This takes care of the difference with desktop vs mobile phy */
addr_reg = (hw->phy.type == e1000_phy_82578) ?
I82578_ADDR_REG : I82577_ADDR_REG;
data_reg = addr_reg + 1;
- ret_val = hw->phy.ops.acquire_phy(hw);
- if (ret_val) {
- hw_dbg(hw, "Could not acquire PHY\n");
- phy_acquired = 0;
- goto out;
- }
-
/* All operations in this function are phy address 2 */
hw->phy.addr = 2;
@@ -2718,8 +2900,6 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
}
out:
- if (phy_acquired == 1)
- hw->phy.ops.release_phy(hw);
return ret_val;
}
diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c
index 9c950bb5e90c..f7d9ac8324cb 100644
--- a/drivers/net/ethoc.c
+++ b/drivers/net/ethoc.c
@@ -223,24 +223,25 @@ struct ethoc_bd {
u32 addr;
};
-static u32 ethoc_read(struct ethoc *dev, loff_t offset)
+static inline u32 ethoc_read(struct ethoc *dev, loff_t offset)
{
return ioread32(dev->iobase + offset);
}
-static void ethoc_write(struct ethoc *dev, loff_t offset, u32 data)
+static inline void ethoc_write(struct ethoc *dev, loff_t offset, u32 data)
{
iowrite32(data, dev->iobase + offset);
}
-static void ethoc_read_bd(struct ethoc *dev, int index, struct ethoc_bd *bd)
+static inline void ethoc_read_bd(struct ethoc *dev, int index,
+ struct ethoc_bd *bd)
{
loff_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
bd->stat = ethoc_read(dev, offset + 0);
bd->addr = ethoc_read(dev, offset + 4);
}
-static void ethoc_write_bd(struct ethoc *dev, int index,
+static inline void ethoc_write_bd(struct ethoc *dev, int index,
const struct ethoc_bd *bd)
{
loff_t offset = ETHOC_BD_BASE + (index * sizeof(struct ethoc_bd));
@@ -248,33 +249,33 @@ static void ethoc_write_bd(struct ethoc *dev, int index,
ethoc_write(dev, offset + 4, bd->addr);
}
-static void ethoc_enable_irq(struct ethoc *dev, u32 mask)
+static inline void ethoc_enable_irq(struct ethoc *dev, u32 mask)
{
u32 imask = ethoc_read(dev, INT_MASK);
imask |= mask;
ethoc_write(dev, INT_MASK, imask);
}
-static void ethoc_disable_irq(struct ethoc *dev, u32 mask)
+static inline void ethoc_disable_irq(struct ethoc *dev, u32 mask)
{
u32 imask = ethoc_read(dev, INT_MASK);
imask &= ~mask;
ethoc_write(dev, INT_MASK, imask);
}
-static void ethoc_ack_irq(struct ethoc *dev, u32 mask)
+static inline void ethoc_ack_irq(struct ethoc *dev, u32 mask)
{
ethoc_write(dev, INT_SOURCE, mask);
}
-static void ethoc_enable_rx_and_tx(struct ethoc *dev)
+static inline void ethoc_enable_rx_and_tx(struct ethoc *dev)
{
u32 mode = ethoc_read(dev, MODER);
mode |= MODER_RXEN | MODER_TXEN;
ethoc_write(dev, MODER, mode);
}
-static void ethoc_disable_rx_and_tx(struct ethoc *dev)
+static inline void ethoc_disable_rx_and_tx(struct ethoc *dev)
{
u32 mode = ethoc_read(dev, MODER);
mode &= ~(MODER_RXEN | MODER_TXEN);
@@ -508,7 +509,7 @@ static irqreturn_t ethoc_interrupt(int irq, void *dev_id)
return IRQ_NONE;
}
- ethoc_ack_irq(priv, INT_MASK_ALL);
+ ethoc_ack_irq(priv, pending);
if (pending & INT_MASK_BUSY) {
dev_err(&dev->dev, "packet dropped\n");
diff --git a/drivers/net/fec.c b/drivers/net/fec.c
index 29234380e6c6..16a1d58419d9 100644
--- a/drivers/net/fec.c
+++ b/drivers/net/fec.c
@@ -1654,7 +1654,7 @@ static const struct net_device_ops fec_netdev_ops = {
*
* index is only used in legacy code
*/
-int __init fec_enet_init(struct net_device *dev, int index)
+static int fec_enet_init(struct net_device *dev, int index)
{
struct fec_enet_private *fep = netdev_priv(dev);
struct bufdesc *cbd_base;
diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c
index 801f088c134f..030913f8bd26 100644
--- a/drivers/net/ifb.c
+++ b/drivers/net/ifb.c
@@ -98,12 +98,13 @@ static void ri_tasklet(unsigned long dev)
stats->tx_packets++;
stats->tx_bytes +=skb->len;
- skb->dev = __dev_get_by_index(&init_net, skb->iif);
+ skb->dev = dev_get_by_index(&init_net, skb->iif);
if (!skb->dev) {
dev_kfree_skb(skb);
stats->tx_dropped++;
break;
}
+ dev_put(skb->dev);
skb->iif = _dev->ifindex;
if (from & AT_EGRESS) {
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index deaea8fa1032..b243ed3b0c36 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -732,7 +732,7 @@ static int igb_set_ringparam(struct net_device *netdev,
{
struct igb_adapter *adapter = netdev_priv(netdev);
struct igb_ring *temp_ring;
- int i, err;
+ int i, err = 0;
u32 new_rx_count, new_tx_count;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
@@ -752,18 +752,30 @@ static int igb_set_ringparam(struct net_device *netdev,
return 0;
}
+ while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
+ msleep(1);
+
+ if (!netif_running(adapter->netdev)) {
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ adapter->tx_ring[i].count = new_tx_count;
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ adapter->rx_ring[i].count = new_rx_count;
+ adapter->tx_ring_count = new_tx_count;
+ adapter->rx_ring_count = new_rx_count;
+ goto clear_reset;
+ }
+
if (adapter->num_tx_queues > adapter->num_rx_queues)
temp_ring = vmalloc(adapter->num_tx_queues * sizeof(struct igb_ring));
else
temp_ring = vmalloc(adapter->num_rx_queues * sizeof(struct igb_ring));
- if (!temp_ring)
- return -ENOMEM;
- while (test_and_set_bit(__IGB_RESETTING, &adapter->state))
- msleep(1);
+ if (!temp_ring) {
+ err = -ENOMEM;
+ goto clear_reset;
+ }
- if (netif_running(adapter->netdev))
- igb_down(adapter);
+ igb_down(adapter);
/*
* We can't just free everything and then setup again,
@@ -820,14 +832,11 @@ static int igb_set_ringparam(struct net_device *netdev,
adapter->rx_ring_count = new_rx_count;
}
-
- err = 0;
err_setup:
- if (netif_running(adapter->netdev))
- igb_up(adapter);
-
- clear_bit(__IGB_RESETTING, &adapter->state);
+ igb_up(adapter);
vfree(temp_ring);
+clear_reset:
+ clear_bit(__IGB_RESETTING, &adapter->state);
return err;
}
diff --git a/drivers/net/igbvf/ethtool.c b/drivers/net/igbvf/ethtool.c
index ee17a097d1ca..c68265bd0d1a 100644
--- a/drivers/net/igbvf/ethtool.c
+++ b/drivers/net/igbvf/ethtool.c
@@ -279,7 +279,7 @@ static int igbvf_set_ringparam(struct net_device *netdev,
{
struct igbvf_adapter *adapter = netdev_priv(netdev);
struct igbvf_ring *temp_ring;
- int err;
+ int err = 0;
u32 new_rx_count, new_tx_count;
if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
@@ -299,15 +299,22 @@ static int igbvf_set_ringparam(struct net_device *netdev,
return 0;
}
- temp_ring = vmalloc(sizeof(struct igbvf_ring));
- if (!temp_ring)
- return -ENOMEM;
-
while (test_and_set_bit(__IGBVF_RESETTING, &adapter->state))
msleep(1);
- if (netif_running(adapter->netdev))
- igbvf_down(adapter);
+ if (!netif_running(adapter->netdev)) {
+ adapter->tx_ring->count = new_tx_count;
+ adapter->rx_ring->count = new_rx_count;
+ goto clear_reset;
+ }
+
+ temp_ring = vmalloc(sizeof(struct igbvf_ring));
+ if (!temp_ring) {
+ err = -ENOMEM;
+ goto clear_reset;
+ }
+
+ igbvf_down(adapter);
/*
* We can't just free everything and then setup again,
@@ -339,14 +346,11 @@ static int igbvf_set_ringparam(struct net_device *netdev,
memcpy(adapter->rx_ring, temp_ring,sizeof(struct igbvf_ring));
}
-
- err = 0;
err_setup:
- if (netif_running(adapter->netdev))
- igbvf_up(adapter);
-
- clear_bit(__IGBVF_RESETTING, &adapter->state);
+ igbvf_up(adapter);
vfree(temp_ring);
+clear_reset:
+ clear_bit(__IGBVF_RESETTING, &adapter->state);
return err;
}
diff --git a/drivers/net/ixgbe/ixgbe_ethtool.c b/drivers/net/ixgbe/ixgbe_ethtool.c
index fa314cb005a4..856c18c207f3 100644
--- a/drivers/net/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ixgbe/ixgbe_ethtool.c
@@ -798,7 +798,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
{
struct ixgbe_adapter *adapter = netdev_priv(netdev);
struct ixgbe_ring *temp_tx_ring, *temp_rx_ring;
- int i, err;
+ int i, err = 0;
u32 new_rx_count, new_tx_count;
bool need_update = false;
@@ -822,6 +822,16 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
msleep(1);
+ if (!netif_running(adapter->netdev)) {
+ for (i = 0; i < adapter->num_tx_queues; i++)
+ adapter->tx_ring[i].count = new_tx_count;
+ for (i = 0; i < adapter->num_rx_queues; i++)
+ adapter->rx_ring[i].count = new_rx_count;
+ adapter->tx_ring_count = new_tx_count;
+ adapter->rx_ring_count = new_rx_count;
+ goto err_setup;
+ }
+
temp_tx_ring = kcalloc(adapter->num_tx_queues,
sizeof(struct ixgbe_ring), GFP_KERNEL);
if (!temp_tx_ring) {
@@ -879,8 +889,7 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
/* if rings need to be updated, here's the place to do it in one shot */
if (need_update) {
- if (netif_running(netdev))
- ixgbe_down(adapter);
+ ixgbe_down(adapter);
/* tx */
if (new_tx_count != adapter->tx_ring_count) {
@@ -897,13 +906,8 @@ static int ixgbe_set_ringparam(struct net_device *netdev,
temp_rx_ring = NULL;
adapter->rx_ring_count = new_rx_count;
}
- }
-
- /* success! */
- err = 0;
- if (netif_running(netdev))
ixgbe_up(adapter);
-
+ }
err_setup:
clear_bit(__IXGBE_RESETTING, &adapter->state);
return err;
diff --git a/drivers/net/ks8851.c b/drivers/net/ks8851.c
index 237835864357..a23f739d222f 100644
--- a/drivers/net/ks8851.c
+++ b/drivers/net/ks8851.c
@@ -171,6 +171,36 @@ static void ks8851_wrreg16(struct ks8851_net *ks, unsigned reg, unsigned val)
}
/**
+ * ks8851_wrreg8 - write 8bit register value to chip
+ * @ks: The chip state
+ * @reg: The register address
+ * @val: The value to write
+ *
+ * Issue a write to put the value @val into the register specified in @reg.
+ */
+static void ks8851_wrreg8(struct ks8851_net *ks, unsigned reg, unsigned val)
+{
+ struct spi_transfer *xfer = &ks->spi_xfer1;
+ struct spi_message *msg = &ks->spi_msg1;
+ __le16 txb[2];
+ int ret;
+ int bit;
+
+ bit = 1 << (reg & 3);
+
+ txb[0] = cpu_to_le16(MK_OP(bit, reg) | KS_SPIOP_WR);
+ txb[1] = val;
+
+ xfer->tx_buf = txb;
+ xfer->rx_buf = NULL;
+ xfer->len = 3;
+
+ ret = spi_sync(ks->spidev, msg);
+ if (ret < 0)
+ ks_err(ks, "spi_sync() failed\n");
+}
+
+/**
* ks8851_rx_1msg - select whether to use one or two messages for spi read
* @ks: The device structure
*
@@ -322,13 +352,12 @@ static void ks8851_soft_reset(struct ks8851_net *ks, unsigned op)
static int ks8851_write_mac_addr(struct net_device *dev)
{
struct ks8851_net *ks = netdev_priv(dev);
- u16 *mcp = (u16 *)dev->dev_addr;
+ int i;
mutex_lock(&ks->lock);
- ks8851_wrreg16(ks, KS_MARL, mcp[0]);
- ks8851_wrreg16(ks, KS_MARM, mcp[1]);
- ks8851_wrreg16(ks, KS_MARH, mcp[2]);
+ for (i = 0; i < ETH_ALEN; i++)
+ ks8851_wrreg8(ks, KS_MAR(i), dev->dev_addr[i]);
mutex_unlock(&ks->lock);
@@ -951,7 +980,7 @@ static void ks8851_set_rx_mode(struct net_device *dev)
mcptr = mcptr->next;
}
- rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXAE | RXCR1_RXPAFMA;
+ rxctrl.rxcr1 = RXCR1_RXME | RXCR1_RXPAFMA;
} else {
/* just accept broadcast / unicast */
rxctrl.rxcr1 = RXCR1_RXPAFMA;
@@ -1239,6 +1268,9 @@ static int __devinit ks8851_probe(struct spi_device *spi)
ndev->netdev_ops = &ks8851_netdev_ops;
ndev->irq = spi->irq;
+ /* issue a global soft reset to reset the device. */
+ ks8851_soft_reset(ks, GRR_GSR);
+
/* simple check for a valid chip being connected to the bus */
if ((ks8851_rdreg16(ks, KS_CIDER) & ~CIDER_REV_MASK) != CIDER_ID) {
diff --git a/drivers/net/ks8851.h b/drivers/net/ks8851.h
index 85abe147afbf..f52c312cc356 100644
--- a/drivers/net/ks8851.h
+++ b/drivers/net/ks8851.h
@@ -16,6 +16,7 @@
#define CCR_32PIN (1 << 0)
/* MAC address registers */
+#define KS_MAR(_m) 0x15 - (_m)
#define KS_MARL 0x10
#define KS_MARM 0x12
#define KS_MARH 0x14
diff --git a/drivers/net/mlx4/main.c b/drivers/net/mlx4/main.c
index 5dd7225b178e..291a505fd4fc 100644
--- a/drivers/net/mlx4/main.c
+++ b/drivers/net/mlx4/main.c
@@ -1282,6 +1282,7 @@ static struct pci_device_id mlx4_pci_table[] = {
{ PCI_VDEVICE(MELLANOX, 0x6372) }, /* MT25458 ConnectX EN 10GBASE-T 10GigE */
{ PCI_VDEVICE(MELLANOX, 0x675a) }, /* MT25458 ConnectX EN 10GBASE-T+Gen2 10GigE */
{ PCI_VDEVICE(MELLANOX, 0x6764) }, /* MT26468 ConnectX EN 10GigE PCIe gen2*/
+ { PCI_VDEVICE(MELLANOX, 0x6746) }, /* MT26438 ConnectX EN 40GigE PCIe gen2 5GT/s */
{ PCI_VDEVICE(MELLANOX, 0x676e) }, /* MT26478 ConnectX2 40GigE PCIe gen2 */
{ 0, }
};
diff --git a/drivers/net/myri10ge/myri10ge.c b/drivers/net/myri10ge/myri10ge.c
index 6930c87f362e..f3624517cb0e 100644
--- a/drivers/net/myri10ge/myri10ge.c
+++ b/drivers/net/myri10ge/myri10ge.c
@@ -75,7 +75,7 @@
#include "myri10ge_mcp.h"
#include "myri10ge_mcp_gen_header.h"
-#define MYRI10GE_VERSION_STR "1.5.0-1.432"
+#define MYRI10GE_VERSION_STR "1.5.1-1.451"
MODULE_DESCRIPTION("Myricom 10G driver (10GbE)");
MODULE_AUTHOR("Maintainer: help@myri.com");
@@ -1624,10 +1624,21 @@ myri10ge_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
return 0;
}
}
- if (*ptr == 'R' || *ptr == 'Q') {
- /* We've found either an XFP or quad ribbon fiber */
+ if (*ptr == '2')
+ ptr++;
+ if (*ptr == 'R' || *ptr == 'Q' || *ptr == 'S') {
+ /* We've found either an XFP, quad ribbon fiber, or SFP+ */
cmd->port = PORT_FIBRE;
+ cmd->supported |= SUPPORTED_FIBRE;
+ cmd->advertising |= ADVERTISED_FIBRE;
+ } else {
+ cmd->port = PORT_OTHER;
}
+ if (*ptr == 'R' || *ptr == 'S')
+ cmd->transceiver = XCVR_EXTERNAL;
+ else
+ cmd->transceiver = XCVR_INTERNAL;
+
return 0;
}
diff --git a/drivers/net/netxen/netxen_nic_hdr.h b/drivers/net/netxen/netxen_nic_hdr.h
index 7a7177421d7c..1c46da632125 100644
--- a/drivers/net/netxen/netxen_nic_hdr.h
+++ b/drivers/net/netxen/netxen_nic_hdr.h
@@ -419,6 +419,7 @@ enum {
#define NETXEN_CRB_ROMUSB \
NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_ROMUSB)
#define NETXEN_CRB_I2Q NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2Q)
+#define NETXEN_CRB_I2C0 NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_I2C0)
#define NETXEN_CRB_SMB NETXEN_PCI_CRB_WINDOW(NETXEN_HW_PX_MAP_CRB_SMB)
#define NETXEN_CRB_MAX NETXEN_PCI_CRB_WINDOW(64)
diff --git a/drivers/net/netxen/netxen_nic_hw.c b/drivers/net/netxen/netxen_nic_hw.c
index 32314000dfcd..3185a98b0917 100644
--- a/drivers/net/netxen/netxen_nic_hw.c
+++ b/drivers/net/netxen/netxen_nic_hw.c
@@ -1901,22 +1901,16 @@ netxen_setup_hwops(struct netxen_adapter *adapter)
int netxen_nic_get_board_info(struct netxen_adapter *adapter)
{
- int offset, board_type, magic, header_version;
+ int offset, board_type, magic;
struct pci_dev *pdev = adapter->pdev;
offset = NX_FW_MAGIC_OFFSET;
if (netxen_rom_fast_read(adapter, offset, &magic))
return -EIO;
- offset = NX_HDR_VERSION_OFFSET;
- if (netxen_rom_fast_read(adapter, offset, &header_version))
- return -EIO;
-
- if (magic != NETXEN_BDINFO_MAGIC ||
- header_version != NETXEN_BDINFO_VERSION) {
- dev_err(&pdev->dev,
- "invalid board config, magic=%08x, version=%08x\n",
- magic, header_version);
+ if (magic != NETXEN_BDINFO_MAGIC) {
+ dev_err(&pdev->dev, "invalid board config, magic=%08x\n",
+ magic);
return -EIO;
}
diff --git a/drivers/net/netxen/netxen_nic_init.c b/drivers/net/netxen/netxen_nic_init.c
index 91c2bc61c8eb..e40b914d6faf 100644
--- a/drivers/net/netxen/netxen_nic_init.c
+++ b/drivers/net/netxen/netxen_nic_init.c
@@ -531,6 +531,8 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
continue;
if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) {
+ if (off == (NETXEN_CRB_I2C0 + 0x1c))
+ continue;
/* do not reset PCI */
if (off == (ROMUSB_GLB + 0xbc))
continue;
@@ -553,12 +555,6 @@ int netxen_pinit_from_rom(struct netxen_adapter *adapter, int verbose)
continue;
}
- if (off == NETXEN_ADDR_ERROR) {
- printk(KERN_ERR "%s: Err: Unknown addr: 0x%08x\n",
- netxen_nic_driver_name, buf[i].addr);
- continue;
- }
-
init_delay = 1;
/* After writing this register, HW needs time for CRB */
/* to quiet down (else crb_window returns 0xffffffff) */
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 7fc15e9e8adb..0b4a56a8c8d5 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -1919,6 +1919,7 @@ static void netxen_tx_timeout_task(struct work_struct *work)
request_reset:
adapter->need_fw_reset = 1;
+ clear_bit(__NX_RESETTING, &adapter->state);
}
struct net_device_stats *netxen_nic_get_stats(struct net_device *netdev)
diff --git a/drivers/net/niu.c b/drivers/net/niu.c
index f9364d0678f2..d6c7ac68f6ea 100644
--- a/drivers/net/niu.c
+++ b/drivers/net/niu.c
@@ -3545,7 +3545,7 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
rp->rcr_index = index;
skb_reserve(skb, NET_IP_ALIGN);
- __pskb_pull_tail(skb, min(len, NIU_RXPULL_MAX));
+ __pskb_pull_tail(skb, min(len, VLAN_ETH_HLEN));
rp->rx_packets++;
rp->rx_bytes += skb->len;
diff --git a/drivers/net/pcmcia/pcnet_cs.c b/drivers/net/pcmcia/pcnet_cs.c
index bd3447f04902..94c9ad2746bc 100644
--- a/drivers/net/pcmcia/pcnet_cs.c
+++ b/drivers/net/pcmcia/pcnet_cs.c
@@ -1760,7 +1760,7 @@ static struct pcmcia_device_id pcnet_ids[] = {
PCMCIA_DEVICE_CIS_MANF_CARD(0xc00f, 0x0002, "cis/LA-PCM.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("KTI", "PE520 PLUS", 0xad180345, 0x9d58d392, "PE520.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("NDC", "Ethernet", 0x01c43ae1, 0x00b2e941, "cis/NE2K.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "PE-200.cis"),
+ PCMCIA_DEVICE_CIS_PROD_ID12("PMX ", "PE-200", 0x34f3f1c8, 0x10b59f8c, "cis/PE-200.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("TAMARACK", "Ethernet", 0xcf434fba, 0x00b2e941, "cis/tamarack.cis"),
PCMCIA_DEVICE_PROD_ID12("Ethernet", "CF Size PC Card", 0x00b2e941, 0x43ac239b),
PCMCIA_DEVICE_PROD_ID123("Fast Ethernet", "CF Size PC Card", "1.0",
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index 7cbf6f9b51de..2559991eea6a 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -111,9 +111,6 @@ struct pppoe_net {
rwlock_t hash_lock;
};
-/* to eliminate a race btw pppoe_flush_dev and pppoe_release */
-static DEFINE_SPINLOCK(flush_lock);
-
/*
* PPPoE could be in the following stages:
* 1) Discovery stage (to obtain remote MAC and Session ID)
@@ -303,45 +300,48 @@ static void pppoe_flush_dev(struct net_device *dev)
write_lock_bh(&pn->hash_lock);
for (i = 0; i < PPPOE_HASH_SIZE; i++) {
struct pppox_sock *po = pn->hash_table[i];
+ struct sock *sk;
- while (po != NULL) {
- struct sock *sk;
- if (po->pppoe_dev != dev) {
+ while (po) {
+ while (po && po->pppoe_dev != dev) {
po = po->next;
- continue;
}
+
+ if (!po)
+ break;
+
sk = sk_pppox(po);
- spin_lock(&flush_lock);
- po->pppoe_dev = NULL;
- spin_unlock(&flush_lock);
- dev_put(dev);
/* We always grab the socket lock, followed by the
- * hash_lock, in that order. Since we should
- * hold the sock lock while doing any unbinding,
- * we need to release the lock we're holding.
- * Hold a reference to the sock so it doesn't disappear
- * as we're jumping between locks.
+ * hash_lock, in that order. Since we should hold the
+ * sock lock while doing any unbinding, we need to
+ * release the lock we're holding. Hold a reference to
+ * the sock so it doesn't disappear as we're jumping
+ * between locks.
*/
sock_hold(sk);
-
write_unlock_bh(&pn->hash_lock);
lock_sock(sk);
- if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+ if (po->pppoe_dev == dev
+ && sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
pppox_unbind_sock(sk);
sk->sk_state = PPPOX_ZOMBIE;
sk->sk_state_change(sk);
+ po->pppoe_dev = NULL;
+ dev_put(dev);
}
release_sock(sk);
sock_put(sk);
- /* Restart scan at the beginning of this hash chain.
- * While the lock was dropped the chain contents may
- * have changed.
+ /* Restart the process from the start of the current
+ * hash chain. We dropped locks so the world may have
+ * change from underneath us.
*/
+
+ BUG_ON(pppoe_pernet(dev_net(dev)) == NULL);
write_lock_bh(&pn->hash_lock);
po = pn->hash_table[i];
}
@@ -388,11 +388,16 @@ static int pppoe_rcv_core(struct sock *sk, struct sk_buff *skb)
struct pppox_sock *po = pppox_sk(sk);
struct pppox_sock *relay_po;
+ /* Backlog receive. Semantics of backlog rcv preclude any code from
+ * executing in lock_sock()/release_sock() bounds; meaning sk->sk_state
+ * can't change.
+ */
+
if (sk->sk_state & PPPOX_BOUND) {
ppp_input(&po->chan, skb);
} else if (sk->sk_state & PPPOX_RELAY) {
- relay_po = get_item_by_addr(dev_net(po->pppoe_dev),
- &po->pppoe_relay);
+ relay_po = get_item_by_addr(sock_net(sk),
+ &po->pppoe_relay);
if (relay_po == NULL)
goto abort_kfree;
@@ -447,6 +452,10 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
goto drop;
pn = pppoe_pernet(dev_net(dev));
+
+ /* Note that get_item does a sock_hold(), so sk_pppox(po)
+ * is known to be safe.
+ */
po = get_item(pn, ph->sid, eth_hdr(skb)->h_source, dev->ifindex);
if (!po)
goto drop;
@@ -561,6 +570,7 @@ static int pppoe_release(struct socket *sock)
struct sock *sk = sock->sk;
struct pppox_sock *po;
struct pppoe_net *pn;
+ struct net *net = NULL;
if (!sk)
return 0;
@@ -571,44 +581,28 @@ static int pppoe_release(struct socket *sock)
return -EBADF;
}
+ po = pppox_sk(sk);
+
+ if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+ dev_put(po->pppoe_dev);
+ po->pppoe_dev = NULL;
+ }
+
pppox_unbind_sock(sk);
/* Signal the death of the socket. */
sk->sk_state = PPPOX_DEAD;
- /*
- * pppoe_flush_dev could lead to a race with
- * this routine so we use flush_lock to eliminate
- * such a case (we only need per-net specific data)
- */
- spin_lock(&flush_lock);
- po = pppox_sk(sk);
- if (!po->pppoe_dev) {
- spin_unlock(&flush_lock);
- goto out;
- }
- pn = pppoe_pernet(dev_net(po->pppoe_dev));
- spin_unlock(&flush_lock);
+ net = sock_net(sk);
+ pn = pppoe_pernet(net);
/*
* protect "po" from concurrent updates
* on pppoe_flush_dev
*/
- write_lock_bh(&pn->hash_lock);
+ delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote,
+ po->pppoe_ifindex);
- po = pppox_sk(sk);
- if (stage_session(po->pppoe_pa.sid))
- __delete_item(pn, po->pppoe_pa.sid, po->pppoe_pa.remote,
- po->pppoe_ifindex);
-
- if (po->pppoe_dev) {
- dev_put(po->pppoe_dev);
- po->pppoe_dev = NULL;
- }
-
- write_unlock_bh(&pn->hash_lock);
-
-out:
sock_orphan(sk);
sock->sk = NULL;
@@ -625,8 +619,9 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
struct sock *sk = sock->sk;
struct sockaddr_pppox *sp = (struct sockaddr_pppox *)uservaddr;
struct pppox_sock *po = pppox_sk(sk);
- struct net_device *dev;
+ struct net_device *dev = NULL;
struct pppoe_net *pn;
+ struct net *net = NULL;
int error;
lock_sock(sk);
@@ -652,12 +647,14 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
/* Delete the old binding */
if (stage_session(po->pppoe_pa.sid)) {
pppox_unbind_sock(sk);
+ pn = pppoe_pernet(sock_net(sk));
+ delete_item(pn, po->pppoe_pa.sid,
+ po->pppoe_pa.remote, po->pppoe_ifindex);
if (po->pppoe_dev) {
- pn = pppoe_pernet(dev_net(po->pppoe_dev));
- delete_item(pn, po->pppoe_pa.sid,
- po->pppoe_pa.remote, po->pppoe_ifindex);
dev_put(po->pppoe_dev);
+ po->pppoe_dev = NULL;
}
+
memset(sk_pppox(po) + 1, 0,
sizeof(struct pppox_sock) - sizeof(struct sock));
sk->sk_state = PPPOX_NONE;
@@ -666,16 +663,15 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
/* Re-bind in session stage only */
if (stage_session(sp->sa_addr.pppoe.sid)) {
error = -ENODEV;
- dev = dev_get_by_name(sock_net(sk), sp->sa_addr.pppoe.dev);
+ net = sock_net(sk);
+ dev = dev_get_by_name(net, sp->sa_addr.pppoe.dev);
if (!dev)
- goto end;
+ goto err_put;
po->pppoe_dev = dev;
po->pppoe_ifindex = dev->ifindex;
- pn = pppoe_pernet(dev_net(dev));
- write_lock_bh(&pn->hash_lock);
+ pn = pppoe_pernet(net);
if (!(dev->flags & IFF_UP)) {
- write_unlock_bh(&pn->hash_lock);
goto err_put;
}
@@ -683,6 +679,7 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
&sp->sa_addr.pppoe,
sizeof(struct pppoe_addr));
+ write_lock_bh(&pn->hash_lock);
error = __set_item(pn, po);
write_unlock_bh(&pn->hash_lock);
if (error < 0)
@@ -696,8 +693,11 @@ static int pppoe_connect(struct socket *sock, struct sockaddr *uservaddr,
po->chan.ops = &pppoe_chan_ops;
error = ppp_register_net_channel(dev_net(dev), &po->chan);
- if (error)
+ if (error) {
+ delete_item(pn, po->pppoe_pa.sid,
+ po->pppoe_pa.remote, po->pppoe_ifindex);
goto err_put;
+ }
sk->sk_state = PPPOX_CONNECTED;
}
@@ -915,6 +915,14 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
struct pppoe_hdr *ph;
int data_len = skb->len;
+ /* The higher-level PPP code (ppp_unregister_channel()) ensures the PPP
+ * xmit operations conclude prior to an unregistration call. Thus
+ * sk->sk_state cannot change, so we don't need to do lock_sock().
+ * But, we also can't do a lock_sock since that introduces a potential
+ * deadlock as we'd reverse the lock ordering used when calling
+ * ppp_unregister_channel().
+ */
+
if (sock_flag(sk, SOCK_DEAD) || !(sk->sk_state & PPPOX_CONNECTED))
goto abort;
@@ -944,7 +952,6 @@ static int __pppoe_xmit(struct sock *sk, struct sk_buff *skb)
po->pppoe_pa.remote, NULL, data_len);
dev_queue_xmit(skb);
-
return 1;
abort:
diff --git a/drivers/net/qlge/qlge.h b/drivers/net/qlge/qlge.h
index e7285f01bd04..c2383adcd527 100644
--- a/drivers/net/qlge/qlge.h
+++ b/drivers/net/qlge/qlge.h
@@ -95,6 +95,7 @@ enum {
/* Misc. stuff */
MAILBOX_COUNT = 16,
+ MAILBOX_TIMEOUT = 5,
PROC_ADDR_RDY = (1 << 31),
PROC_ADDR_R = (1 << 30),
diff --git a/drivers/net/qlge/qlge_main.c b/drivers/net/qlge/qlge_main.c
index 48b45df85ec9..cea7531f4f40 100644
--- a/drivers/net/qlge/qlge_main.c
+++ b/drivers/net/qlge/qlge_main.c
@@ -3916,6 +3916,7 @@ static int __devinit ql_init_device(struct pci_dev *pdev,
goto err_out;
}
+ pci_save_state(pdev);
qdev->reg_base =
ioremap_nocache(pci_resource_start(pdev, 1),
pci_resource_len(pdev, 1));
@@ -4070,6 +4071,33 @@ static void __devexit qlge_remove(struct pci_dev *pdev)
free_netdev(ndev);
}
+/* Clean up resources without touching hardware. */
+static void ql_eeh_close(struct net_device *ndev)
+{
+ int i;
+ struct ql_adapter *qdev = netdev_priv(ndev);
+
+ if (netif_carrier_ok(ndev)) {
+ netif_carrier_off(ndev);
+ netif_stop_queue(ndev);
+ }
+
+ if (test_bit(QL_ADAPTER_UP, &qdev->flags))
+ cancel_delayed_work_sync(&qdev->asic_reset_work);
+ cancel_delayed_work_sync(&qdev->mpi_reset_work);
+ cancel_delayed_work_sync(&qdev->mpi_work);
+ cancel_delayed_work_sync(&qdev->mpi_idc_work);
+ cancel_delayed_work_sync(&qdev->mpi_port_cfg_work);
+
+ for (i = 0; i < qdev->rss_ring_count; i++)
+ netif_napi_del(&qdev->rx_ring[i].napi);
+
+ clear_bit(QL_ADAPTER_UP, &qdev->flags);
+ ql_tx_ring_clean(qdev);
+ ql_free_rx_buffers(qdev);
+ ql_release_adapter_resources(qdev);
+}
+
/*
* This callback is called by the PCI subsystem whenever
* a PCI bus error is detected.
@@ -4078,17 +4106,21 @@ static pci_ers_result_t qlge_io_error_detected(struct pci_dev *pdev,
enum pci_channel_state state)
{
struct net_device *ndev = pci_get_drvdata(pdev);
- struct ql_adapter *qdev = netdev_priv(ndev);
-
- netif_device_detach(ndev);
- if (state == pci_channel_io_perm_failure)
+ switch (state) {
+ case pci_channel_io_normal:
+ return PCI_ERS_RESULT_CAN_RECOVER;
+ case pci_channel_io_frozen:
+ netif_device_detach(ndev);
+ if (netif_running(ndev))
+ ql_eeh_close(ndev);
+ pci_disable_device(pdev);
+ return PCI_ERS_RESULT_NEED_RESET;
+ case pci_channel_io_perm_failure:
+ dev_err(&pdev->dev,
+ "%s: pci_channel_io_perm_failure.\n", __func__);
return PCI_ERS_RESULT_DISCONNECT;
-
- if (netif_running(ndev))
- ql_adapter_down(qdev);
-
- pci_disable_device(pdev);
+ }
/* Request a slot reset. */
return PCI_ERS_RESULT_NEED_RESET;
@@ -4105,25 +4137,15 @@ static pci_ers_result_t qlge_io_slot_reset(struct pci_dev *pdev)
struct net_device *ndev = pci_get_drvdata(pdev);
struct ql_adapter *qdev = netdev_priv(ndev);
+ pdev->error_state = pci_channel_io_normal;
+
+ pci_restore_state(pdev);
if (pci_enable_device(pdev)) {
QPRINTK(qdev, IFUP, ERR,
"Cannot re-enable PCI device after reset.\n");
return PCI_ERS_RESULT_DISCONNECT;
}
-
pci_set_master(pdev);
-
- netif_carrier_off(ndev);
- ql_adapter_reset(qdev);
-
- /* Make sure the EEPROM is good */
- memcpy(ndev->perm_addr, ndev->dev_addr, ndev->addr_len);
-
- if (!is_valid_ether_addr(ndev->perm_addr)) {
- QPRINTK(qdev, IFUP, ERR, "After reset, invalid MAC address.\n");
- return PCI_ERS_RESULT_DISCONNECT;
- }
-
return PCI_ERS_RESULT_RECOVERED;
}
@@ -4131,17 +4153,21 @@ static void qlge_io_resume(struct pci_dev *pdev)
{
struct net_device *ndev = pci_get_drvdata(pdev);
struct ql_adapter *qdev = netdev_priv(ndev);
+ int err = 0;
- pci_set_master(pdev);
-
+ if (ql_adapter_reset(qdev))
+ QPRINTK(qdev, DRV, ERR, "reset FAILED!\n");
if (netif_running(ndev)) {
- if (ql_adapter_up(qdev)) {
+ err = qlge_open(ndev);
+ if (err) {
QPRINTK(qdev, IFUP, ERR,
"Device initialization failed after reset.\n");
return;
}
+ } else {
+ QPRINTK(qdev, IFUP, ERR,
+ "Device was not running prior to EEH.\n");
}
-
netif_device_attach(ndev);
}
diff --git a/drivers/net/qlge/qlge_mpi.c b/drivers/net/qlge/qlge_mpi.c
index 99e58e3f8e22..bcf13c96f73f 100644
--- a/drivers/net/qlge/qlge_mpi.c
+++ b/drivers/net/qlge/qlge_mpi.c
@@ -470,7 +470,8 @@ end:
*/
static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
{
- int status, count;
+ int status;
+ unsigned long count;
/* Begin polled mode for MPI */
@@ -491,9 +492,9 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
/* Wait for the command to complete. We loop
* here because some AEN might arrive while
* we're waiting for the mailbox command to
- * complete. If more than 5 arrive then we can
+ * complete. If more than 5 seconds expire we can
* assume something is wrong. */
- count = 5;
+ count = jiffies + HZ * MAILBOX_TIMEOUT;
do {
/* Wait for the interrupt to come in. */
status = ql_wait_mbx_cmd_cmplt(qdev);
@@ -517,15 +518,15 @@ static int ql_mailbox_command(struct ql_adapter *qdev, struct mbox_params *mbcp)
MB_CMD_STS_GOOD) ||
((mbcp->mbox_out[0] & 0x0000f000) ==
MB_CMD_STS_INTRMDT))
- break;
- } while (--count);
+ goto done;
+ } while (time_before(jiffies, count));
- if (!count) {
- QPRINTK(qdev, DRV, ERR,
- "Timed out waiting for mailbox complete.\n");
- status = -ETIMEDOUT;
- goto end;
- }
+ QPRINTK(qdev, DRV, ERR,
+ "Timed out waiting for mailbox complete.\n");
+ status = -ETIMEDOUT;
+ goto end;
+
+done:
/* Now we can clear the interrupt condition
* and look at our status.
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 83c47d95c3aa..fa4935678488 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -1029,7 +1029,10 @@ static void rtl8169_vlan_rx_register(struct net_device *dev,
spin_lock_irqsave(&tp->lock, flags);
tp->vlgrp = grp;
- if (tp->vlgrp)
+ /*
+ * Do not disable RxVlan on 8110SCd.
+ */
+ if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05))
tp->cp_cmd |= RxVlan;
else
tp->cp_cmd &= ~RxVlan;
@@ -3197,6 +3200,14 @@ rtl8169_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
}
rtl8169_init_phy(dev, tp);
+
+ /*
+ * Pretend we are using VLANs; This bypasses a nasty bug where
+ * Interrupts stop flowing on high load on 8110SCd controllers.
+ */
+ if (tp->mac_version == RTL_GIGA_MAC_VER_05)
+ RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan);
+
device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL);
out:
@@ -3368,7 +3379,7 @@ static u16 rtl_rw_cpluscmd(void __iomem *ioaddr)
static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz)
{
/* Low hurts. Let's disable the filtering. */
- RTL_W16(RxMaxSize, rx_buf_sz);
+ RTL_W16(RxMaxSize, rx_buf_sz + 1);
}
static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version)
diff --git a/drivers/net/sfc/rx.c b/drivers/net/sfc/rx.c
index 01f9432c31ef..98bff5ada09a 100644
--- a/drivers/net/sfc/rx.c
+++ b/drivers/net/sfc/rx.c
@@ -444,7 +444,8 @@ static void efx_rx_packet__check_len(struct efx_rx_queue *rx_queue,
* the appropriate LRO method
*/
static void efx_rx_packet_lro(struct efx_channel *channel,
- struct efx_rx_buffer *rx_buf)
+ struct efx_rx_buffer *rx_buf,
+ bool checksummed)
{
struct napi_struct *napi = &channel->napi_str;
@@ -466,7 +467,8 @@ static void efx_rx_packet_lro(struct efx_channel *channel,
skb->len = rx_buf->len;
skb->data_len = rx_buf->len;
skb->truesize += rx_buf->len;
- skb->ip_summed = CHECKSUM_UNNECESSARY;
+ skb->ip_summed =
+ checksummed ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE;
napi_gro_frags(napi);
@@ -475,6 +477,7 @@ out:
rx_buf->page = NULL;
} else {
EFX_BUG_ON_PARANOID(!rx_buf->skb);
+ EFX_BUG_ON_PARANOID(!checksummed);
napi_gro_receive(napi, rx_buf->skb);
rx_buf->skb = NULL;
@@ -570,7 +573,7 @@ void __efx_rx_packet(struct efx_channel *channel,
}
if (likely(checksummed || rx_buf->page)) {
- efx_rx_packet_lro(channel, rx_buf);
+ efx_rx_packet_lro(channel, rx_buf, checksummed);
goto done;
}
diff --git a/drivers/net/sh_eth.c b/drivers/net/sh_eth.c
index f49d0800c1d1..528b912a4b0d 100644
--- a/drivers/net/sh_eth.c
+++ b/drivers/net/sh_eth.c
@@ -30,6 +30,7 @@
#include <linux/phy.h>
#include <linux/cache.h>
#include <linux/io.h>
+#include <asm/cacheflush.h>
#include "sh_eth.h"
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 2ab5c39f33ca..6a10d7ba5877 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -4538,6 +4538,8 @@ static int __devinit sky2_probe(struct pci_dev *pdev,
goto err_out_free_netdev;
}
+ netif_carrier_off(dev);
+
netif_napi_add(dev, &hw->napi, sky2_poll, NAPI_WEIGHT);
err = request_irq(pdev->irq, sky2_intr,
diff --git a/drivers/net/tokenring/ibmtr.c b/drivers/net/tokenring/ibmtr.c
index 36cb2423bcf1..75fa32e34fd0 100644
--- a/drivers/net/tokenring/ibmtr.c
+++ b/drivers/net/tokenring/ibmtr.c
@@ -1144,9 +1144,16 @@ static void dir_open_adapter (struct net_device *dev)
} else {
char **prphase = printphase;
char **prerror = printerror;
+ int pnr = err / 16 - 1;
+ int enr = err % 16 - 1;
DPRINTK("TR Adapter misc open failure, error code = ");
- printk("0x%x, Phase: %s, Error: %s\n",
- err, prphase[err/16 -1], prerror[err%16 -1]);
+ if (pnr < 0 || pnr >= ARRAY_SIZE(printphase) ||
+ enr < 0 ||
+ enr >= ARRAY_SIZE(printerror))
+ printk("0x%x, invalid Phase/Error.", err);
+ else
+ printk("0x%x, Phase: %s, Error: %s\n", err,
+ prphase[pnr], prerror[enr]);
printk(" retrying after %ds delay...\n",
TR_RETRY_INTERVAL/HZ);
}
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index 72470f77f556..a2b30a10064f 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -649,6 +649,10 @@ static const struct usb_device_id products[] = {
USB_DEVICE(0x0fe6, 0x8101), /* DM9601 USB to Fast Ethernet Adapter */
.driver_info = (unsigned long)&dm9601_info,
},
+ {
+ USB_DEVICE(0x0a46, 0x9000), /* DM9000E */
+ .driver_info = (unsigned long)&dm9601_info,
+ },
{}, // END
};
diff --git a/drivers/net/usb/rndis_host.c b/drivers/net/usb/rndis_host.c
index 0caa8008c51c..f56dec6119c3 100644
--- a/drivers/net/usb/rndis_host.c
+++ b/drivers/net/usb/rndis_host.c
@@ -362,12 +362,12 @@ generic_rndis_bind(struct usbnet *dev, struct usb_interface *intf, int flags)
retval = -EINVAL;
goto halt_fail_and_release;
}
- dev->hard_mtu = tmp;
- net->mtu = dev->hard_mtu - net->hard_header_len;
dev_warn(&intf->dev,
"dev can't take %u byte packets (max %u), "
"adjusting MTU to %u\n",
- dev->hard_mtu, tmp, net->mtu);
+ dev->hard_mtu, tmp, tmp - net->hard_header_len);
+ dev->hard_mtu = tmp;
+ net->mtu = dev->hard_mtu - net->hard_header_len;
}
/* REVISIT: peripheral "alignment" request is ignored ... */
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 8d009760277c..05630f2f6930 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -22,7 +22,6 @@
#include <linux/ethtool.h>
#include <linux/module.h>
#include <linux/virtio.h>
-#include <linux/virtio_ids.h>
#include <linux/virtio_net.h>
#include <linux/scatterlist.h>
#include <linux/if_vlan.h>
@@ -454,7 +453,7 @@ static unsigned int free_old_xmit_skbs(struct virtnet_info *vi)
vi->dev->stats.tx_bytes += skb->len;
vi->dev->stats.tx_packets++;
tot_sgs += skb_vnet_hdr(skb)->num_sg;
- kfree_skb(skb);
+ dev_kfree_skb_any(skb);
}
return tot_sgs;
}
@@ -517,8 +516,7 @@ again:
/* Free up any pending old buffers before queueing new ones. */
free_old_xmit_skbs(vi);
- /* Put new one in send queue and do transmit */
- __skb_queue_head(&vi->send, skb);
+ /* Try to transmit */
capacity = xmit_skb(vi, skb);
/* This can happen with OOM and indirect buffers. */
@@ -532,8 +530,17 @@ again:
}
return NETDEV_TX_BUSY;
}
-
vi->svq->vq_ops->kick(vi->svq);
+
+ /*
+ * Put new one in send queue. You'd expect we'd need this before
+ * xmit_skb calls add_buf(), since the callback can be triggered
+ * immediately after that. But since the callback just triggers
+ * another call back here, normal network xmit locking prevents the
+ * race.
+ */
+ __skb_queue_head(&vi->send, skb);
+
/* Don't wait up for transmitted skbs to be freed. */
skb_orphan(skb);
nf_reset(skb);
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c
index 6a16f76f277e..004353a46af0 100644
--- a/drivers/net/vmxnet3/vmxnet3_drv.c
+++ b/drivers/net/vmxnet3/vmxnet3_drv.c
@@ -481,7 +481,8 @@ vmxnet3_rq_alloc_rx_buf(struct vmxnet3_rx_queue *rq, u32 ring_idx,
}
rq->uncommitted[ring_idx] += num_allocated;
- dprintk(KERN_ERR "alloc_rx_buf: %d allocated, next2fill %u, next2comp "
+ dev_dbg(&adapter->netdev->dev,
+ "alloc_rx_buf: %d allocated, next2fill %u, next2comp "
"%u, uncommited %u\n", num_allocated, ring->next2fill,
ring->next2comp, rq->uncommitted[ring_idx]);
@@ -539,7 +540,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
tbi = tq->buf_info + tq->tx_ring.next2fill;
tbi->map_type = VMXNET3_MAP_NONE;
- dprintk(KERN_ERR "txd[%u]: 0x%Lx 0x%x 0x%x\n",
+ dev_dbg(&adapter->netdev->dev,
+ "txd[%u]: 0x%Lx 0x%x 0x%x\n",
tq->tx_ring.next2fill, ctx->sop_txd->txd.addr,
ctx->sop_txd->dword[2], ctx->sop_txd->dword[3]);
vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
@@ -572,7 +574,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
gdesc->dword[2] = dw2 | buf_size;
gdesc->dword[3] = 0;
- dprintk(KERN_ERR "txd[%u]: 0x%Lx 0x%x 0x%x\n",
+ dev_dbg(&adapter->netdev->dev,
+ "txd[%u]: 0x%Lx 0x%x 0x%x\n",
tq->tx_ring.next2fill, gdesc->txd.addr,
gdesc->dword[2], gdesc->dword[3]);
vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
@@ -600,7 +603,8 @@ vmxnet3_map_pkt(struct sk_buff *skb, struct vmxnet3_tx_ctx *ctx,
gdesc->dword[2] = dw2 | frag->size;
gdesc->dword[3] = 0;
- dprintk(KERN_ERR "txd[%u]: 0x%llu %u %u\n",
+ dev_dbg(&adapter->netdev->dev,
+ "txd[%u]: 0x%llu %u %u\n",
tq->tx_ring.next2fill, gdesc->txd.addr,
gdesc->dword[2], gdesc->dword[3]);
vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring);
@@ -697,7 +701,8 @@ vmxnet3_parse_and_copy_hdr(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
tdd = tq->data_ring.base + tq->tx_ring.next2fill;
memcpy(tdd->data, skb->data, ctx->copy_size);
- dprintk(KERN_ERR "copy %u bytes to dataRing[%u]\n",
+ dev_dbg(&adapter->netdev->dev,
+ "copy %u bytes to dataRing[%u]\n",
ctx->copy_size, tq->tx_ring.next2fill);
return 1;
@@ -808,7 +813,8 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
if (count > vmxnet3_cmd_ring_desc_avail(&tq->tx_ring)) {
tq->stats.tx_ring_full++;
- dprintk(KERN_ERR "tx queue stopped on %s, next2comp %u"
+ dev_dbg(&adapter->netdev->dev,
+ "tx queue stopped on %s, next2comp %u"
" next2fill %u\n", adapter->netdev->name,
tq->tx_ring.next2comp, tq->tx_ring.next2fill);
@@ -853,7 +859,8 @@ vmxnet3_tq_xmit(struct sk_buff *skb, struct vmxnet3_tx_queue *tq,
/* finally flips the GEN bit of the SOP desc */
gdesc->dword[2] ^= VMXNET3_TXD_GEN;
- dprintk(KERN_ERR "txd[%u]: SOP 0x%Lx 0x%x 0x%x\n",
+ dev_dbg(&adapter->netdev->dev,
+ "txd[%u]: SOP 0x%Lx 0x%x 0x%x\n",
(u32)((union Vmxnet3_GenericDesc *)ctx.sop_txd -
tq->tx_ring.base), gdesc->txd.addr, gdesc->dword[2],
gdesc->dword[3]);
@@ -990,7 +997,8 @@ vmxnet3_rq_rx_complete(struct vmxnet3_rx_queue *rq,
if (unlikely(rcd->len == 0)) {
/* Pretend the rx buffer is skipped. */
BUG_ON(!(rcd->sop && rcd->eop));
- dprintk(KERN_ERR "rxRing[%u][%u] 0 length\n",
+ dev_dbg(&adapter->netdev->dev,
+ "rxRing[%u][%u] 0 length\n",
ring_idx, idx);
goto rcd_done;
}
@@ -1683,7 +1691,8 @@ vmxnet3_activate_dev(struct vmxnet3_adapter *adapter)
int err;
u32 ret;
- dprintk(KERN_ERR "%s: skb_buf_size %d, rx_buf_per_pkt %d, ring sizes"
+ dev_dbg(&adapter->netdev->dev,
+ "%s: skb_buf_size %d, rx_buf_per_pkt %d, ring sizes"
" %u %u %u\n", adapter->netdev->name, adapter->skb_buf_size,
adapter->rx_buf_per_pkt, adapter->tx_queue.tx_ring.size,
adapter->rx_queue.rx_ring[0].size,
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h
index 6bb91576e999..3c0d70d58111 100644
--- a/drivers/net/vmxnet3/vmxnet3_int.h
+++ b/drivers/net/vmxnet3/vmxnet3_int.h
@@ -30,6 +30,7 @@
#include <linux/types.h>
#include <linux/ethtool.h>
#include <linux/delay.h>
+#include <linux/device.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include <linux/ethtool.h>
@@ -59,7 +60,6 @@
#include <linux/if_vlan.h>
#include <linux/if_arp.h>
#include <linux/inetdevice.h>
-#include <linux/dst.h>
#include "vmxnet3_defs.h"
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 7116a1aa20ce..abf896a7390e 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4790,9 +4790,8 @@ static int proc_stats_rid_open( struct inode *inode,
static int get_dec_u16( char *buffer, int *start, int limit ) {
u16 value;
int valid = 0;
- for( value = 0; buffer[*start] >= '0' &&
- buffer[*start] <= '9' &&
- *start < limit; (*start)++ ) {
+ for (value = 0; *start < limit && buffer[*start] >= '0' &&
+ buffer[*start] <= '9'; (*start)++) {
valid = 1;
value *= 10;
value += buffer[*start] - '0';
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 16a271787b85..1895d63aad0a 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -679,7 +679,7 @@ static u8 ath_rc_get_highest_rix(struct ath_softc *sc,
return rate;
if (rate_table->info[rate].valid_single_stream &&
- !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG));
+ !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG))
return rate;
/* This should not happen */
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 8701034569fa..de4e804bedf0 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1157,8 +1157,9 @@ struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot)
}
static int dma_tx_fragment(struct b43_dmaring *ring,
- struct sk_buff *skb)
+ struct sk_buff **in_skb)
{
+ struct sk_buff *skb = *in_skb;
const struct b43_dma_ops *ops = ring->ops;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
u8 *header;
@@ -1224,8 +1225,14 @@ static int dma_tx_fragment(struct b43_dmaring *ring,
}
memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len);
+ memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb));
+ bounce_skb->dev = skb->dev;
+ skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb));
+ info = IEEE80211_SKB_CB(bounce_skb);
+
dev_kfree_skb_any(skb);
skb = bounce_skb;
+ *in_skb = bounce_skb;
meta->skb = skb;
meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1);
if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) {
@@ -1355,7 +1362,11 @@ int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb)
* static, so we don't need to store it per frame. */
ring->queue_prio = skb_get_queue_mapping(skb);
- err = dma_tx_fragment(ring, skb);
+ /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing
+ * into the skb data or cb now. */
+ hdr = NULL;
+ info = NULL;
+ err = dma_tx_fragment(ring, &skb);
if (unlikely(err == -ENOKEY)) {
/* Drop this packet, as we don't have the encryption key
* anymore and must not transmit it unencrypted. */
diff --git a/drivers/net/wireless/b43/leds.h b/drivers/net/wireless/b43/leds.h
index 4c56187810fc..32b66d53cdac 100644
--- a/drivers/net/wireless/b43/leds.h
+++ b/drivers/net/wireless/b43/leds.h
@@ -1,6 +1,7 @@
#ifndef B43_LEDS_H_
#define B43_LEDS_H_
+struct b43_wl;
struct b43_wldev;
#ifdef CONFIG_B43_LEDS
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index df6b26a0c05e..86f35827f008 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -4501,7 +4501,6 @@ static void b43_op_stop(struct ieee80211_hw *hw)
cancel_work_sync(&(wl->beacon_update_trigger));
- wiphy_rfkill_stop_polling(hw->wiphy);
mutex_lock(&wl->mutex);
if (b43_status(dev) >= B43_STAT_STARTED) {
dev = b43_wireless_core_stop(dev);
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index 7a3218c5ba7d..ffdce6f3c909 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -33,7 +33,8 @@ bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
& B43_MMIO_RADIO_HWENABLED_HI_MASK))
return 1;
} else {
- if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
+ if (b43_status(dev) >= B43_STAT_STARTED &&
+ b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
& B43_MMIO_RADIO_HWENABLED_LO_MASK)
return 1;
}
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 240cff1e6979..a741d37fd96f 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -6325,8 +6325,10 @@ static int ipw2100_pci_init_one(struct pci_dev *pci_dev,
fail:
if (dev) {
- if (registered)
+ if (registered) {
+ unregister_ieee80211(priv->ieee);
unregister_netdev(dev);
+ }
ipw2100_hw_stop_adapter(priv);
@@ -6383,6 +6385,7 @@ static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev)
/* Unregister the device first - this results in close()
* being called if the device is open. If we free storage
* first, then close() will crash. */
+ unregister_ieee80211(priv->ieee);
unregister_netdev(dev);
/* ipw2100_down will ensure that there is no more pending work
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 827824d45de9..9b0f2c0646e0 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -11822,6 +11822,7 @@ static int __devinit ipw_pci_probe(struct pci_dev *pdev,
if (err) {
IPW_ERROR("Failed to register promiscuous network "
"device (error %d).\n", err);
+ unregister_ieee80211(priv->ieee);
unregister_netdev(priv->net_dev);
goto out_remove_sysfs;
}
@@ -11872,6 +11873,7 @@ static void __devexit ipw_pci_remove(struct pci_dev *pdev)
mutex_unlock(&priv->mutex);
+ unregister_ieee80211(priv->ieee);
unregister_netdev(priv->net_dev);
if (priv->rxq) {
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h
index bf45391172f3..f42ade6c2d3e 100644
--- a/drivers/net/wireless/ipw2x00/libipw.h
+++ b/drivers/net/wireless/ipw2x00/libipw.h
@@ -1020,6 +1020,7 @@ static inline int libipw_is_cck_rate(u8 rate)
/* ieee80211.c */
extern void free_ieee80211(struct net_device *dev, int monitor);
extern struct net_device *alloc_ieee80211(int sizeof_priv, int monitor);
+extern void unregister_ieee80211(struct libipw_device *ieee);
extern int libipw_change_mtu(struct net_device *dev, int new_mtu);
extern void libipw_networks_age(struct libipw_device *ieee,
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c
index a0e9f6aed7da..be5b809ec97a 100644
--- a/drivers/net/wireless/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/ipw2x00/libipw_module.c
@@ -235,16 +235,19 @@ void free_ieee80211(struct net_device *dev, int monitor)
libipw_networks_free(ieee);
/* free cfg80211 resources */
- if (!monitor) {
- wiphy_unregister(ieee->wdev.wiphy);
- kfree(ieee->a_band.channels);
- kfree(ieee->bg_band.channels);
+ if (!monitor)
wiphy_free(ieee->wdev.wiphy);
- }
free_netdev(dev);
}
+void unregister_ieee80211(struct libipw_device *ieee)
+{
+ wiphy_unregister(ieee->wdev.wiphy);
+ kfree(ieee->a_band.channels);
+ kfree(ieee->bg_band.channels);
+}
+
#ifdef CONFIG_LIBIPW_DEBUG
static int debug = 0;
@@ -330,3 +333,4 @@ module_init(libipw_init);
EXPORT_SYMBOL(alloc_ieee80211);
EXPORT_SYMBOL(free_ieee80211);
+EXPORT_SYMBOL(unregister_ieee80211);
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index cb8be8d7abc1..5b3672c4d0cc 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -134,7 +134,7 @@ static void spu_transaction_finish(struct if_spi_card *card)
static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
{
int err = 0;
- u16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK);
+ __le16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK);
struct spi_message m;
struct spi_transfer reg_trans;
struct spi_transfer data_trans;
@@ -166,7 +166,7 @@ static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len)
static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val)
{
- u16 buff;
+ __le16 buff;
buff = cpu_to_le16(val);
return spu_write(card, reg, (u8 *)&buff, sizeof(u16));
@@ -188,7 +188,7 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
{
unsigned int delay;
int err = 0;
- u16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK);
+ __le16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK);
struct spi_message m;
struct spi_transfer reg_trans;
struct spi_transfer dummy_trans;
@@ -235,7 +235,7 @@ static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len)
/* Read 16 bits from an SPI register */
static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
{
- u16 buf;
+ __le16 buf;
int ret;
ret = spu_read(card, reg, (u8 *)&buf, sizeof(buf));
@@ -248,7 +248,7 @@ static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val)
* The low 16 bits are read first. */
static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val)
{
- u32 buf;
+ __le32 buf;
int err;
err = spu_read(card, reg, (u8 *)&buf, sizeof(buf));
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index 92bc8c5f1ca2..3fac4efa5ac8 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -508,7 +508,7 @@ static int __if_usb_submit_rx_urb(struct if_usb_card *cardp,
/* Fill the receive configuration URB and initialise the Rx call back */
usb_fill_bulk_urb(cardp->rx_urb, cardp->udev,
usb_rcvbulkpipe(cardp->udev, cardp->ep_in),
- (void *) (skb->tail + (size_t) IPFIELD_ALIGN_OFFSET),
+ skb->data + IPFIELD_ALIGN_OFFSET,
MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn,
cardp);
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 88cd58eb3b9f..1c88c2ea59aa 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -2879,7 +2879,7 @@ static int write_essid(struct file *file, const char __user *buffer,
unsigned long count, void *data)
{
static char proc_essid[33];
- int len = count;
+ unsigned int len = count;
if (len > 32)
len = 32;
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index a084077a1c61..9fe770f7d7bb 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -1994,7 +1994,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size);
rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
- (skbdesc->entry->entry_idx + 1) : 0xff);
+ txdesc->key_idx : 0xff);
rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT,
skb->len - txdesc->l2pad);
rt2x00_set_field32(&word, TXWI_W1_PACKETID,
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index b8f5ee33445e..14e7bb210075 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2389,10 +2389,13 @@ static struct usb_device_id rt73usb_device_table[] = {
{ USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) },
/* MSI */
+ { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) },
+ /* Ovislink */
+ { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) },
/* Ralink */
{ USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) },
@@ -2420,6 +2423,8 @@ static struct usb_device_id rt73usb_device_table[] = {
/* Planex */
{ USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) },
{ USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) },
+ /* WideTell */
+ { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) },
/* Zcom */
{ USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) },
/* ZyXEL */
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index bacaa536fd51..4b22ba568b19 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -97,6 +97,12 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
}
EXPORT_SYMBOL(of_mdiobus_register);
+/* Helper function for of_phy_find_device */
+static int of_phy_match(struct device *dev, void *phy_np)
+{
+ return dev_archdata_get_node(&dev->archdata) == phy_np;
+}
+
/**
* of_phy_find_device - Give a PHY node, find the phy_device
* @phy_np: Pointer to the phy's device tree node
@@ -106,15 +112,10 @@ EXPORT_SYMBOL(of_mdiobus_register);
struct phy_device *of_phy_find_device(struct device_node *phy_np)
{
struct device *d;
- int match(struct device *dev, void *phy_np)
- {
- return dev_archdata_get_node(&dev->archdata) == phy_np;
- }
-
if (!phy_np)
return NULL;
- d = bus_find_device(&mdio_bus_type, NULL, phy_np, match);
+ d = bus_find_device(&mdio_bus_type, NULL, phy_np, of_phy_match);
return d ? to_phy_device(d) : NULL;
}
EXPORT_SYMBOL(of_phy_find_device);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index a790b1771f9f..245d2cdb4765 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -1009,7 +1009,7 @@ DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82454NX,
static void __devinit quirk_amd_ide_mode(struct pci_dev *pdev)
{
- /* set SBX00 SATA in IDE mode to AHCI mode */
+ /* set SBX00/Hudson-2 SATA in IDE mode to AHCI mode */
u8 tmp;
pci_read_config_byte(pdev, PCI_CLASS_DEVICE, &tmp);
@@ -1028,8 +1028,8 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP600_SATA, quirk_amd_ide_mode);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_amd_ide_mode);
DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP700_SATA, quirk_amd_ide_mode);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SB900_SATA_IDE, quirk_amd_ide_mode);
-DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SB900_SATA_IDE, quirk_amd_ide_mode);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode);
+DECLARE_PCI_FIXUP_RESUME_EARLY(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_HUDSON2_SATA_IDE, quirk_amd_ide_mode);
/*
* Serverworks CSB5 IDE does not fully support native mode
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
index 0959430534b2..cb1a027eb552 100644
--- a/drivers/pci/setup-bus.c
+++ b/drivers/pci/setup-bus.c
@@ -299,17 +299,8 @@ static struct resource *find_free_bus_resource(struct pci_bus *bus, unsigned lon
r = bus->resource[i];
if (r == &ioport_resource || r == &iomem_resource)
continue;
- if (r && (r->flags & type_mask) == type) {
- if (!r->parent)
- return r;
- /*
- * if there is no child under that, we should release
- * and use it. don't need to reset it, pbus_size_* will
- * set it again
- */
- if (!r->child && !release_resource(r))
- return r;
- }
+ if (r && (r->flags & type_mask) == type && !r->parent)
+ return r;
}
return NULL;
}
diff --git a/drivers/pcmcia/cistpl.c b/drivers/pcmcia/cistpl.c
index 4a110b7b2673..6c4a4fc83630 100644
--- a/drivers/pcmcia/cistpl.c
+++ b/drivers/pcmcia/cistpl.c
@@ -1463,7 +1463,9 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function, cisdata_t
return -ENOMEM;
}
tuple.DesiredTuple = code;
- tuple.Attributes = TUPLE_RETURN_COMMON;
+ tuple.Attributes = 0;
+ if (function == BIND_FN_ALL)
+ tuple.Attributes = TUPLE_RETURN_COMMON;
ret = pccard_get_first_tuple(s, function, &tuple);
if (ret != 0)
goto done;
@@ -1490,7 +1492,7 @@ EXPORT_SYMBOL(pccard_read_tuple);
======================================================================*/
-int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned int *info)
+int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *info)
{
tuple_t *tuple;
cisparse_t *p;
@@ -1515,30 +1517,30 @@ int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function, unsigned
count = reserved = 0;
tuple->DesiredTuple = RETURN_FIRST_TUPLE;
tuple->Attributes = TUPLE_RETURN_COMMON;
- ret = pccard_get_first_tuple(s, function, tuple);
+ ret = pccard_get_first_tuple(s, BIND_FN_ALL, tuple);
if (ret != 0)
goto done;
/* First tuple should be DEVICE; we should really have either that
or a CFTABLE_ENTRY of some sort */
if ((tuple->TupleCode == CISTPL_DEVICE) ||
- (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY, p) == 0) ||
- (pccard_read_tuple(s, function, CISTPL_CFTABLE_ENTRY_CB, p) == 0))
+ (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY, p) == 0) ||
+ (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_CFTABLE_ENTRY_CB, p) == 0))
dev_ok++;
/* All cards should have a MANFID tuple, and/or a VERS_1 or VERS_2
tuple, for card identification. Certain old D-Link and Linksys
cards have only a broken VERS_2 tuple; hence the bogus test. */
- if ((pccard_read_tuple(s, function, CISTPL_MANFID, p) == 0) ||
- (pccard_read_tuple(s, function, CISTPL_VERS_1, p) == 0) ||
- (pccard_read_tuple(s, function, CISTPL_VERS_2, p) != -ENOSPC))
+ if ((pccard_read_tuple(s, BIND_FN_ALL, CISTPL_MANFID, p) == 0) ||
+ (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_1, p) == 0) ||
+ (pccard_read_tuple(s, BIND_FN_ALL, CISTPL_VERS_2, p) != -ENOSPC))
ident_ok++;
if (!dev_ok && !ident_ok)
goto done;
for (count = 1; count < MAX_TUPLES; count++) {
- ret = pccard_get_next_tuple(s, function, tuple);
+ ret = pccard_get_next_tuple(s, BIND_FN_ALL, tuple);
if (ret != 0)
break;
if (((tuple->TupleCode > 0x23) && (tuple->TupleCode < 0x40)) ||
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c
index 934d4bee39a0..698d75cda084 100644
--- a/drivers/pcmcia/cs.c
+++ b/drivers/pcmcia/cs.c
@@ -98,10 +98,13 @@ EXPORT_SYMBOL(pcmcia_socket_list_rwsem);
* These functions check for the appropriate struct pcmcia_soket arrays,
* and pass them to the low-level functions pcmcia_{suspend,resume}_socket
*/
+static int socket_early_resume(struct pcmcia_socket *skt);
+static int socket_late_resume(struct pcmcia_socket *skt);
static int socket_resume(struct pcmcia_socket *skt);
static int socket_suspend(struct pcmcia_socket *skt);
-int pcmcia_socket_dev_suspend(struct device *dev)
+static void pcmcia_socket_dev_run(struct device *dev,
+ int (*cb)(struct pcmcia_socket *))
{
struct pcmcia_socket *socket;
@@ -110,29 +113,34 @@ int pcmcia_socket_dev_suspend(struct device *dev)
if (socket->dev.parent != dev)
continue;
mutex_lock(&socket->skt_mutex);
- socket_suspend(socket);
+ cb(socket);
mutex_unlock(&socket->skt_mutex);
}
up_read(&pcmcia_socket_list_rwsem);
+}
+int pcmcia_socket_dev_suspend(struct device *dev)
+{
+ pcmcia_socket_dev_run(dev, socket_suspend);
return 0;
}
EXPORT_SYMBOL(pcmcia_socket_dev_suspend);
-int pcmcia_socket_dev_resume(struct device *dev)
+void pcmcia_socket_dev_early_resume(struct device *dev)
{
- struct pcmcia_socket *socket;
+ pcmcia_socket_dev_run(dev, socket_early_resume);
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_early_resume);
- down_read(&pcmcia_socket_list_rwsem);
- list_for_each_entry(socket, &pcmcia_socket_list, socket_list) {
- if (socket->dev.parent != dev)
- continue;
- mutex_lock(&socket->skt_mutex);
- socket_resume(socket);
- mutex_unlock(&socket->skt_mutex);
- }
- up_read(&pcmcia_socket_list_rwsem);
+void pcmcia_socket_dev_late_resume(struct device *dev)
+{
+ pcmcia_socket_dev_run(dev, socket_late_resume);
+}
+EXPORT_SYMBOL(pcmcia_socket_dev_late_resume);
+int pcmcia_socket_dev_resume(struct device *dev)
+{
+ pcmcia_socket_dev_run(dev, socket_resume);
return 0;
}
EXPORT_SYMBOL(pcmcia_socket_dev_resume);
@@ -546,29 +554,24 @@ static int socket_suspend(struct pcmcia_socket *skt)
return 0;
}
-/*
- * Resume a socket. If a card is present, verify its CIS against
- * our cached copy. If they are different, the card has been
- * replaced, and we need to tell the drivers.
- */
-static int socket_resume(struct pcmcia_socket *skt)
+static int socket_early_resume(struct pcmcia_socket *skt)
{
- int ret;
-
- if (!(skt->state & SOCKET_SUSPEND))
- return -EBUSY;
-
skt->socket = dead_socket;
skt->ops->init(skt);
skt->ops->set_socket(skt, &skt->socket);
+ if (skt->state & SOCKET_PRESENT)
+ skt->resume_status = socket_setup(skt, resume_delay);
+ return 0;
+}
+static int socket_late_resume(struct pcmcia_socket *skt)
+{
if (!(skt->state & SOCKET_PRESENT)) {
skt->state &= ~SOCKET_SUSPEND;
return socket_insert(skt);
}
- ret = socket_setup(skt, resume_delay);
- if (ret == 0) {
+ if (skt->resume_status == 0) {
/*
* FIXME: need a better check here for cardbus cards.
*/
@@ -596,6 +599,20 @@ static int socket_resume(struct pcmcia_socket *skt)
return 0;
}
+/*
+ * Resume a socket. If a card is present, verify its CIS against
+ * our cached copy. If they are different, the card has been
+ * replaced, and we need to tell the drivers.
+ */
+static int socket_resume(struct pcmcia_socket *skt)
+{
+ if (!(skt->state & SOCKET_SUSPEND))
+ return -EBUSY;
+
+ socket_early_resume(skt);
+ return socket_late_resume(skt);
+}
+
static void socket_remove(struct pcmcia_socket *skt)
{
dev_printk(KERN_NOTICE, &skt->dev,
diff --git a/drivers/pcmcia/cs_internal.h b/drivers/pcmcia/cs_internal.h
index 79615e6d540b..1f4098f1354d 100644
--- a/drivers/pcmcia/cs_internal.h
+++ b/drivers/pcmcia/cs_internal.h
@@ -197,8 +197,7 @@ int pccard_read_tuple(struct pcmcia_socket *s, unsigned int function,
cisdata_t code, void *parse);
int pcmcia_replace_cis(struct pcmcia_socket *s,
const u8 *data, const size_t len);
-int pccard_validate_cis(struct pcmcia_socket *s, unsigned int function,
- unsigned int *count);
+int pccard_validate_cis(struct pcmcia_socket *s, unsigned int *count);
/* rsrc_mgr.c */
int pcmcia_validate_mem(struct pcmcia_socket *s);
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c
index 9f300d3cb125..f5b7079f13d3 100644
--- a/drivers/pcmcia/ds.c
+++ b/drivers/pcmcia/ds.c
@@ -547,7 +547,7 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
if (!vers1)
return -ENOMEM;
- if (!pccard_read_tuple(p_dev->socket, p_dev->func,
+ if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL,
CISTPL_MANFID, &manf_id)) {
p_dev->manf_id = manf_id.manf;
p_dev->card_id = manf_id.card;
@@ -581,9 +581,9 @@ static int pcmcia_device_query(struct pcmcia_device *p_dev)
kfree(devgeo);
}
- if (!pccard_read_tuple(p_dev->socket, p_dev->func, CISTPL_VERS_1,
+ if (!pccard_read_tuple(p_dev->socket, BIND_FN_ALL, CISTPL_VERS_1,
vers1)) {
- for (i=0; i < vers1->ns; i++) {
+ for (i = 0; i < min_t(unsigned int, 4, vers1->ns); i++) {
char *tmp;
unsigned int length;
@@ -733,7 +733,7 @@ static int pcmcia_card_add(struct pcmcia_socket *s)
return -EAGAIN; /* try again, but later... */
}
- ret = pccard_validate_cis(s, BIND_FN_ALL, &no_chains);
+ ret = pccard_validate_cis(s, &no_chains);
if (ret || !no_chains) {
ds_dev_dbg(0, &s->dev, "invalid CIS or invalid resources\n");
return -ENODEV;
diff --git a/drivers/pcmcia/i82365.c b/drivers/pcmcia/i82365.c
index b906abe26ad0..a4aacb830b80 100644
--- a/drivers/pcmcia/i82365.c
+++ b/drivers/pcmcia/i82365.c
@@ -1053,8 +1053,8 @@ static int i365_set_io_map(u_short sock, struct pccard_io_map *io)
u_char map, ioctl;
debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
- "%#x-%#x)\n", sock, io->map, io->flags,
- io->speed, io->start, io->stop);
+ "%#llx-%#llx)\n", sock, io->map, io->flags, io->speed,
+ (unsigned long long)io->start, (unsigned long long)io->stop);
map = io->map;
if ((map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
(io->stop < io->start)) return -EINVAL;
diff --git a/drivers/pcmcia/m32r_cfc.c b/drivers/pcmcia/m32r_cfc.c
index d1d89c4491ad..7dfbee1dcd76 100644
--- a/drivers/pcmcia/m32r_cfc.c
+++ b/drivers/pcmcia/m32r_cfc.c
@@ -537,8 +537,9 @@ static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io)
u_char map;
debug(3, "m32r_cfc: SetIOMap(%d, %d, %#2.2x, %d ns, "
- "%#lx-%#lx)\n", sock, io->map, io->flags,
- io->speed, io->start, io->stop);
+ "%#llx-%#llx)\n", sock, io->map, io->flags,
+ io->speed, (unsigned long long)io->start,
+ (unsigned long long)io->stop);
map = io->map;
return 0;
@@ -554,8 +555,9 @@ static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem)
pcc_socket_t *t = &socket[sock];
debug(3, "m32r_cfc: SetMemMap(%d, %d, %#2.2x, %d ns, "
- "%#lx, %#x)\n", sock, map, mem->flags,
- mem->speed, mem->static_start, mem->card_start);
+ "%#llx, %#x)\n", sock, map, mem->flags,
+ mem->speed, (unsigned long long)mem->static_start,
+ mem->card_start);
/*
* sanity check
diff --git a/drivers/pcmcia/m32r_pcc.c b/drivers/pcmcia/m32r_pcc.c
index a0655839c8d3..c6524f99ccc3 100644
--- a/drivers/pcmcia/m32r_pcc.c
+++ b/drivers/pcmcia/m32r_pcc.c
@@ -492,8 +492,9 @@ static int _pcc_set_io_map(u_short sock, struct pccard_io_map *io)
u_char map;
debug(3, "m32r-pcc: SetIOMap(%d, %d, %#2.2x, %d ns, "
- "%#x-%#x)\n", sock, io->map, io->flags,
- io->speed, io->start, io->stop);
+ "%#llx-%#llx)\n", sock, io->map, io->flags,
+ io->speed, (unsigned long long)io->start,
+ (unsigned long long)io->stop);
map = io->map;
return 0;
@@ -515,8 +516,9 @@ static int _pcc_set_mem_map(u_short sock, struct pccard_mem_map *mem)
#endif
debug(3, "m32r-pcc: SetMemMap(%d, %d, %#2.2x, %d ns, "
- "%#lx, %#x)\n", sock, map, mem->flags,
- mem->speed, mem->static_start, mem->card_start);
+ "%#llx, %#x)\n", sock, map, mem->flags,
+ mem->speed, (unsigned long long)mem->static_start,
+ mem->card_start);
/*
* sanity check
diff --git a/drivers/pcmcia/m8xx_pcmcia.c b/drivers/pcmcia/m8xx_pcmcia.c
index c69f2c4fe520..403559ba49dd 100644
--- a/drivers/pcmcia/m8xx_pcmcia.c
+++ b/drivers/pcmcia/m8xx_pcmcia.c
@@ -975,8 +975,9 @@ static int m8xx_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
#define M8XX_BASE (PCMCIA_IO_WIN_BASE + io->start)
dprintk("SetIOMap(%d, %d, %#2.2x, %d ns, "
- "%#4.4x-%#4.4x)\n", lsock, io->map, io->flags,
- io->speed, io->start, io->stop);
+ "%#4.4llx-%#4.4llx)\n", lsock, io->map, io->flags,
+ io->speed, (unsigned long long)io->start,
+ (unsigned long long)io->stop);
if ((io->map >= PCMCIA_IO_WIN_NO) || (io->start > 0xffff)
|| (io->stop > 0xffff) || (io->stop < io->start))
@@ -1055,8 +1056,9 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock,
pcmconf8xx_t *pcmcia = s->pcmcia;
dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
- "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
- mem->speed, mem->static_start, mem->card_start);
+ "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
+ mem->speed, (unsigned long long)mem->static_start,
+ mem->card_start);
if ((mem->map >= PCMCIA_MEM_WIN_NO)
// || ((mem->s) >= PCMCIA_MEM_WIN_SIZE)
@@ -1107,8 +1109,9 @@ static int m8xx_set_mem_map(struct pcmcia_socket *sock,
}
dprintk("SetMemMap(%d, %d, %#2.2x, %d ns, "
- "%#5.5lx, %#5.5x)\n", lsock, mem->map, mem->flags,
- mem->speed, mem->static_start, mem->card_start);
+ "%#5.5llx, %#5.5x)\n", lsock, mem->map, mem->flags,
+ mem->speed, (unsigned long long)mem->static_start,
+ mem->card_start);
/* copy the struct and modify the copy */
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c
index 32c44040c1e8..30cf71d2ee23 100644
--- a/drivers/pcmcia/pcmcia_ioctl.c
+++ b/drivers/pcmcia/pcmcia_ioctl.c
@@ -881,7 +881,7 @@ static int ds_ioctl(struct inode * inode, struct file * file,
mutex_lock(&s->skt_mutex);
pcmcia_validate_mem(s);
mutex_unlock(&s->skt_mutex);
- ret = pccard_validate_cis(s, BIND_FN_ALL, &buf->cisinfo.Chains);
+ ret = pccard_validate_cis(s, &buf->cisinfo.Chains);
break;
case DS_SUSPEND_CARD:
ret = pcmcia_suspend_card(s);
diff --git a/drivers/pcmcia/pd6729.c b/drivers/pcmcia/pd6729.c
index 1c39d3438f20..70a33468bcd0 100644
--- a/drivers/pcmcia/pd6729.c
+++ b/drivers/pcmcia/pd6729.c
@@ -641,6 +641,12 @@ static int __devinit pd6729_pci_probe(struct pci_dev *dev,
if ((ret = pci_enable_device(dev)))
goto err_out_free_mem;
+ if (!pci_resource_start(dev, 0)) {
+ printk(KERN_INFO "pd6729: refusing to load the driver "
+ "as the io_base is 0.\n");
+ goto err_out_free_mem;
+ }
+
printk(KERN_INFO "pd6729: Cirrus PD6729 PCI to PCMCIA Bridge "
"at 0x%llx on irq %d\n",
(unsigned long long)pci_resource_start(dev, 0), dev->irq);
diff --git a/drivers/pcmcia/rsrc_nonstatic.c b/drivers/pcmcia/rsrc_nonstatic.c
index 9ca22c7aafb2..7039f3cf5b77 100644
--- a/drivers/pcmcia/rsrc_nonstatic.c
+++ b/drivers/pcmcia/rsrc_nonstatic.c
@@ -206,6 +206,7 @@ static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
/* First, what does a floating port look like? */
b = kzalloc(256, GFP_KERNEL);
if (!b) {
+ printk("\n");
dev_printk(KERN_ERR, &s->dev,
"do_io_probe: unable to kmalloc 256 bytes");
return;
@@ -275,7 +276,7 @@ static int readable(struct pcmcia_socket *s, struct resource *res,
s->cis_mem.res = res;
s->cis_virt = ioremap(res->start, s->map_size);
if (s->cis_virt) {
- ret = pccard_validate_cis(s, BIND_FN_ALL, count);
+ ret = pccard_validate_cis(s, count);
/* invalidate mapping and CIS cache */
iounmap(s->cis_virt);
s->cis_virt = NULL;
diff --git a/drivers/pcmcia/soc_common.c b/drivers/pcmcia/soc_common.c
index 163cf98e2386..ef7e9e58782b 100644
--- a/drivers/pcmcia/soc_common.c
+++ b/drivers/pcmcia/soc_common.c
@@ -336,8 +336,9 @@ soc_common_pcmcia_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *m
struct soc_pcmcia_socket *skt = to_soc_pcmcia_socket(sock);
unsigned short speed = map->speed;
- debug(skt, 2, "map %u speed %u start 0x%08x stop 0x%08x\n",
- map->map, map->speed, map->start, map->stop);
+ debug(skt, 2, "map %u speed %u start 0x%08llx stop 0x%08llx\n",
+ map->map, map->speed, (unsigned long long)map->start,
+ (unsigned long long)map->stop);
debug(skt, 2, "flags: %s%s%s%s%s%s%s%s\n",
(map->flags==0)?"<NONE>":"",
(map->flags&MAP_ACTIVE)?"ACTIVE ":"",
diff --git a/drivers/pcmcia/socket_sysfs.c b/drivers/pcmcia/socket_sysfs.c
index ff9a3bb3c88d..78d5aab542f7 100644
--- a/drivers/pcmcia/socket_sysfs.c
+++ b/drivers/pcmcia/socket_sysfs.c
@@ -300,7 +300,7 @@ static ssize_t pccard_show_cis(struct kobject *kobj,
if (!(s->state & SOCKET_PRESENT))
return -ENODEV;
- if (pccard_validate_cis(s, BIND_FN_ALL, &chains))
+ if (pccard_validate_cis(s, &chains))
return -EIO;
if (!chains)
return -ENODATA;
diff --git a/drivers/pcmcia/tcic.c b/drivers/pcmcia/tcic.c
index 582413fcb62f..6918849d511e 100644
--- a/drivers/pcmcia/tcic.c
+++ b/drivers/pcmcia/tcic.c
@@ -732,8 +732,8 @@ static int tcic_set_io_map(struct pcmcia_socket *sock, struct pccard_io_map *io)
u_short base, len, ioctl;
debug(1, "SetIOMap(%d, %d, %#2.2x, %d ns, "
- "%#x-%#x)\n", psock, io->map, io->flags,
- io->speed, io->start, io->stop);
+ "%#llx-%#llx)\n", psock, io->map, io->flags, io->speed,
+ (unsigned long long)io->start, (unsigned long long)io->stop);
if ((io->map > 1) || (io->start > 0xffff) || (io->stop > 0xffff) ||
(io->stop < io->start)) return -EINVAL;
tcic_setw(TCIC_ADDR+2, TCIC_ADR2_INDREG | (psock << TCIC_SS_SHFT));
diff --git a/drivers/pcmcia/yenta_socket.c b/drivers/pcmcia/yenta_socket.c
index abe0e44c6e9e..8be4cc447a17 100644
--- a/drivers/pcmcia/yenta_socket.c
+++ b/drivers/pcmcia/yenta_socket.c
@@ -1275,16 +1275,26 @@ static int yenta_dev_resume_noirq(struct device *dev)
if (socket->type && socket->type->restore_state)
socket->type->restore_state(socket);
- return pcmcia_socket_dev_resume(dev);
+ pcmcia_socket_dev_early_resume(dev);
+ return 0;
+}
+
+static int yenta_dev_resume(struct device *dev)
+{
+ pcmcia_socket_dev_late_resume(dev);
+ return 0;
}
static struct dev_pm_ops yenta_pm_ops = {
.suspend_noirq = yenta_dev_suspend_noirq,
.resume_noirq = yenta_dev_resume_noirq,
+ .resume = yenta_dev_resume,
.freeze_noirq = yenta_dev_suspend_noirq,
.thaw_noirq = yenta_dev_resume_noirq,
+ .thaw = yenta_dev_resume,
.poweroff_noirq = yenta_dev_suspend_noirq,
.restore_noirq = yenta_dev_resume_noirq,
+ .restore = yenta_dev_resume,
};
#define YENTA_PM_OPS (&yenta_pm_ops)
diff --git a/drivers/s390/char/sclp_async.c b/drivers/s390/char/sclp_async.c
index a4f68e5b9c96..b44462a6c6d3 100644
--- a/drivers/s390/char/sclp_async.c
+++ b/drivers/s390/char/sclp_async.c
@@ -26,7 +26,6 @@ static struct sclp_async_sccb *sccb;
static int sclp_async_send_wait(char *message);
static struct ctl_table_header *callhome_sysctl_header;
static DEFINE_SPINLOCK(sclp_async_lock);
-static char nodename[64];
#define SCLP_NORMAL_WRITE 0x00
struct async_evbuf {
@@ -52,9 +51,10 @@ static struct sclp_register sclp_async_register = {
static int call_home_on_panic(struct notifier_block *self,
unsigned long event, void *data)
{
- strncat(data, nodename, strlen(nodename));
- sclp_async_send_wait(data);
- return NOTIFY_DONE;
+ strncat(data, init_utsname()->nodename,
+ sizeof(init_utsname()->nodename));
+ sclp_async_send_wait(data);
+ return NOTIFY_DONE;
}
static struct notifier_block call_home_panic_nb = {
@@ -68,15 +68,14 @@ static int proc_handler_callhome(struct ctl_table *ctl, int write,
{
unsigned long val;
int len, rc;
- char buf[2];
+ char buf[3];
- if (!*count | (*ppos && !write)) {
+ if (!*count || (*ppos && !write)) {
*count = 0;
return 0;
}
if (!write) {
- len = sprintf(buf, "%d\n", callhome_enabled);
- buf[len] = '\0';
+ len = snprintf(buf, sizeof(buf), "%d\n", callhome_enabled);
rc = copy_to_user(buffer, buf, sizeof(buf));
if (rc != 0)
return -EFAULT;
@@ -171,39 +170,29 @@ static int __init sclp_async_init(void)
rc = sclp_register(&sclp_async_register);
if (rc)
return rc;
- callhome_sysctl_header = register_sysctl_table(kern_dir_table);
- if (!callhome_sysctl_header) {
- rc = -ENOMEM;
- goto out_sclp;
- }
- if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK)) {
- rc = -EOPNOTSUPP;
+ rc = -EOPNOTSUPP;
+ if (!(sclp_async_register.sclp_receive_mask & EVTYP_ASYNC_MASK))
goto out_sclp;
- }
rc = -ENOMEM;
+ callhome_sysctl_header = register_sysctl_table(kern_dir_table);
+ if (!callhome_sysctl_header)
+ goto out_sclp;
request = kzalloc(sizeof(struct sclp_req), GFP_KERNEL);
- if (!request)
- goto out_sys;
sccb = (struct sclp_async_sccb *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
- if (!sccb)
+ if (!request || !sccb)
goto out_mem;
- rc = atomic_notifier_chain_register(&panic_notifier_list,
- &call_home_panic_nb);
- if (rc)
- goto out_mem;
-
- strncpy(nodename, init_utsname()->nodename, 64);
- return 0;
-
+ rc = atomic_notifier_chain_register(&panic_notifier_list,
+ &call_home_panic_nb);
+ if (!rc)
+ goto out;
out_mem:
kfree(request);
free_page((unsigned long) sccb);
-out_sys:
unregister_sysctl_table(callhome_sysctl_header);
out_sclp:
sclp_unregister(&sclp_async_register);
+out:
return rc;
-
}
module_init(sclp_async_init);
diff --git a/drivers/s390/net/smsgiucv.c b/drivers/s390/net/smsgiucv.c
index 102000d1af6f..3012355f8304 100644
--- a/drivers/s390/net/smsgiucv.c
+++ b/drivers/s390/net/smsgiucv.c
@@ -158,7 +158,12 @@ static int smsg_pm_restore_thaw(struct device *dev)
smsg_path->flags = 0;
rc = iucv_path_connect(smsg_path, &smsg_handler, "*MSG ",
NULL, NULL, NULL);
- printk(KERN_ERR "iucv_path_connect returned with rc %i\n", rc);
+#ifdef CONFIG_PM_DEBUG
+ if (rc)
+ printk(KERN_ERR
+ "iucv_path_connect returned with rc %i\n", rc);
+#endif
+ cpcmd("SET SMSG IUCV", NULL, 0, NULL);
}
return 0;
}
diff --git a/drivers/s390/scsi/zfcp_aux.c b/drivers/s390/scsi/zfcp_aux.c
index 0f79f3af4f54..2889e5f2dfd3 100644
--- a/drivers/s390/scsi/zfcp_aux.c
+++ b/drivers/s390/scsi/zfcp_aux.c
@@ -128,12 +128,13 @@ out_ccwdev:
static void __init zfcp_init_device_setup(char *devstr)
{
char *token;
- char *str;
+ char *str, *str_saved;
char busid[ZFCP_BUS_ID_SIZE];
u64 wwpn, lun;
/* duplicate devstr and keep the original for sysfs presentation*/
- str = kmalloc(strlen(devstr) + 1, GFP_KERNEL);
+ str_saved = kmalloc(strlen(devstr) + 1, GFP_KERNEL);
+ str = str_saved;
if (!str)
return;
@@ -152,12 +153,12 @@ static void __init zfcp_init_device_setup(char *devstr)
if (!token || strict_strtoull(token, 0, (unsigned long long *) &lun))
goto err_out;
- kfree(str);
+ kfree(str_saved);
zfcp_init_device_configure(busid, wwpn, lun);
return;
- err_out:
- kfree(str);
+err_out:
+ kfree(str_saved);
pr_err("%s is not a valid SCSI device\n", devstr);
}
diff --git a/drivers/s390/scsi/zfcp_erp.c b/drivers/s390/scsi/zfcp_erp.c
index 73d366ba31e5..f73e2180f333 100644
--- a/drivers/s390/scsi/zfcp_erp.c
+++ b/drivers/s390/scsi/zfcp_erp.c
@@ -858,10 +858,7 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_PTP)
return zfcp_erp_open_ptp_port(act);
if (!port->d_id) {
- zfcp_port_get(port);
- if (!queue_work(adapter->work_queue,
- &port->gid_pn_work))
- zfcp_port_put(port);
+ zfcp_fc_trigger_did_lookup(port);
return ZFCP_ERP_EXIT;
}
return zfcp_erp_port_strategy_open_port(act);
@@ -869,12 +866,11 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
case ZFCP_ERP_STEP_PORT_OPENING:
/* D_ID might have changed during open */
if (p_status & ZFCP_STATUS_COMMON_OPEN) {
- if (port->d_id)
- return ZFCP_ERP_SUCCEEDED;
- else {
- act->step = ZFCP_ERP_STEP_PORT_CLOSING;
- return ZFCP_ERP_CONTINUES;
+ if (!port->d_id) {
+ zfcp_fc_trigger_did_lookup(port);
+ return ZFCP_ERP_EXIT;
}
+ return ZFCP_ERP_SUCCEEDED;
}
if (port->d_id && !(p_status & ZFCP_STATUS_COMMON_NOESC)) {
port->d_id = 0;
@@ -889,19 +885,21 @@ static int zfcp_erp_port_strategy_open_common(struct zfcp_erp_action *act)
static int zfcp_erp_port_strategy(struct zfcp_erp_action *erp_action)
{
struct zfcp_port *port = erp_action->port;
+ int p_status = atomic_read(&port->status);
- if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_NOESC)
+ if ((p_status & ZFCP_STATUS_COMMON_NOESC) &&
+ !(p_status & ZFCP_STATUS_COMMON_OPEN))
goto close_init_done;
switch (erp_action->step) {
case ZFCP_ERP_STEP_UNINITIALIZED:
zfcp_erp_port_strategy_clearstati(port);
- if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)
+ if (p_status & ZFCP_STATUS_COMMON_OPEN)
return zfcp_erp_port_strategy_close(erp_action);
break;
case ZFCP_ERP_STEP_PORT_CLOSING:
- if (atomic_read(&port->status) & ZFCP_STATUS_COMMON_OPEN)
+ if (p_status & ZFCP_STATUS_COMMON_OPEN)
return ZFCP_ERP_FAILED;
break;
}
diff --git a/drivers/s390/scsi/zfcp_ext.h b/drivers/s390/scsi/zfcp_ext.h
index 629edec70405..b3f28deb4505 100644
--- a/drivers/s390/scsi/zfcp_ext.h
+++ b/drivers/s390/scsi/zfcp_ext.h
@@ -96,6 +96,7 @@ extern int zfcp_fc_scan_ports(struct zfcp_adapter *);
extern void _zfcp_fc_scan_ports_later(struct work_struct *);
extern void zfcp_fc_incoming_els(struct zfcp_fsf_req *);
extern void zfcp_fc_port_did_lookup(struct work_struct *);
+extern void zfcp_fc_trigger_did_lookup(struct zfcp_port *);
extern void zfcp_fc_plogi_evaluate(struct zfcp_port *, struct fsf_plogi *);
extern void zfcp_fc_test_link(struct zfcp_port *);
extern void zfcp_fc_link_test_work(struct work_struct *);
diff --git a/drivers/s390/scsi/zfcp_fc.c b/drivers/s390/scsi/zfcp_fc.c
index 722f22de8753..df23bcead23d 100644
--- a/drivers/s390/scsi/zfcp_fc.c
+++ b/drivers/s390/scsi/zfcp_fc.c
@@ -361,6 +361,17 @@ out:
}
/**
+ * zfcp_fc_trigger_did_lookup - trigger the d_id lookup using a GID_PN request
+ * @port: The zfcp_port to lookup the d_id for.
+ */
+void zfcp_fc_trigger_did_lookup(struct zfcp_port *port)
+{
+ zfcp_port_get(port);
+ if (!queue_work(port->adapter->work_queue, &port->gid_pn_work))
+ zfcp_port_put(port);
+}
+
+/**
* zfcp_fc_plogi_evaluate - evaluate PLOGI playload
* @port: zfcp_port structure
* @plogi: plogi payload
diff --git a/drivers/s390/scsi/zfcp_fsf.c b/drivers/s390/scsi/zfcp_fsf.c
index 38a7e4a6b639..4e41baa0c141 100644
--- a/drivers/s390/scsi/zfcp_fsf.c
+++ b/drivers/s390/scsi/zfcp_fsf.c
@@ -1079,7 +1079,7 @@ static int zfcp_fsf_setup_ct_els(struct zfcp_fsf_req *req,
/* common settings for ct/gs and els requests */
req->qtcb->bottom.support.service_class = FSF_CLASS_3;
req->qtcb->bottom.support.timeout = 2 * R_A_TOV;
- zfcp_fsf_start_timer(req, 2 * R_A_TOV + 10);
+ zfcp_fsf_start_timer(req, (2 * R_A_TOV + 10) * HZ);
return 0;
}
@@ -1475,9 +1475,16 @@ static void zfcp_fsf_open_port_handler(struct zfcp_fsf_req *req)
plogi = (struct fsf_plogi *) req->qtcb->bottom.support.els;
if (req->qtcb->bottom.support.els1_length >=
FSF_PLOGI_MIN_LEN) {
- if (plogi->serv_param.wwpn != port->wwpn)
+ if (plogi->serv_param.wwpn != port->wwpn) {
port->d_id = 0;
- else {
+ dev_warn(&port->adapter->ccw_device->dev,
+ "A port opened with WWPN 0x%016Lx "
+ "returned data that identifies it as "
+ "WWPN 0x%016Lx\n",
+ (unsigned long long) port->wwpn,
+ (unsigned long long)
+ plogi->serv_param.wwpn);
+ } else {
port->wwnn = plogi->serv_param.wwnn;
zfcp_fc_plogi_evaluate(port, plogi);
}
diff --git a/drivers/s390/scsi/zfcp_sysfs.c b/drivers/s390/scsi/zfcp_sysfs.c
index 079a8cf518a3..d31000886ca8 100644
--- a/drivers/s390/scsi/zfcp_sysfs.c
+++ b/drivers/s390/scsi/zfcp_sysfs.c
@@ -224,6 +224,7 @@ static ssize_t zfcp_sysfs_unit_add_store(struct device *dev,
zfcp_erp_unit_reopen(unit, 0, "syuas_1", NULL);
zfcp_erp_wait(unit->port->adapter);
+ flush_work(&unit->scsi_work);
zfcp_unit_put(unit);
out:
mutex_unlock(&zfcp_data.config_mutex);
diff --git a/drivers/scsi/dpt_i2o.c b/drivers/scsi/dpt_i2o.c
index b6af63ca980b..496764349c41 100644
--- a/drivers/scsi/dpt_i2o.c
+++ b/drivers/scsi/dpt_i2o.c
@@ -1918,6 +1918,10 @@ static int adpt_i2o_passthru(adpt_hba* pHba, u32 __user *arg)
}
size = size>>16;
size *= 4;
+ if (size > MAX_MESSAGE_SIZE) {
+ rcode = -EINVAL;
+ goto cleanup;
+ }
/* Copy in the user's I2O command */
if (copy_from_user (msg, user_msg, size)) {
rcode = -EFAULT;
diff --git a/drivers/scsi/scsi_scan.c b/drivers/scsi/scsi_scan.c
index c44783801402..0547a7f44d42 100644
--- a/drivers/scsi/scsi_scan.c
+++ b/drivers/scsi/scsi_scan.c
@@ -317,6 +317,7 @@ static struct scsi_device *scsi_alloc_sdev(struct scsi_target *starget,
out_device_destroy:
scsi_device_set_state(sdev, SDEV_DEL);
transport_destroy_device(&sdev->sdev_gendev);
+ put_device(&sdev->sdev_dev);
put_device(&sdev->sdev_gendev);
out:
if (display_failure_msg)
@@ -957,6 +958,7 @@ static inline void scsi_destroy_sdev(struct scsi_device *sdev)
if (sdev->host->hostt->slave_destroy)
sdev->host->hostt->slave_destroy(sdev);
transport_destroy_device(&sdev->sdev_gendev);
+ put_device(&sdev->sdev_dev);
put_device(&sdev->sdev_gendev);
}
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index fde54537d715..5c7eb63a19d1 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -864,10 +864,6 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
goto clean_device;
}
- /* take a reference for the sdev_dev; this is
- * released by the sdev_class .release */
- get_device(&sdev->sdev_gendev);
-
/* create queue files, which may be writable, depending on the host */
if (sdev->host->hostt->change_queue_depth)
error = device_create_file(&sdev->sdev_gendev, &sdev_attr_queue_depth_rw);
@@ -917,6 +913,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev)
device_del(&sdev->sdev_gendev);
transport_destroy_device(&sdev->sdev_gendev);
+ put_device(&sdev->sdev_dev);
put_device(&sdev->sdev_gendev);
return error;
@@ -1065,7 +1062,7 @@ void scsi_sysfs_device_initialize(struct scsi_device *sdev)
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
device_initialize(&sdev->sdev_dev);
- sdev->sdev_dev.parent = &sdev->sdev_gendev;
+ sdev->sdev_dev.parent = get_device(&sdev->sdev_gendev);
sdev->sdev_dev.class = &sdev_class;
dev_set_name(&sdev->sdev_dev, "%d:%d:%d:%d",
sdev->host->host_no, sdev->channel, sdev->id, sdev->lun);
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c
index e7108e75653d..42e8550cd2b6 100644
--- a/drivers/serial/8250_pci.c
+++ b/drivers/serial/8250_pci.c
@@ -1561,11 +1561,16 @@ enum pci_board_num_t {
pbn_exar_XR17C152,
pbn_exar_XR17C154,
pbn_exar_XR17C158,
+ pbn_exar_ibm_saturn,
pbn_pasemi_1682M,
pbn_ni8430_2,
pbn_ni8430_4,
pbn_ni8430_8,
pbn_ni8430_16,
+ pbn_ADDIDATA_PCIe_1_3906250,
+ pbn_ADDIDATA_PCIe_2_3906250,
+ pbn_ADDIDATA_PCIe_4_3906250,
+ pbn_ADDIDATA_PCIe_8_3906250,
};
/*
@@ -2146,6 +2151,13 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.base_baud = 921600,
.uart_offset = 0x200,
},
+ [pbn_exar_ibm_saturn] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 921600,
+ .uart_offset = 0x200,
+ },
+
/*
* PA Semi PWRficient PA6T-1682M on-chip UART
*/
@@ -2185,6 +2197,37 @@ static struct pciserial_board pci_boards[] __devinitdata = {
.uart_offset = 0x10,
.first_offset = 0x800,
},
+ /*
+ * ADDI-DATA GmbH PCI-Express communication cards <info@addi-data.com>
+ */
+ [pbn_ADDIDATA_PCIe_1_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_ADDIDATA_PCIe_2_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_ADDIDATA_PCIe_4_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+ [pbn_ADDIDATA_PCIe_8_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
};
static const struct pci_device_id softmodem_blacklist[] = {
@@ -2649,6 +2692,9 @@ static struct pci_device_id serial_pci_tbl[] = {
PCI_SUBVENDOR_ID_CONNECT_TECH,
PCI_SUBDEVICE_ID_CONNECT_TECH_PCI_UART_8_485, 0, 0,
pbn_b0_8_1843200_200 },
+ { PCI_VENDOR_ID_EXAR, PCI_DEVICE_ID_EXAR_XR17C152,
+ PCI_VENDOR_ID_IBM, PCI_SUBDEVICE_ID_IBM_SATURN_SERIAL_ONE_PORT,
+ 0, 0, pbn_exar_ibm_saturn },
{ PCI_VENDOR_ID_SEALEVEL, PCI_DEVICE_ID_SEALEVEL_U530,
PCI_ANY_ID, PCI_ANY_ID, 0, 0,
@@ -3556,6 +3602,38 @@ static struct pci_device_id serial_pci_tbl[] = {
0,
pbn_b0_8_115200 },
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCIe7500,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_ADDIDATA_PCIe_4_3906250 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCIe7420,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_ADDIDATA_PCIe_2_3906250 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCIe7300,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_ADDIDATA_PCIe_1_3906250 },
+
+ { PCI_VENDOR_ID_ADDIDATA,
+ PCI_DEVICE_ID_ADDIDATA_APCIe7800,
+ PCI_ANY_ID,
+ PCI_ANY_ID,
+ 0,
+ 0,
+ pbn_ADDIDATA_PCIe_8_3906250 },
+
{ PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835,
PCI_VENDOR_ID_IBM, 0x0299,
0, 0, pbn_b0_bt_2_115200 },
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index 3551c5cb7094..9d948bccafaf 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -1531,7 +1531,7 @@ static int __devinit atmel_serial_probe(struct platform_device *pdev)
void *data;
int ret;
- BUILD_BUG_ON(!is_power_of_2(ATMEL_SERIAL_RINGSIZE));
+ BUILD_BUG_ON(ATMEL_SERIAL_RINGSIZE & (ATMEL_SERIAL_RINGSIZE - 1));
port = &atmel_ports[pdev->id];
port->backup_imr = 0;
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c
index d7bcd074d383..7ce9e9f567a3 100644
--- a/drivers/serial/mpc52xx_uart.c
+++ b/drivers/serial/mpc52xx_uart.c
@@ -705,7 +705,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
return -EINVAL;
if ((ser->irq != port->irq) ||
- (ser->io_type != SERIAL_IO_MEM) ||
+ (ser->io_type != UPIO_MEM) ||
(ser->baud_base != port->uartclk) ||
(ser->iomem_base != (void *)port->mapbase) ||
(ser->hub6 != 0))
diff --git a/drivers/serial/serial_cs.c b/drivers/serial/serial_cs.c
index ff4617e21426..7c7914f5fa02 100644
--- a/drivers/serial/serial_cs.c
+++ b/drivers/serial/serial_cs.c
@@ -879,10 +879,10 @@ static struct pcmcia_device_id serial_ids[] = {
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0175, 0x0000, "cis/DP83903.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x0035, "cis/3CXEM556.cis"),
PCMCIA_MFC_DEVICE_CIS_MANF_CARD(1, 0x0101, 0x003d, "cis/3CXEM556.cis"),
- PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
- PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0x0710, "SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
- PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
- PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
+ PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC850", 0xd85f6206, 0x42a2c018, "cis/SW_8xx_SER.cis"), /* Sierra Wireless AC850 3G Network Adapter R1 */
+ PCMCIA_DEVICE_CIS_PROD_ID12("Sierra Wireless", "AC710/AC750", 0xd85f6206, 0x761b11e0, "cis/SW_7xx_SER.cis"), /* Sierra Wireless AC710/AC750 GPRS Network Adapter R1 */
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x0192, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- pre update */
+ PCMCIA_DEVICE_CIS_MANF_CARD(0x013f, 0xa555, "cis/SW_555_SER.cis"), /* Sierra Aircard 555 CDMA 1xrtt Modem -- post update */
PCMCIA_DEVICE_CIS_PROD_ID12("MultiTech", "PCMCIA 56K DataFax", 0x842047ee, 0xc2efcf03, "cis/MT5634ZLX.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-2", 0x96913a85, 0x27ab5437, "cis/COMpad2.cis"),
PCMCIA_DEVICE_CIS_PROD_ID12("ADVANTECH", "COMpad-32/85B-4", 0x96913a85, 0xcec8f102, "cis/COMpad4.cis"),
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index 7df3ba4f1f4d..d21b3469f6d7 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -93,8 +93,6 @@ source "drivers/staging/dst/Kconfig"
source "drivers/staging/pohmelfs/Kconfig"
-source "drivers/staging/stlc45xx/Kconfig"
-
source "drivers/staging/b3dfg/Kconfig"
source "drivers/staging/phison/Kconfig"
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 747571172269..8cbf1aebea2e 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -29,7 +29,6 @@ obj-$(CONFIG_ANDROID) += android/
obj-$(CONFIG_ANDROID) += dream/
obj-$(CONFIG_DST) += dst/
obj-$(CONFIG_POHMELFS) += pohmelfs/
-obj-$(CONFIG_STLC45XX) += stlc45xx/
obj-$(CONFIG_B3DFG) += b3dfg/
obj-$(CONFIG_IDE_PHISON) += phison/
obj-$(CONFIG_PLAN9AUTH) += p9auth/
diff --git a/drivers/staging/android/Kconfig b/drivers/staging/android/Kconfig
index 247194992374..eb675635ae60 100644
--- a/drivers/staging/android/Kconfig
+++ b/drivers/staging/android/Kconfig
@@ -2,6 +2,7 @@ menu "Android"
config ANDROID
bool "Android Drivers"
+ depends on BROKEN
default N
---help---
Enable support for various drivers needed on the Android platform
diff --git a/drivers/staging/hv/ChannelMgmt.h b/drivers/staging/hv/ChannelMgmt.h
index a839d8fe6cec..fa973d86b624 100644
--- a/drivers/staging/hv/ChannelMgmt.h
+++ b/drivers/staging/hv/ChannelMgmt.h
@@ -26,6 +26,7 @@
#define _CHANNEL_MGMT_H_
#include <linux/list.h>
+#include <linux/timer.h>
#include "RingBuffer.h"
#include "VmbusChannelInterface.h"
#include "VmbusPacketFormat.h"
@@ -54,7 +55,7 @@ enum vmbus_channel_message_type {
ChannelMessageViewRangeRemove = 18,
#endif
ChannelMessageCount
-} __attribute__((packed));
+};
struct vmbus_channel_message_header {
enum vmbus_channel_message_type MessageType;
diff --git a/drivers/staging/hv/NetVsc.c b/drivers/staging/hv/NetVsc.c
index 1610b845198f..d384c0ddf069 100644
--- a/drivers/staging/hv/NetVsc.c
+++ b/drivers/staging/hv/NetVsc.c
@@ -1052,7 +1052,7 @@ static void NetVscOnReceive(struct hv_device *Device,
*/
spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
while (!list_empty(&netDevice->ReceivePacketList)) {
- list_move_tail(&netDevice->ReceivePacketList, &listHead);
+ list_move_tail(netDevice->ReceivePacketList.next, &listHead);
if (++count == vmxferpagePacket->RangeCount + 1)
break;
}
@@ -1071,7 +1071,7 @@ static void NetVscOnReceive(struct hv_device *Device,
/* Return it to the freelist */
spin_lock_irqsave(&netDevice->receive_packet_list_lock, flags);
for (i = count; i != 0; i--) {
- list_move_tail(&listHead,
+ list_move_tail(listHead.next,
&netDevice->ReceivePacketList);
}
spin_unlock_irqrestore(&netDevice->receive_packet_list_lock,
@@ -1085,8 +1085,7 @@ static void NetVscOnReceive(struct hv_device *Device,
}
/* Remove the 1st packet to represent the xfer page packet itself */
- xferpagePacket = list_entry(&listHead, struct xferpage_packet,
- ListEntry);
+ xferpagePacket = (struct xferpage_packet*)listHead.next;
list_del(&xferpagePacket->ListEntry);
/* This is how much we can satisfy */
@@ -1102,8 +1101,7 @@ static void NetVscOnReceive(struct hv_device *Device,
/* Each range represents 1 RNDIS pkt that contains 1 ethernet frame */
for (i = 0; i < (count - 1); i++) {
- netvscPacket = list_entry(&listHead, struct hv_netvsc_packet,
- ListEntry);
+ netvscPacket = (struct hv_netvsc_packet*)listHead.next;
list_del(&netvscPacket->ListEntry);
/* Initialize the netvsc packet */
diff --git a/drivers/staging/hv/TODO b/drivers/staging/hv/TODO
index 4d390b237742..dbfbde937a66 100644
--- a/drivers/staging/hv/TODO
+++ b/drivers/staging/hv/TODO
@@ -1,11 +1,17 @@
TODO:
- fix remaining checkpatch warnings and errors
+ - use of /** when it is not a kerneldoc header
- remove RingBuffer.c to us in-kernel ringbuffer functions instead.
- audit the vmbus to verify it is working properly with the
driver model
+ - convert vmbus driver interface function pointer tables
+ to constant, a.k.a vmbus_ops
- see if the vmbus can be merged with the other virtual busses
in the kernel
- audit the network driver
+ - use existing net_device_stats struct in network device
+ - checking for carrier inside open is wrong, network device API
+ confusion??
- audit the block driver
- audit the scsi driver
diff --git a/drivers/staging/hv/osd.h b/drivers/staging/hv/osd.h
index 9504604c72bd..ce064e8ea644 100644
--- a/drivers/staging/hv/osd.h
+++ b/drivers/staging/hv/osd.h
@@ -25,6 +25,7 @@
#ifndef _OSD_H_
#define _OSD_H_
+#include <linux/workqueue.h>
/* Defines */
#define ALIGN_UP(value, align) (((value) & (align-1)) ? \
diff --git a/drivers/staging/hv/vmbus_drv.c b/drivers/staging/hv/vmbus_drv.c
index 582318f10222..894eecfc63ca 100644
--- a/drivers/staging/hv/vmbus_drv.c
+++ b/drivers/staging/hv/vmbus_drv.c
@@ -507,12 +507,12 @@ static struct hv_device *vmbus_child_device_create(struct hv_guid *type,
child_device_obj = &child_device_ctx->device_obj;
child_device_obj->context = context;
- memcpy(&child_device_obj->deviceType, &type, sizeof(struct hv_guid));
- memcpy(&child_device_obj->deviceInstance, &instance,
+ memcpy(&child_device_obj->deviceType, type, sizeof(struct hv_guid));
+ memcpy(&child_device_obj->deviceInstance, instance,
sizeof(struct hv_guid));
- memcpy(&child_device_ctx->class_id, &type, sizeof(struct hv_guid));
- memcpy(&child_device_ctx->device_id, &instance, sizeof(struct hv_guid));
+ memcpy(&child_device_ctx->class_id, type, sizeof(struct hv_guid));
+ memcpy(&child_device_ctx->device_id, instance, sizeof(struct hv_guid));
DPRINT_EXIT(VMBUS_DRV);
@@ -537,18 +537,7 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj,
DPRINT_DBG(VMBUS_DRV, "child device (%p) registering",
child_device_ctx);
- /* Make sure we are not registered already */
- if (strlen(dev_name(&child_device_ctx->device)) != 0) {
- DPRINT_ERR(VMBUS_DRV,
- "child device (%p) already registered - busid %s",
- child_device_ctx,
- dev_name(&child_device_ctx->device));
-
- ret = -1;
- goto Cleanup;
- }
-
- /* Set the device bus id. Otherwise, device_register()will fail. */
+ /* Set the device name. Otherwise, device_register() will fail. */
dev_set_name(&child_device_ctx->device, "vmbus_0_%d",
atomic_inc_return(&device_num));
@@ -573,7 +562,6 @@ static int vmbus_child_device_register(struct hv_device *root_device_obj,
DPRINT_INFO(VMBUS_DRV, "child device (%p) registered",
&child_device_ctx->device);
-Cleanup:
DPRINT_EXIT(VMBUS_DRV);
return ret;
@@ -623,8 +611,6 @@ static void vmbus_child_device_destroy(struct hv_device *device_obj)
static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
{
struct device_context *device_ctx = device_to_device_context(device);
- int i = 0;
- int len = 0;
int ret;
DPRINT_ENTER(VMBUS_DRV);
@@ -644,8 +630,6 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
device_ctx->class_id.data[14],
device_ctx->class_id.data[15]);
- env->envp_idx = i;
- env->buflen = len;
ret = add_uevent_var(env, "VMBUS_DEVICE_CLASS_GUID={"
"%02x%02x%02x%02x-%02x%02x-%02x%02x-"
"%02x%02x%02x%02x%02x%02x%02x%02x}",
@@ -691,8 +675,6 @@ static int vmbus_uevent(struct device *device, struct kobj_uevent_env *env)
if (ret)
return ret;
- env->envp[env->envp_idx] = NULL;
-
DPRINT_EXIT(VMBUS_DRV);
return 0;
diff --git a/drivers/staging/otus/Kconfig b/drivers/staging/otus/Kconfig
index d549d08fd495..f6cc2625e341 100644
--- a/drivers/staging/otus/Kconfig
+++ b/drivers/staging/otus/Kconfig
@@ -1,6 +1,6 @@
config OTUS
tristate "Atheros OTUS 802.11n USB wireless support"
- depends on USB && WLAN_80211 && MAC80211
+ depends on USB && WLAN && MAC80211
default N
---help---
Enable support for Atheros 802.11n USB hardware:
diff --git a/drivers/staging/panel/panel.c b/drivers/staging/panel/panel.c
index dd7d3fde9699..4ce399b6d237 100644
--- a/drivers/staging/panel/panel.c
+++ b/drivers/staging/panel/panel.c
@@ -2071,11 +2071,15 @@ static void panel_detach(struct parport *port)
return;
}
- if (keypad_enabled && keypad_initialized)
+ if (keypad_enabled && keypad_initialized) {
misc_deregister(&keypad_dev);
+ keypad_initialized = 0;
+ }
- if (lcd_enabled && lcd_initialized)
+ if (lcd_enabled && lcd_initialized) {
misc_deregister(&lcd_dev);
+ lcd_initialized = 0;
+ }
parport_release(pprt);
parport_unregister_device(pprt);
@@ -2211,13 +2215,16 @@ static void __exit panel_cleanup_module(void)
del_timer(&scan_timer);
if (pprt != NULL) {
- if (keypad_enabled)
+ if (keypad_enabled) {
misc_deregister(&keypad_dev);
+ keypad_initialized = 0;
+ }
if (lcd_enabled) {
panel_lcd_print("\x0cLCD driver " PANEL_VERSION
"\nunloaded.\x1b[Lc\x1b[Lb\x1b[L-");
misc_deregister(&lcd_dev);
+ lcd_initialized = 0;
}
/* TODO: free all input signals */
diff --git a/drivers/staging/rt2860/Kconfig b/drivers/staging/rt2860/Kconfig
index 7f44e5e72463..efe38e25c5ed 100644
--- a/drivers/staging/rt2860/Kconfig
+++ b/drivers/staging/rt2860/Kconfig
@@ -1,5 +1,5 @@
config RT2860
tristate "Ralink 2860 wireless support"
- depends on PCI && X86 && WLAN_80211
+ depends on PCI && X86 && WLAN
---help---
This is an experimental driver for the Ralink 2860 wireless chip.
diff --git a/drivers/staging/rt2870/Kconfig b/drivers/staging/rt2870/Kconfig
index 76841f6dea93..aea5c8221810 100644
--- a/drivers/staging/rt2870/Kconfig
+++ b/drivers/staging/rt2870/Kconfig
@@ -1,5 +1,5 @@
config RT2870
tristate "Ralink 2870/3070 wireless support"
- depends on USB && X86 && WLAN_80211
+ depends on USB && X86 && WLAN
---help---
This is an experimental driver for the Ralink xx70 wireless chips.
diff --git a/drivers/staging/rt3090/Kconfig b/drivers/staging/rt3090/Kconfig
index 255e8eaa4836..2b3f745d72b7 100644
--- a/drivers/staging/rt3090/Kconfig
+++ b/drivers/staging/rt3090/Kconfig
@@ -1,5 +1,5 @@
config RT3090
tristate "Ralink 3090 wireless support"
- depends on PCI && X86 && WLAN_80211
+ depends on PCI && X86 && WLAN
---help---
This is an experimental driver for the Ralink 3090 wireless chip.
diff --git a/drivers/staging/rtl8187se/Kconfig b/drivers/staging/rtl8187se/Kconfig
index 236e42725447..203c79b8180f 100644
--- a/drivers/staging/rtl8187se/Kconfig
+++ b/drivers/staging/rtl8187se/Kconfig
@@ -1,6 +1,6 @@
config RTL8187SE
tristate "RealTek RTL8187SE Wireless LAN NIC driver"
- depends on PCI
+ depends on PCI && WLAN
depends on WIRELESS_EXT
default N
---help---
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
index 013c3e19ae25..4c5d63fd5833 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_crypt.c
@@ -53,10 +53,8 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
list_del(ptr);
- if (entry->ops) {
+ if (entry->ops)
entry->ops->deinit(entry->priv);
- module_put(entry->ops->owner);
- }
kfree(entry);
}
}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
index 6fbe4890cb66..18392fce487d 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_module.c
@@ -189,10 +189,8 @@ void free_ieee80211(struct net_device *dev)
for (i = 0; i < WEP_KEYS; i++) {
struct ieee80211_crypt_data *crypt = ieee->crypt[i];
if (crypt) {
- if (crypt->ops) {
+ if (crypt->ops)
crypt->ops->deinit(crypt->priv);
- module_put(crypt->ops->owner);
- }
kfree(crypt);
ieee->crypt[i] = NULL;
}
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
index 59b2ab48cdcf..334e4c7ec61b 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_softmac.c
@@ -2839,16 +2839,12 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
goto skip_host_crypt;
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
- request_module("ieee80211_crypt_wep");
+ if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
- request_module("ieee80211_crypt_tkip");
+ else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
- request_module("ieee80211_crypt_ccmp");
+ else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- }
if (ops == NULL) {
printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
@@ -2869,7 +2865,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
}
memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
new_crypt->ops = ops;
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ if (new_crypt->ops)
new_crypt->priv =
new_crypt->ops->init(param->u.crypt.idx);
diff --git a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
index 8d8bdd0a130e..a08b97a09512 100644
--- a/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8187se/ieee80211/ieee80211_wx.c
@@ -331,12 +331,10 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
return -ENOMEM;
memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
- if (!new_crypt->ops) {
- request_module("ieee80211_crypt_wep");
+ if (!new_crypt->ops)
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
- }
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ if (new_crypt->ops)
new_crypt->priv = new_crypt->ops->init(key);
if (!new_crypt->ops || !new_crypt->priv) {
@@ -483,7 +481,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int i, idx, ret = 0;
int group_key = 0;
- const char *alg, *module;
+ const char *alg;
struct ieee80211_crypto_ops *ops;
struct ieee80211_crypt_data **crypt;
@@ -539,15 +537,12 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
switch (ext->alg) {
case IW_ENCODE_ALG_WEP:
alg = "WEP";
- module = "ieee80211_crypt_wep";
break;
case IW_ENCODE_ALG_TKIP:
alg = "TKIP";
- module = "ieee80211_crypt_tkip";
break;
case IW_ENCODE_ALG_CCMP:
alg = "CCMP";
- module = "ieee80211_crypt_ccmp";
break;
default:
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
@@ -558,10 +553,8 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
// printk("8-09-08-9=====>%s, alg name:%s\n",__func__, alg);
ops = ieee80211_get_crypto_ops(alg);
- if (ops == NULL) {
- request_module(module);
+ if (ops == NULL)
ops = ieee80211_get_crypto_ops(alg);
- }
if (ops == NULL) {
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
dev->name, ext->alg);
@@ -581,7 +574,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
goto done;
}
new_crypt->ops = ops;
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ if (new_crypt->ops)
new_crypt->priv = new_crypt->ops->init(idx);
if (new_crypt->priv == NULL) {
kfree(new_crypt);
diff --git a/drivers/staging/rtl8192e/Kconfig b/drivers/staging/rtl8192e/Kconfig
index 3100aa58c940..37e4fde45073 100644
--- a/drivers/staging/rtl8192e/Kconfig
+++ b/drivers/staging/rtl8192e/Kconfig
@@ -1,6 +1,6 @@
config RTL8192E
tristate "RealTek RTL8192E Wireless LAN NIC driver"
- depends on PCI
+ depends on PCI && WLAN
depends on WIRELESS_EXT
default N
---help---
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
index 1a8ea8a40c3c..b1c54932da3e 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_crypt.c
@@ -53,14 +53,8 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
list_del(ptr);
- if (entry->ops) {
+ if (entry->ops)
entry->ops->deinit(entry->priv);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- module_put(entry->ops->owner);
-#else
- __MOD_DEC_USE_COUNT(entry->ops->owner);
-#endif
- }
kfree(entry);
}
}
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
index 16256a31f993..12c2a18e1fa2 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_module.c
@@ -242,14 +242,8 @@ void free_ieee80211(struct net_device *dev)
for (i = 0; i < WEP_KEYS; i++) {
struct ieee80211_crypt_data *crypt = ieee->crypt[i];
if (crypt) {
- if (crypt->ops) {
+ if (crypt->ops)
crypt->ops->deinit(crypt->priv);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- module_put(crypt->ops->owner);
-#else
- __MOD_DEC_USE_COUNT(crypt->ops->owner);
-#endif
- }
kfree(crypt);
ieee->crypt[i] = NULL;
}
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
index 2fc04df872ca..eae7c4579a68 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_softmac.c
@@ -3284,17 +3284,14 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
goto skip_host_crypt;
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
- request_module("ieee80211_crypt_wep");
+ if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
- request_module("ieee80211_crypt_tkip");
+ /* set WEP40 first, it will be modified according to WEP104 or
+ * WEP40 at other place */
+ else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
- request_module("ieee80211_crypt_ccmp");
+ else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- }
if (ops == NULL) {
printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
@@ -3315,11 +3312,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
}
memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
new_crypt->ops = ops;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
-#else
- if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner))
-#endif
+ if (new_crypt->ops)
new_crypt->priv =
new_crypt->ops->init(param->u.crypt.idx);
diff --git a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
index 223483126b0e..4e34a1f4c66b 100644
--- a/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192e/ieee80211/ieee80211_wx.c
@@ -482,15 +482,9 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
return -ENOMEM;
memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
- if (!new_crypt->ops) {
- request_module("ieee80211_crypt_wep");
+ if (!new_crypt->ops)
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
- }
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,0)
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
-#else
- if (new_crypt->ops && try_inc_mod_count(new_crypt->ops->owner))
-#endif
+ if (new_crypt->ops)
new_crypt->priv = new_crypt->ops->init(key);
if (!new_crypt->ops || !new_crypt->priv) {
@@ -644,7 +638,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int i, idx;
int group_key = 0;
- const char *alg, *module;
+ const char *alg;
struct ieee80211_crypto_ops *ops;
struct ieee80211_crypt_data **crypt;
@@ -711,15 +705,12 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
switch (ext->alg) {
case IW_ENCODE_ALG_WEP:
alg = "WEP";
- module = "ieee80211_crypt_wep";
break;
case IW_ENCODE_ALG_TKIP:
alg = "TKIP";
- module = "ieee80211_crypt_tkip";
break;
case IW_ENCODE_ALG_CCMP:
alg = "CCMP";
- module = "ieee80211_crypt_ccmp";
break;
default:
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
@@ -730,10 +721,8 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
printk("alg name:%s\n",alg);
ops = ieee80211_get_crypto_ops(alg);
- if (ops == NULL) {
- request_module(module);
+ if (ops == NULL)
ops = ieee80211_get_crypto_ops(alg);
- }
if (ops == NULL) {
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
dev->name, ext->alg);
@@ -758,7 +747,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
goto done;
}
new_crypt->ops = ops;
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ if (new_crypt->ops)
new_crypt->priv = new_crypt->ops->init(idx);
if (new_crypt->priv == NULL) {
kfree(new_crypt);
diff --git a/drivers/staging/rtl8192su/Kconfig b/drivers/staging/rtl8192su/Kconfig
index 770f41280f21..b8c95f942069 100644
--- a/drivers/staging/rtl8192su/Kconfig
+++ b/drivers/staging/rtl8192su/Kconfig
@@ -1,6 +1,6 @@
config RTL8192SU
tristate "RealTek RTL8192SU Wireless LAN NIC driver"
- depends on PCI
+ depends on PCI && WLAN
depends on WIRELESS_EXT
default N
---help---
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c
index d76a54d59d2f..521e7b989934 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_crypt.c
@@ -53,10 +53,8 @@ void ieee80211_crypt_deinit_entries(struct ieee80211_device *ieee,
list_del(ptr);
- if (entry->ops) {
+ if (entry->ops)
entry->ops->deinit(entry->priv);
- module_put(entry->ops->owner);
- }
kfree(entry);
}
}
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
index 68dc8fa094cc..c3383bb8b760 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_module.c
@@ -216,10 +216,8 @@ void free_ieee80211(struct net_device *dev)
for (i = 0; i < WEP_KEYS; i++) {
struct ieee80211_crypt_data *crypt = ieee->crypt[i];
if (crypt) {
- if (crypt->ops) {
+ if (crypt->ops)
crypt->ops->deinit(crypt->priv);
- module_put(crypt->ops->owner);
- }
kfree(crypt);
ieee->crypt[i] = NULL;
}
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
index c64ae03f68a0..fd8e11252f1b 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_softmac.c
@@ -3026,17 +3026,14 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
goto skip_host_crypt;
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) {
- request_module("ieee80211_crypt_wep");
+ if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0)
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- //set WEP40 first, it will be modified according to WEP104 or WEP40 at other place
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) {
- request_module("ieee80211_crypt_tkip");
+ /* set WEP40 first, it will be modified according to WEP104 or
+ * WEP40 at other place */
+ else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0)
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) {
- request_module("ieee80211_crypt_ccmp");
+ else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0)
ops = ieee80211_get_crypto_ops(param->u.crypt.alg);
- }
if (ops == NULL) {
printk("unknown crypto alg '%s'\n", param->u.crypt.alg);
param->u.crypt.err = IEEE_CRYPT_ERR_UNKNOWN_ALG;
@@ -3058,7 +3055,7 @@ static int ieee80211_wpa_set_encryption(struct ieee80211_device *ieee,
memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
new_crypt->ops = ops;
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ if (new_crypt->ops)
new_crypt->priv =
new_crypt->ops->init(param->u.crypt.idx);
diff --git a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
index 107759024335..6146c6435dde 100644
--- a/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
+++ b/drivers/staging/rtl8192su/ieee80211/ieee80211_wx.c
@@ -358,11 +358,9 @@ int ieee80211_wx_set_encode(struct ieee80211_device *ieee,
return -ENOMEM;
memset(new_crypt, 0, sizeof(struct ieee80211_crypt_data));
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
- if (!new_crypt->ops) {
- request_module("ieee80211_crypt_wep");
+ if (!new_crypt->ops)
new_crypt->ops = ieee80211_get_crypto_ops("WEP");
- }
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ if (new_crypt->ops)
new_crypt->priv = new_crypt->ops->init(key);
if (!new_crypt->ops || !new_crypt->priv) {
@@ -507,7 +505,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
int i, idx;
int group_key = 0;
- const char *alg, *module;
+ const char *alg;
struct ieee80211_crypto_ops *ops;
struct ieee80211_crypt_data **crypt;
@@ -570,15 +568,12 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
switch (ext->alg) {
case IW_ENCODE_ALG_WEP:
alg = "WEP";
- module = "ieee80211_crypt_wep";
break;
case IW_ENCODE_ALG_TKIP:
alg = "TKIP";
- module = "ieee80211_crypt_tkip";
break;
case IW_ENCODE_ALG_CCMP:
alg = "CCMP";
- module = "ieee80211_crypt_ccmp";
break;
default:
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
@@ -589,10 +584,8 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
printk("alg name:%s\n",alg);
ops = ieee80211_get_crypto_ops(alg);
- if (ops == NULL) {
- request_module("%s", module);
+ if (ops == NULL)
ops = ieee80211_get_crypto_ops(alg);
- }
if (ops == NULL) {
IEEE80211_DEBUG_WX("%s: unknown crypto alg %d\n",
dev->name, ext->alg);
@@ -612,7 +605,7 @@ int ieee80211_wx_set_encode_ext(struct ieee80211_device *ieee,
goto done;
}
new_crypt->ops = ops;
- if (new_crypt->ops && try_module_get(new_crypt->ops->owner))
+ if (new_crypt->ops)
new_crypt->priv = new_crypt->ops->init(idx);
if (new_crypt->priv == NULL) {
kfree(new_crypt);
diff --git a/drivers/staging/stlc45xx/Kconfig b/drivers/staging/stlc45xx/Kconfig
deleted file mode 100644
index 947fb75a9c68..000000000000
--- a/drivers/staging/stlc45xx/Kconfig
+++ /dev/null
@@ -1,8 +0,0 @@
-config STLC45XX
- tristate "stlc4550/4560 support"
- depends on MAC80211 && WLAN_80211 && SPI_MASTER && GENERIC_HARDIRQS
- ---help---
- This is a driver for stlc4550 and stlc4560 chipsets.
-
- To compile this driver as a module, choose M here: the module will be
- called stlc45xx. If unsure, say N.
diff --git a/drivers/staging/stlc45xx/Makefile b/drivers/staging/stlc45xx/Makefile
deleted file mode 100644
index 7ee32903055a..000000000000
--- a/drivers/staging/stlc45xx/Makefile
+++ /dev/null
@@ -1 +0,0 @@
-obj-$(CONFIG_STLC45XX) += stlc45xx.o
diff --git a/drivers/staging/stlc45xx/stlc45xx.c b/drivers/staging/stlc45xx/stlc45xx.c
deleted file mode 100644
index be99eb33d817..000000000000
--- a/drivers/staging/stlc45xx/stlc45xx.c
+++ /dev/null
@@ -1,2594 +0,0 @@
-/*
- * This file is part of stlc45xx
- *
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include "stlc45xx.h"
-
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/firmware.h>
-#include <linux/delay.h>
-#include <linux/irq.h>
-#include <linux/spi/spi.h>
-#include <linux/etherdevice.h>
-#include <linux/gpio.h>
-#include <linux/moduleparam.h>
-
-#include "stlc45xx_lmac.h"
-
-/*
- * gpios should be handled in board files and provided via platform data,
- * but because it's currently impossible for stlc45xx to have a header file
- * in include/linux, let's use module paramaters for now
- */
-static int stlc45xx_gpio_power = 97;
-module_param(stlc45xx_gpio_power, int, 0444);
-MODULE_PARM_DESC(stlc45xx_gpio_power, "stlc45xx gpio number for power line");
-
-static int stlc45xx_gpio_irq = 87;
-module_param(stlc45xx_gpio_irq, int, 0444);
-MODULE_PARM_DESC(stlc45xx_gpio_irq, "stlc45xx gpio number for irq line");
-
-static const u8 default_cal_channels[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x09,
- 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10,
- 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xe0, 0x00, 0xe0, 0x00,
- 0xe0, 0x00, 0xe0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0,
- 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42,
- 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00,
- 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9,
- 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00,
- 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
- 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0,
- 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
- 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d,
- 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa,
- 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00,
- 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17,
- 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00,
- 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00,
- 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00,
- 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
- 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x71, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8,
- 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
- 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0,
- 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6,
- 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00,
- 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
- 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0,
- 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
- 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca,
- 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4,
- 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00,
- 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21,
- 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00,
- 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00,
- 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00,
- 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
- 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0,
- 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
- 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76,
- 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01,
- 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0,
- 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
- 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0,
- 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
- 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37,
- 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc,
- 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00,
- 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b,
- 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00,
- 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00,
- 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00,
- 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
- 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0,
- 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
- 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a,
- 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d,
- 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
- 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x7b, 0x09, 0x00, 0x00, 0xc9, 0xff,
- 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10,
- 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
- 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab,
- 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb,
- 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00,
- 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33,
- 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00,
- 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00,
- 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00,
- 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
- 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0,
- 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
- 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7,
- 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17,
- 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00,
- 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d,
- 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00,
- 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80,
- 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x80, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00,
- 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00,
- 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0,
- 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42,
- 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00,
- 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01,
- 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00,
- 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
- 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0,
- 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
- 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0,
- 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21,
- 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00,
- 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17,
- 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00,
- 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
- 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0,
- 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
- 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x85, 0x09, 0x00, 0x00, 0xc9,
- 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01,
- 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0,
- 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01,
- 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00,
- 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
- 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0,
- 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
- 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb,
- 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b,
- 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00,
- 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21,
- 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00,
- 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
- 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0,
- 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
- 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0,
- 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96,
- 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
- 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,
- 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x8a, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00,
- 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0,
- 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
- 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0,
- 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
- 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22,
- 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33,
- 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00,
- 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b,
- 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00,
- 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
- 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0,
- 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
- 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0,
- 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0,
- 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00,
- 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d,
- 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
- 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x09, 0x00, 0x00,
- 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10,
- 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00,
- 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54,
- 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42,
- 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00,
- 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33,
- 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00,
- 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
- 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0,
- 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
- 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0,
- 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa,
- 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00,
- 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17,
- 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00,
- 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c,
- 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00,
- 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
- 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x94, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00,
- 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01,
- 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0,
- 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42,
- 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00,
- 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
- 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0,
- 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc,
- 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0,
- 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4,
- 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00,
- 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21,
- 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00,
- 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d,
- 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00,
- 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
- 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0,
- 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96,
- 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x09, 0x00,
- 0x00, 0xc9, 0xff, 0xd8, 0xff, 0x00, 0x00, 0x00, 0x01, 0x10, 0x01,
- 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0,
- 0x00, 0xf0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00,
- 0x54, 0x01, 0xab, 0xf6, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0,
- 0x42, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb,
- 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0,
- 0x33, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc,
- 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00,
- 0xbc, 0xfb, 0x00, 0xca, 0x79, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b,
- 0xc0, 0x2b, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00,
- 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54,
- 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00,
- 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
- 0x00, 0xaa, 0xa7, 0x00, 0xa9, 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0,
- 0x17, 0xc0, 0x17, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
- 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06,
- 0x2c, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96,
- 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
- 0x96, 0x00, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x06, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x9e, 0x09, 0x00, 0x00, 0xc9, 0xff, 0xd8, 0xff,
- 0x00, 0x00, 0x00, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10,
- 0x01, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xd0, 0x00,
- 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0x54, 0x01, 0xab, 0xf6, 0xc0,
- 0x42, 0xc0, 0x42, 0xc0, 0x42, 0xc0, 0x42, 0x00, 0xcb, 0x00, 0xcb,
- 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00, 0xcb, 0x00,
- 0xcb, 0x22, 0x01, 0x37, 0xa9, 0xc0, 0x33, 0xc0, 0x33, 0xc0, 0x33,
- 0xc0, 0x33, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00,
- 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0x00, 0xbc, 0xfb, 0x00, 0xca, 0x79,
- 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0xc0, 0x2b, 0x00, 0xb4, 0x00,
- 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4, 0x00, 0xb4,
- 0x00, 0xb4, 0xd0, 0x00, 0x5d, 0x54, 0xc0, 0x21, 0xc0, 0x21, 0xc0,
- 0x21, 0xc0, 0x21, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa,
- 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0xa7, 0x00, 0xa9,
- 0x3d, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0xc0, 0x17, 0x00, 0xa0,
- 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00,
- 0xa0, 0x00, 0xa0, 0x7a, 0x00, 0x06, 0x2c, 0xc0, 0x0d, 0xc0, 0x0d,
- 0xc0, 0x0d, 0xc0, 0x0d, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00,
- 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x96, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00 };
-
-static const u8 default_cal_rssi[] = {
- 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72,
- 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00,
- 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a,
- 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe,
- 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00,
- 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01,
- 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a,
- 0x00, 0x00, 0x00, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-static void stlc45xx_tx_edcf(struct stlc45xx *stlc);
-static void stlc45xx_tx_setup(struct stlc45xx *stlc);
-static void stlc45xx_tx_scan(struct stlc45xx *stlc);
-static void stlc45xx_tx_psm(struct stlc45xx *stlc, bool enable);
-static int stlc45xx_tx_nullfunc(struct stlc45xx *stlc, bool powersave);
-static int stlc45xx_tx_pspoll(struct stlc45xx *stlc, bool powersave);
-
-static ssize_t stlc45xx_sysfs_show_cal_rssi(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct stlc45xx *stlc = dev_get_drvdata(dev);
- ssize_t len;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- len = PAGE_SIZE;
-
- mutex_lock(&stlc->mutex);
-
- if (stlc->cal_rssi)
- hex_dump_to_buffer(stlc->cal_rssi, RSSI_CAL_ARRAY_LEN, 16,
- 2, buf, len, 0);
- mutex_unlock(&stlc->mutex);
-
- len = strlen(buf);
-
- return len;
-}
-
-static ssize_t stlc45xx_sysfs_store_cal_rssi(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct stlc45xx *stlc = dev_get_drvdata(dev);
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- mutex_lock(&stlc->mutex);
-
- if (count != RSSI_CAL_ARRAY_LEN) {
- stlc45xx_error("invalid cal_rssi length: %zu", count);
- count = 0;
- goto out_unlock;
- }
-
- kfree(stlc->cal_rssi);
-
- stlc->cal_rssi = kmemdup(buf, RSSI_CAL_ARRAY_LEN, GFP_KERNEL);
-
- if (!stlc->cal_rssi) {
- stlc45xx_error("failed to allocate memory for cal_rssi");
- count = 0;
- goto out_unlock;
- }
-
- out_unlock:
- mutex_unlock(&stlc->mutex);
-
- return count;
-}
-
-static ssize_t stlc45xx_sysfs_show_cal_channels(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct stlc45xx *stlc = dev_get_drvdata(dev);
- ssize_t len;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- len = PAGE_SIZE;
-
- mutex_lock(&stlc->mutex);
-
- if (stlc->cal_channels)
- hex_dump_to_buffer(stlc->cal_channels, CHANNEL_CAL_ARRAY_LEN,
- 16, 2, buf, len, 0);
-
- mutex_unlock(&stlc->mutex);
-
- len = strlen(buf);
-
- return len;
-}
-
-static ssize_t stlc45xx_sysfs_store_cal_channels(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct stlc45xx *stlc = dev_get_drvdata(dev);
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- mutex_lock(&stlc->mutex);
-
- if (count != CHANNEL_CAL_ARRAY_LEN) {
- stlc45xx_error("invalid cal_channels size: %zu ", count);
- count = 0;
- goto out_unlock;
- }
-
- kfree(stlc->cal_channels);
-
- stlc->cal_channels = kmemdup(buf, count, GFP_KERNEL);
-
- if (!stlc->cal_channels) {
- stlc45xx_error("failed to allocate memory for cal_channels");
- count = 0;
- goto out_unlock;
- }
-
-out_unlock:
- mutex_unlock(&stlc->mutex);
-
- return count;
-}
-
-static ssize_t stlc45xx_sysfs_show_tx_buf(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct stlc45xx *stlc = dev_get_drvdata(dev);
- struct txbuffer *entry;
- ssize_t len = 0;
-
- stlc45xx_debug(DEBUG_FUNC, "%s()", __func__);
-
- mutex_lock(&stlc->mutex);
-
- list_for_each_entry(entry, &stlc->tx_sent, tx_list) {
- len += sprintf(buf + len, "0x%x: 0x%x-0x%x\n",
- entry->handle, entry->start,
- entry->end);
- }
-
- mutex_unlock(&stlc->mutex);
-
- return len;
-}
-
-static DEVICE_ATTR(cal_rssi, S_IRUGO | S_IWUSR,
- stlc45xx_sysfs_show_cal_rssi,
- stlc45xx_sysfs_store_cal_rssi);
-static DEVICE_ATTR(cal_channels, S_IRUGO | S_IWUSR,
- stlc45xx_sysfs_show_cal_channels,
- stlc45xx_sysfs_store_cal_channels);
-static DEVICE_ATTR(tx_buf, S_IRUGO, stlc45xx_sysfs_show_tx_buf, NULL);
-
-static void stlc45xx_spi_read(struct stlc45xx *stlc, unsigned long addr,
- void *buf, size_t len)
-{
- struct spi_transfer t[2];
- struct spi_message m;
-
- /* We first push the address */
- addr = (addr << 8) | ADDR_READ_BIT_15;
-
- spi_message_init(&m);
- memset(t, 0, sizeof(t));
-
- t[0].tx_buf = &addr;
- t[0].len = 2;
- spi_message_add_tail(&t[0], &m);
-
- t[1].rx_buf = buf;
- t[1].len = len;
- spi_message_add_tail(&t[1], &m);
-
- spi_sync(stlc->spi, &m);
-}
-
-
-static void stlc45xx_spi_write(struct stlc45xx *stlc, unsigned long addr,
- void *buf, size_t len)
-{
- struct spi_transfer t[3];
- struct spi_message m;
- u16 last_word;
-
- /* We first push the address */
- addr = addr << 8;
-
- spi_message_init(&m);
- memset(t, 0, sizeof(t));
-
- t[0].tx_buf = &addr;
- t[0].len = 2;
- spi_message_add_tail(&t[0], &m);
-
- t[1].tx_buf = buf;
- t[1].len = len;
- spi_message_add_tail(&t[1], &m);
-
- if (len % 2) {
- last_word = ((u8 *)buf)[len - 1];
-
- t[2].tx_buf = &last_word;
- t[2].len = 2;
- spi_message_add_tail(&t[2], &m);
- }
-
- spi_sync(stlc->spi, &m);
-}
-
-static u16 stlc45xx_read16(struct stlc45xx *stlc, unsigned long addr)
-{
- u16 val;
-
- stlc45xx_spi_read(stlc, addr, &val, sizeof(val));
-
- return val;
-}
-
-static u32 stlc45xx_read32(struct stlc45xx *stlc, unsigned long addr)
-{
- u32 val;
-
- stlc45xx_spi_read(stlc, addr, &val, sizeof(val));
-
- return val;
-}
-
-static void stlc45xx_write16(struct stlc45xx *stlc, unsigned long addr, u16 val)
-{
- stlc45xx_spi_write(stlc, addr, &val, sizeof(val));
-}
-
-static void stlc45xx_write32(struct stlc45xx *stlc, unsigned long addr, u32 val)
-{
- stlc45xx_spi_write(stlc, addr, &val, sizeof(val));
-}
-
-struct stlc45xx_spi_reg {
- u16 address;
- u16 length;
- char *name;
-};
-
-/* caller must hold tx_lock */
-static void stlc45xx_txbuffer_dump(struct stlc45xx *stlc)
-{
- struct txbuffer *txbuffer;
- char *buf, *pos;
- int buf_len, l, count;
-
- if (!(DEBUG_LEVEL & DEBUG_TXBUFFER))
- return;
-
- stlc45xx_debug(DEBUG_FUNC, "%s()", __func__);
-
- buf_len = 500;
- buf = kmalloc(buf_len, GFP_ATOMIC);
- if (!buf)
- return;
-
- pos = buf;
- count = 0;
-
- list_for_each_entry(txbuffer, &stlc->txbuffer, buffer_list) {
- l = snprintf(pos, buf_len, "0x%x-0x%x,",
- txbuffer->start, txbuffer->end);
- /* drop the null byte */
- pos += l;
- buf_len -= l;
- count++;
- }
-
- if (count == 0)
- *pos = '\0';
- else
- *--pos = '\0';
-
- stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: in buffer %d regions: %s",
- count, buf);
-
- kfree(buf);
-}
-
-/* caller must hold tx_lock */
-static int stlc45xx_txbuffer_find(struct stlc45xx *stlc, size_t len)
-{
- struct txbuffer *txbuffer;
- int pos;
-
- stlc45xx_debug(DEBUG_FUNC, "%s()", __func__);
-
- pos = FIRMWARE_TXBUFFER_START;
-
- if (list_empty(&stlc->txbuffer))
- goto out;
-
- /*
- * the entries in txbuffer must be in the same order as they are in
- * the real buffer
- */
- list_for_each_entry(txbuffer, &stlc->txbuffer, buffer_list) {
- if (pos + len < txbuffer->start)
- break;
- pos = ALIGN(txbuffer->end + 1, 4);
- }
-
- if (pos + len > FIRMWARE_TXBUFFER_END)
- /* not enough room */
- pos = -1;
-
- stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: find %zu B: 0x%x", len, pos);
-
-out:
- return pos;
-}
-
-static int stlc45xx_txbuffer_add(struct stlc45xx *stlc,
- struct txbuffer *txbuffer)
-{
- struct txbuffer *r, *prev = NULL;
-
- if (list_empty(&stlc->txbuffer)) {
- list_add(&txbuffer->buffer_list, &stlc->txbuffer);
- return 0;
- }
-
- r = list_first_entry(&stlc->txbuffer, struct txbuffer, buffer_list);
-
- if (txbuffer->start < r->start) {
- /* add to the beginning of the list */
- list_add(&txbuffer->buffer_list, &stlc->txbuffer);
- return 0;
- }
-
- prev = NULL;
- list_for_each_entry(r, &stlc->txbuffer, buffer_list) {
- /* skip first entry, we checked for that above */
- if (!prev) {
- prev = r;
- continue;
- }
-
- /* double-check overlaps */
- WARN_ON_ONCE(txbuffer->start >= r->start &&
- txbuffer->start <= r->end);
- WARN_ON_ONCE(txbuffer->end >= r->start &&
- txbuffer->end <= r->end);
-
- if (prev->end < txbuffer->start &&
- txbuffer->end < r->start) {
- /* insert at this spot */
- list_add_tail(&txbuffer->buffer_list, &r->buffer_list);
- return 0;
- }
-
- prev = r;
- }
-
- /* not found */
- list_add_tail(&txbuffer->buffer_list, &stlc->txbuffer);
-
- return 0;
-
-}
-
-/* caller must hold tx_lock */
-static struct txbuffer *stlc45xx_txbuffer_alloc(struct stlc45xx *stlc,
- size_t frame_len)
-{
- struct txbuffer *entry = NULL;
- size_t len;
- int pos;
-
- stlc45xx_debug(DEBUG_FUNC, "%s()", __func__);
-
- len = FIRMWARE_TXBUFFER_HEADER + frame_len + FIRMWARE_TXBUFFER_TRAILER;
- pos = stlc45xx_txbuffer_find(stlc, len);
-
- if (pos < 0)
- return NULL;
-
- WARN_ON_ONCE(pos + len > FIRMWARE_TXBUFFER_END);
- WARN_ON_ONCE(pos < FIRMWARE_TXBUFFER_START);
-
- entry = kmalloc(sizeof(*entry), GFP_ATOMIC);
- entry->start = pos;
- entry->frame_start = pos + FIRMWARE_TXBUFFER_HEADER;
- entry->end = entry->start + len - 1;
-
- stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: allocated 0x%x-0x%x",
- entry->start, entry->end);
-
- stlc45xx_txbuffer_add(stlc, entry);
-
- stlc45xx_txbuffer_dump(stlc);
-
- return entry;
-}
-
-/* caller must hold tx_lock */
-static void stlc45xx_txbuffer_free(struct stlc45xx *stlc,
- struct txbuffer *txbuffer)
-{
- stlc45xx_debug(DEBUG_FUNC, "%s()", __func__);
-
- stlc45xx_debug(DEBUG_TXBUFFER, "txbuffer: freed 0x%x-0x%x",
- txbuffer->start, txbuffer->end);
-
- list_del(&txbuffer->buffer_list);
- kfree(txbuffer);
-}
-
-
-static int stlc45xx_wait_bit(struct stlc45xx *stlc, u16 reg, u32 mask,
- u32 expected)
-{
- int i;
- char buffer[4];
-
- for (i = 0; i < 2000; i++) {
- stlc45xx_spi_read(stlc, reg, buffer, sizeof(buffer));
- if (((*(u32 *)buffer) & mask) == expected)
- return 1;
- msleep(1);
- }
-
- return 0;
-}
-
-static int stlc45xx_request_firmware(struct stlc45xx *stlc)
-{
- const struct firmware *fw;
- int ret;
-
- /* FIXME: should driver use it's own struct device? */
- ret = request_firmware(&fw, "3826.arm", &stlc->spi->dev);
-
- if (ret < 0) {
- stlc45xx_error("request_firmware() failed: %d", ret);
- return ret;
- }
-
- if (fw->size % 4) {
- stlc45xx_error("firmware size is not multiple of 32bit: %zu",
- fw->size);
- return -EILSEQ; /* Illegal byte sequence */;
- }
-
- if (fw->size < 1000) {
- stlc45xx_error("firmware is too small: %zu", fw->size);
- return -EILSEQ;
- }
-
- stlc->fw = kmemdup(fw->data, fw->size, GFP_KERNEL);
- if (!stlc->fw) {
- stlc45xx_error("could not allocate memory for firmware");
- return -ENOMEM;
- }
-
- stlc->fw_len = fw->size;
-
- release_firmware(fw);
-
- return 0;
-}
-
-static int stlc45xx_upload_firmware(struct stlc45xx *stlc)
-{
- struct s_dma_regs dma_regs;
- unsigned long fw_len, fw_addr;
- long _fw_len;
- int ret;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- if (!stlc->fw) {
- ret = stlc45xx_request_firmware(stlc);
- if (ret < 0)
- return ret;
- }
-
- /* stop the device */
- stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT,
- SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET
- | SPI_CTRL_STAT_START_HALTED);
-
- msleep(TARGET_BOOT_SLEEP);
-
- stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT,
- SPI_CTRL_STAT_HOST_OVERRIDE
- | SPI_CTRL_STAT_START_HALTED);
-
- msleep(TARGET_BOOT_SLEEP);
-
- fw_addr = FIRMWARE_ADDRESS;
- fw_len = stlc->fw_len;
-
- while (fw_len > 0) {
- _fw_len = (fw_len > SPI_MAX_PACKET_SIZE)
- ? SPI_MAX_PACKET_SIZE : fw_len;
- dma_regs.cmd = SPI_DMA_WRITE_CTRL_ENABLE;
- dma_regs.len = cpu_to_le16(_fw_len);
- dma_regs.addr = cpu_to_le32(fw_addr);
-
- fw_len -= _fw_len;
- fw_addr += _fw_len;
-
- stlc45xx_write16(stlc, SPI_ADRS_DMA_WRITE_CTRL, dma_regs.cmd);
-
- if (stlc45xx_wait_bit(stlc, SPI_ADRS_DMA_WRITE_CTRL,
- HOST_ALLOWED, HOST_ALLOWED) == 0) {
- stlc45xx_error("fw_upload not allowed to DMA write");
- return -EAGAIN;
- }
-
- stlc45xx_write16(stlc, SPI_ADRS_DMA_WRITE_LEN, dma_regs.len);
- stlc45xx_write32(stlc, SPI_ADRS_DMA_WRITE_BASE, dma_regs.addr);
-
- stlc45xx_spi_write(stlc, SPI_ADRS_DMA_DATA, stlc->fw, _fw_len);
-
- /* FIXME: I think this doesn't work if firmware is large,
- * this loop goes to second round. fw->data is not
- * increased at all! */
- }
-
- BUG_ON(fw_len != 0);
-
- /* enable host interrupts */
- stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_EN, SPI_HOST_INTS_DEFAULT);
-
- /* boot the device */
- stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT,
- SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET
- | SPI_CTRL_STAT_RAM_BOOT);
-
- msleep(TARGET_BOOT_SLEEP);
-
- stlc45xx_write16(stlc, SPI_ADRS_DEV_CTRL_STAT,
- SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT);
- msleep(TARGET_BOOT_SLEEP);
-
- return 0;
-}
-
-/* caller must hold tx_lock */
-static void stlc45xx_check_txsent(struct stlc45xx *stlc)
-{
- struct txbuffer *entry, *n;
-
- list_for_each_entry_safe(entry, n, &stlc->tx_sent, tx_list) {
- if (time_after(jiffies, entry->lifetime)) {
- if (net_ratelimit())
- stlc45xx_warning("frame 0x%x lifetime exceeded",
- entry->start);
- list_del(&entry->tx_list);
- skb_pull(entry->skb, entry->header_len);
- ieee80211_tx_status(stlc->hw, entry->skb);
- stlc45xx_txbuffer_free(stlc, entry);
- }
- }
-}
-
-static void stlc45xx_power_off(struct stlc45xx *stlc)
-{
- disable_irq(gpio_to_irq(stlc45xx_gpio_irq));
- gpio_set_value(stlc45xx_gpio_power, 0);
-}
-
-static void stlc45xx_power_on(struct stlc45xx *stlc)
-{
- gpio_set_value(stlc45xx_gpio_power, 1);
- enable_irq(gpio_to_irq(stlc45xx_gpio_irq));
-
- /*
- * need to wait a while before device can be accessed, the length
- * is just a guess
- */
- msleep(10);
-}
-
-/* caller must hold tx_lock */
-static void stlc45xx_flush_queues(struct stlc45xx *stlc)
-{
- struct txbuffer *entry;
-
- while (!list_empty(&stlc->tx_sent)) {
- entry = list_first_entry(&stlc->tx_sent,
- struct txbuffer, tx_list);
- list_del(&entry->tx_list);
- dev_kfree_skb(entry->skb);
- stlc45xx_txbuffer_free(stlc, entry);
- }
-
- WARN_ON(!list_empty(&stlc->tx_sent));
-
- while (!list_empty(&stlc->tx_pending)) {
- entry = list_first_entry(&stlc->tx_pending,
- struct txbuffer, tx_list);
- list_del(&entry->tx_list);
- dev_kfree_skb(entry->skb);
- stlc45xx_txbuffer_free(stlc, entry);
- }
-
- WARN_ON(!list_empty(&stlc->tx_pending));
- WARN_ON(!list_empty(&stlc->txbuffer));
-}
-
-static void stlc45xx_work_reset(struct work_struct *work)
-{
- struct stlc45xx *stlc = container_of(work, struct stlc45xx,
- work_reset);
-
- mutex_lock(&stlc->mutex);
-
- if (stlc->fw_state != FW_STATE_RESET)
- goto out;
-
- stlc45xx_power_off(stlc);
-
- mutex_unlock(&stlc->mutex);
-
- /* wait that all work_structs have finished, we can't hold
- * stlc->mutex to avoid deadlock */
- cancel_work_sync(&stlc->work);
-
- /* FIXME: find out good value to wait for chip power down */
- msleep(100);
-
- mutex_lock(&stlc->mutex);
-
- /* FIXME: we should gracefully handle if the state has changed
- * after re-acquiring mutex */
- WARN_ON(stlc->fw_state != FW_STATE_RESET);
-
- spin_lock_bh(&stlc->tx_lock);
- stlc45xx_flush_queues(stlc);
- spin_unlock_bh(&stlc->tx_lock);
-
- stlc->fw_state = FW_STATE_RESETTING;
-
- stlc45xx_power_on(stlc);
- stlc45xx_upload_firmware(stlc);
-
-out:
- mutex_unlock(&stlc->mutex);
-}
-
-/* caller must hold mutex */
-static void stlc45xx_reset(struct stlc45xx *stlc)
-{
- stlc45xx_warning("resetting firmware");
- stlc->fw_state = FW_STATE_RESET;
- ieee80211_stop_queues(stlc->hw);
- queue_work(stlc->hw->workqueue, &stlc->work_reset);
-}
-
-static void stlc45xx_work_tx_timeout(struct work_struct *work)
-{
- struct stlc45xx *stlc = container_of(work, struct stlc45xx,
- work_tx_timeout.work);
-
- stlc45xx_warning("tx timeout");
-
- mutex_lock(&stlc->mutex);
-
- if (stlc->fw_state != FW_STATE_READY)
- goto out;
-
- stlc45xx_reset(stlc);
-
-out:
- mutex_unlock(&stlc->mutex);
-}
-
-static void stlc45xx_int_ack(struct stlc45xx *stlc, u32 val)
-{
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_ACK, val);
-}
-
-static void stlc45xx_wakeup(struct stlc45xx *stlc)
-{
- unsigned long timeout;
- u32 ints;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- /* wake the chip */
- stlc45xx_write32(stlc, SPI_ADRS_ARM_INTERRUPTS, SPI_TARGET_INT_WAKEUP);
-
- /* And wait for the READY interrupt */
- timeout = jiffies + HZ;
-
- ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
- while (!(ints & SPI_HOST_INT_READY)) {
- if (time_after(jiffies, timeout))
- goto out;
- ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
- }
-
- stlc45xx_int_ack(stlc, SPI_HOST_INT_READY);
-
-out:
- return;
-}
-
-static void stlc45xx_sleep(struct stlc45xx *stlc)
-{
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- stlc45xx_write32(stlc, SPI_ADRS_ARM_INTERRUPTS, SPI_TARGET_INT_SLEEP);
-}
-
-static void stlc45xx_int_ready(struct stlc45xx *stlc)
-{
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- stlc45xx_write32(stlc, SPI_ADRS_HOST_INT_EN,
- SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE);
-
- switch (stlc->fw_state) {
- case FW_STATE_BOOTING:
- stlc->fw_state = FW_STATE_READY;
- complete(&stlc->fw_comp);
- break;
- case FW_STATE_RESETTING:
- stlc->fw_state = FW_STATE_READY;
-
- stlc45xx_tx_scan(stlc);
- stlc45xx_tx_setup(stlc);
- stlc45xx_tx_edcf(stlc);
-
- ieee80211_wake_queues(stlc->hw);
- break;
- default:
- break;
- }
-}
-
-static int stlc45xx_rx_txack(struct stlc45xx *stlc, struct sk_buff *skb)
-{
- struct ieee80211_tx_info *info;
- struct s_lm_control *control;
- struct s_lmo_tx *tx;
- struct txbuffer *entry;
- int found = 0;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- control = (struct s_lm_control *) skb->data;
- tx = (struct s_lmo_tx *) (control + 1);
-
- if (list_empty(&stlc->tx_sent)) {
- if (net_ratelimit())
- stlc45xx_warning("no frames waiting for "
- "acknowledgement");
- return -1;
- }
-
- list_for_each_entry(entry, &stlc->tx_sent, tx_list) {
- if (control->handle == entry->handle) {
- found = 1;
- break;
- }
- }
-
- if (!found) {
- if (net_ratelimit())
- stlc45xx_warning("couldn't find frame for tx ack 0x%x",
- control->handle);
- return -1;
- }
-
- stlc45xx_debug(DEBUG_TX, "TX ACK 0x%x", entry->handle);
-
- if (entry->status_needed) {
- info = IEEE80211_SKB_CB(entry->skb);
-
- if (!(tx->flags & LM_TX_FAILED)) {
- /* frame was acked */
- info->flags |= IEEE80211_TX_STAT_ACK;
- info->status.ack_signal = tx->rcpi / 2 - 110;
- }
-
- skb_pull(entry->skb, entry->header_len);
-
- ieee80211_tx_status(stlc->hw, entry->skb);
- }
-
- list_del(&entry->tx_list);
-
- stlc45xx_check_txsent(stlc);
- if (list_empty(&stlc->tx_sent))
- /* there are no pending frames, we can stop the tx timeout
- * timer */
- cancel_delayed_work(&stlc->work_tx_timeout);
-
- spin_lock_bh(&stlc->tx_lock);
-
- stlc45xx_txbuffer_free(stlc, entry);
-
- if (stlc->tx_queue_stopped &&
- stlc45xx_txbuffer_find(stlc, MAX_FRAME_LEN) != -1) {
- stlc45xx_debug(DEBUG_QUEUE, "room in tx buffer, waking queues");
- ieee80211_wake_queues(stlc->hw);
- stlc->tx_queue_stopped = 0;
- }
-
- spin_unlock_bh(&stlc->tx_lock);
-
- return 0;
-}
-
-static int stlc45xx_rx_control(struct stlc45xx *stlc, struct sk_buff *skb)
-{
- struct s_lm_control *control;
- int ret = 0;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- control = (struct s_lm_control *) skb->data;
-
- switch (control->oid) {
- case LM_OID_TX:
- ret = stlc45xx_rx_txack(stlc, skb);
- break;
- case LM_OID_SETUP:
- case LM_OID_SCAN:
- case LM_OID_TRAP:
- case LM_OID_EDCF:
- case LM_OID_KEYCACHE:
- case LM_OID_PSM:
- case LM_OID_STATS:
- case LM_OID_LED:
- default:
- stlc45xx_warning("unhandled rx control oid %d\n",
- control->oid);
- break;
- }
-
- dev_kfree_skb(skb);
-
- return ret;
-}
-
-/* copied from mac80211 */
-static void stlc45xx_parse_elems(u8 *start, size_t len,
- struct stlc45xx_ie_tim **tim,
- size_t *tim_len)
-{
- size_t left = len;
- u8 *pos = start;
-
- while (left >= 2) {
- u8 id, elen;
-
- id = *pos++;
- elen = *pos++;
- left -= 2;
-
- if (elen > left)
- return;
-
- switch (id) {
- case WLAN_EID_TIM:
- *tim = (struct stlc45xx_ie_tim *) pos;
- *tim_len = elen;
- break;
- default:
- break;
- }
-
- left -= elen;
- pos += elen;
- }
-}
-
-/*
- * mac80211 doesn't have support for asking frames with PS-Poll, so let's
- * implement in the driver for now. We have to add support to mac80211
- * later.
- */
-static int stlc45xx_check_more_data(struct stlc45xx *stlc, struct sk_buff *skb)
-{
- struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data;
- struct ieee80211_hdr *hdr;
- size_t len;
- u16 fc;
-
- hdr = (void *) skb->data + sizeof(*data);
- len = skb->len - sizeof(*data);
-
- /* minimum frame length is the null frame length 24 bytes */
- if (len < 24) {
- stlc45xx_warning("invalid frame length when checking for "
- "more data");
- return -EINVAL;
- }
-
- fc = le16_to_cpu(hdr->frame_control);
- if (!(fc & IEEE80211_FCTL_FROMDS))
- /* this is not from DS */
- return 0;
-
- if (compare_ether_addr(hdr->addr1, stlc->mac_addr) != 0)
- /* the frame was not for us */
- return 0;
-
- if (!(fc & IEEE80211_FCTL_MOREDATA)) {
- /* AP has no more frames buffered for us */
- stlc45xx_debug(DEBUG_PSM, "all buffered frames retrieved");
- stlc->pspolling = false;
- return 0;
- }
-
- /* MOREDATA bit is set, let's ask for a new frame from the AP */
- stlc45xx_tx_pspoll(stlc, stlc->psm);
-
- return 0;
-}
-
-/*
- * mac80211 cannot read TIM from beacons, so let's add a hack to the
- * driver. We have to add support to mac80211 later.
- */
-static int stlc45xx_rx_data_beacon(struct stlc45xx *stlc, struct sk_buff *skb)
-{
- struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data;
- size_t len = skb->len, tim_len = 0, baselen, pvbmap_len;
- struct ieee80211_mgmt *mgmt;
- struct stlc45xx_ie_tim *tim = NULL;
- int bmap_offset, index, aid_bit;
-
- mgmt = (void *) skb->data + sizeof(*data);
-
- baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
- if (baselen > len) {
- stlc45xx_warning("invalid baselen in beacon");
- return -EINVAL;
- }
-
- stlc45xx_parse_elems(mgmt->u.beacon.variable, len - baselen, &tim,
- &tim_len);
-
- if (!tim) {
- stlc45xx_warning("didn't find tim from a beacon");
- return -EINVAL;
- }
-
- bmap_offset = tim->bmap_control & 0xfe;
- index = stlc->aid / 8 - bmap_offset;
-
- pvbmap_len = tim_len - 3;
- if (index > pvbmap_len)
- return -EINVAL;
-
- aid_bit = !!(tim->pvbmap[index] & (1 << stlc->aid % 8));
-
- stlc45xx_debug(DEBUG_PSM, "fc 0x%x duration %d seq %d dtim %u "
- "bmap_control 0x%x aid_bit %d",
- mgmt->frame_control, mgmt->duration, mgmt->seq_ctrl >> 4,
- tim->dtim_count, tim->bmap_control, aid_bit);
-
- if (!aid_bit)
- return 0;
-
- stlc->pspolling = true;
- stlc45xx_tx_pspoll(stlc, stlc->psm);
-
- return 0;
-}
-
-static int stlc45xx_rx_data(struct stlc45xx *stlc, struct sk_buff *skb)
-{
- struct ieee80211_rx_status status;
- struct s_lm_data_in *data = (struct s_lm_data_in *) skb->data;
- int align = 0;
- u8 *p, align_len;
- u16 len;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- if (stlc->psm) {
- if (data->flags & LM_IN_BEACON)
- stlc45xx_rx_data_beacon(stlc, skb);
- else if (stlc->pspolling && (data->flags & LM_IN_DATA))
- stlc45xx_check_more_data(stlc, skb);
- }
-
- memset(&status, 0, sizeof(status));
-
- status.freq = data->frequency;
- status.signal = data->rcpi / 2 - 110;
-
- /* let's assume that maximum rcpi value is 140 (= 35 dBm) */
- status.qual = data->rcpi * 100 / 140;
-
- status.band = IEEE80211_BAND_2GHZ;
-
- /*
- * FIXME: this gives warning from __ieee80211_rx()
- *
- * status.rate_idx = data->rate;
- */
-
- len = data->length;
-
- if (data->flags & LM_FLAG_ALIGN)
- align = 1;
-
- skb_pull(skb, sizeof(*data));
-
- if (align) {
- p = skb->data;
- align_len = *p;
- skb_pull(skb, align_len);
- }
-
- skb_trim(skb, len);
-
- stlc45xx_debug(DEBUG_RX, "rx data 0x%p %d B", skb->data, skb->len);
- stlc45xx_dump(DEBUG_RX_CONTENT, skb->data, skb->len);
-
- memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
- ieee80211_rx(stlc->hw, skb);
-
- return 0;
-}
-
-
-
-static int stlc45xx_rx(struct stlc45xx *stlc)
-{
- struct s_lm_control *control;
- struct sk_buff *skb;
- int ret;
- u16 len;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- stlc45xx_wakeup(stlc);
-
- /* dummy read to flush SPI DMA controller bug */
- stlc45xx_read16(stlc, SPI_ADRS_GEN_PURP_1);
-
- len = stlc45xx_read16(stlc, SPI_ADRS_DMA_DATA);
-
- if (len == 0) {
- stlc45xx_warning("rx request of zero bytes");
- return 0;
- }
-
- skb = dev_alloc_skb(len);
- if (!skb) {
- stlc45xx_warning("could not alloc skb");
- return 0;
- }
-
- stlc45xx_spi_read(stlc, SPI_ADRS_DMA_DATA, skb_put(skb, len), len);
-
- stlc45xx_sleep(stlc);
-
- stlc45xx_debug(DEBUG_RX, "rx frame 0x%p %d B", skb->data, skb->len);
- stlc45xx_dump(DEBUG_RX_CONTENT, skb->data, skb->len);
-
- control = (struct s_lm_control *) skb->data;
-
- if (control->flags & LM_FLAG_CONTROL)
- ret = stlc45xx_rx_control(stlc, skb);
- else
- ret = stlc45xx_rx_data(stlc, skb);
-
- return ret;
-}
-
-
-static irqreturn_t stlc45xx_interrupt(int irq, void *config)
-{
- struct spi_device *spi = config;
- struct stlc45xx *stlc = dev_get_drvdata(&spi->dev);
-
- stlc45xx_debug(DEBUG_IRQ, "IRQ");
-
- queue_work(stlc->hw->workqueue, &stlc->work);
-
- return IRQ_HANDLED;
-}
-
-static int stlc45xx_tx_frame(struct stlc45xx *stlc, u32 address,
- void *buf, size_t len)
-{
- struct s_dma_regs dma_regs;
- unsigned long timeout;
- int ret = 0;
- u32 ints;
-
- stlc->tx_frames++;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- stlc45xx_debug(DEBUG_TX, "tx frame 0x%p %zu B", buf, len);
- stlc45xx_dump(DEBUG_TX_CONTENT, buf, len);
-
- stlc45xx_wakeup(stlc);
-
- dma_regs.cmd = SPI_DMA_WRITE_CTRL_ENABLE;
- dma_regs.len = cpu_to_le16(len);
- dma_regs.addr = cpu_to_le32(address);
-
- stlc45xx_spi_write(stlc, SPI_ADRS_DMA_WRITE_CTRL, &dma_regs,
- sizeof(dma_regs));
-
- stlc45xx_spi_write(stlc, SPI_ADRS_DMA_DATA, buf, len);
-
- timeout = jiffies + 2 * HZ;
- ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
- while (!(ints & SPI_HOST_INT_WR_READY)) {
- if (time_after(jiffies, timeout)) {
- stlc45xx_warning("WR_READY timeout");
- ret = -1;
- goto out;
- }
- ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
- }
-
- stlc45xx_int_ack(stlc, SPI_HOST_INT_WR_READY);
-
- stlc45xx_sleep(stlc);
-
-out:
- return ret;
-}
-
-static int stlc45xx_wq_tx(struct stlc45xx *stlc)
-{
- struct txbuffer *entry;
- int ret = 0;
-
- spin_lock_bh(&stlc->tx_lock);
-
- while (!list_empty(&stlc->tx_pending)) {
- entry = list_entry(stlc->tx_pending.next,
- struct txbuffer, tx_list);
-
- list_del_init(&entry->tx_list);
-
- spin_unlock_bh(&stlc->tx_lock);
-
- ret = stlc45xx_tx_frame(stlc, entry->frame_start,
- entry->skb->data, entry->skb->len);
-
- spin_lock_bh(&stlc->tx_lock);
-
- if (ret < 0) {
- /* frame transfer to firmware buffer failed */
- /* FIXME: report this to mac80211 */
- dev_kfree_skb(entry->skb);
- stlc45xx_txbuffer_free(stlc, entry);
- goto out;
- }
-
- list_add(&entry->tx_list, &stlc->tx_sent);
- queue_delayed_work(stlc->hw->workqueue,
- &stlc->work_tx_timeout,
- msecs_to_jiffies(TX_TIMEOUT));
- }
-
-out:
- spin_unlock_bh(&stlc->tx_lock);
- return ret;
-}
-
-static void stlc45xx_work(struct work_struct *work)
-{
- struct stlc45xx *stlc = container_of(work, struct stlc45xx, work);
- u32 ints;
- int ret;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- mutex_lock(&stlc->mutex);
-
- if (stlc->fw_state == FW_STATE_OFF &&
- stlc->fw_state == FW_STATE_RESET)
- goto out;
-
- ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
- stlc45xx_debug(DEBUG_BH, "begin host_ints 0x%08x", ints);
-
- if (ints & SPI_HOST_INT_READY) {
- stlc45xx_int_ready(stlc);
- stlc45xx_int_ack(stlc, SPI_HOST_INT_READY);
- }
-
- if (stlc->fw_state != FW_STATE_READY)
- goto out;
-
- if (ints & SPI_HOST_INT_UPDATE) {
- stlc45xx_int_ack(stlc, SPI_HOST_INT_UPDATE);
- ret = stlc45xx_rx(stlc);
- if (ret < 0) {
- stlc45xx_reset(stlc);
- goto out;
- }
- }
- if (ints & SPI_HOST_INT_SW_UPDATE) {
- stlc45xx_int_ack(stlc, SPI_HOST_INT_SW_UPDATE);
- ret = stlc45xx_rx(stlc);
- if (ret < 0) {
- stlc45xx_reset(stlc);
- goto out;
- }
- }
-
- ret = stlc45xx_wq_tx(stlc);
- if (ret < 0) {
- stlc45xx_reset(stlc);
- goto out;
- }
-
- ints = stlc45xx_read32(stlc, SPI_ADRS_HOST_INTERRUPTS);
- stlc45xx_debug(DEBUG_BH, "end host_ints 0x%08x", ints);
-
-out:
- mutex_unlock(&stlc->mutex);
-}
-
-static void stlc45xx_tx_edcf(struct stlc45xx *stlc)
-{
- struct s_lm_control *control;
- struct s_lmo_edcf *edcf;
- size_t len, edcf_len;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- edcf_len = sizeof(*edcf);
- len = sizeof(*control) + edcf_len;
- control = kzalloc(len, GFP_KERNEL);
- edcf = (struct s_lmo_edcf *) (control + 1);
-
- control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET;
- control->length = edcf_len;
- control->oid = LM_OID_EDCF;
-
- edcf->slottime = 0x14;
- edcf->sifs = 10;
- edcf->eofpad = 6;
- edcf->maxburst = 1500;
-
- edcf->queues[0].aifs = 2;
- edcf->queues[0].pad0 = 1;
- edcf->queues[0].cwmin = 3;
- edcf->queues[0].cwmax = 7;
- edcf->queues[0].txop = 47;
- edcf->queues[1].aifs = 2;
- edcf->queues[1].pad0 = 0;
- edcf->queues[1].cwmin = 7;
- edcf->queues[1].cwmax = 15;
- edcf->queues[1].txop = 94;
- edcf->queues[2].aifs = 3;
- edcf->queues[2].pad0 = 0;
- edcf->queues[2].cwmin = 15;
- edcf->queues[2].cwmax = 1023;
- edcf->queues[2].txop = 0;
- edcf->queues[3].aifs = 7;
- edcf->queues[3].pad0 = 0;
- edcf->queues[3].cwmin = 15;
- edcf->queues[3].cwmax = 1023;
- edcf->queues[3].txop = 0;
- edcf->queues[4].aifs = 13;
- edcf->queues[4].pad0 = 99;
- edcf->queues[4].cwmin = 3437;
- edcf->queues[4].cwmax = 512;
- edcf->queues[4].txop = 12;
- edcf->queues[5].aifs = 142;
- edcf->queues[5].pad0 = 109;
- edcf->queues[5].cwmin = 8756;
- edcf->queues[5].cwmax = 6;
- edcf->queues[5].txop = 0;
- edcf->queues[6].aifs = 4;
- edcf->queues[6].pad0 = 0;
- edcf->queues[6].cwmin = 0;
- edcf->queues[6].cwmax = 58705;
- edcf->queues[6].txop = 25716;
- edcf->queues[7].aifs = 0;
- edcf->queues[7].pad0 = 0;
- edcf->queues[7].cwmin = 0;
- edcf->queues[7].cwmax = 0;
- edcf->queues[7].txop = 0;
-
- stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len);
-
- kfree(control);
-}
-
-static void stlc45xx_tx_setup(struct stlc45xx *stlc)
-{
- struct s_lm_control *control;
- struct s_lmo_setup *setup;
- size_t len, setup_len;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- setup_len = sizeof(*setup);
- len = sizeof(*control) + setup_len;
- control = kzalloc(len, GFP_KERNEL);
- setup = (struct s_lmo_setup *) (control + 1);
-
- control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET;
- control->length = setup_len;
- control->oid = LM_OID_SETUP;
-
- setup->flags = LM_SETUP_INFRA;
- setup->antenna = 2;
- setup->rx_align = 0;
- setup->rx_buffer = FIRMWARE_RXBUFFER_START;
- setup->rx_mtu = FIRMWARE_MTU;
- setup->frontend = 5;
- setup->timeout = 0;
- setup->truncate = 48896;
- setup->bratemask = 0xffffffff;
- setup->ref_clock = 644245094;
- setup->lpf_bandwidth = 65535;
- setup->osc_start_delay = 65535;
-
- memcpy(setup->macaddr, stlc->mac_addr, ETH_ALEN);
- memcpy(setup->bssid, stlc->bssid, ETH_ALEN);
-
- stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len);
-
- kfree(control);
-}
-
-static void stlc45xx_tx_scan(struct stlc45xx *stlc)
-{
- struct s_lm_control *control;
- struct s_lmo_scan *scan;
- size_t len, scan_len;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- scan_len = sizeof(*scan);
- len = sizeof(*control) + scan_len;
- control = kzalloc(len, GFP_KERNEL);
- scan = (struct s_lmo_scan *) (control + 1);
-
- control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET;
- control->length = scan_len;
- control->oid = LM_OID_SCAN;
-
- scan->flags = LM_SCAN_EXIT;
- scan->bratemask = 0x15f;
- scan->aloft[0] = 3;
- scan->aloft[1] = 3;
- scan->aloft[2] = 1;
- scan->aloft[3] = 0;
- scan->aloft[4] = 0;
- scan->aloft[5] = 0;
- scan->aloft[6] = 0;
- scan->aloft[7] = 0;
-
- memcpy(&scan->rssical, &stlc->cal_rssi[(stlc->channel - 1) *
- RSSI_CAL_LEN],
- RSSI_CAL_LEN);
- memcpy(&scan->channel, &stlc->cal_channels[(stlc->channel - 1) *
- CHANNEL_CAL_LEN],
- CHANNEL_CAL_LEN);
-
- stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len);
-
- kfree(control);
-}
-
-/*
- * caller must hold mutex
- */
-static int stlc45xx_tx_pspoll(struct stlc45xx *stlc, bool powersave)
-{
- struct ieee80211_hdr *pspoll;
- int payload_len, padding, i;
- struct s_lm_data_out *data;
- struct txbuffer *entry;
- struct sk_buff *skb;
- char *payload;
- u16 fc;
-
- skb = dev_alloc_skb(stlc->hw->extra_tx_headroom + 16);
- if (!skb) {
- stlc45xx_warning("failed to allocate pspoll frame");
- return -ENOMEM;
- }
- skb_reserve(skb, stlc->hw->extra_tx_headroom);
-
- pspoll = (struct ieee80211_hdr *) skb_put(skb, 16);
- memset(pspoll, 0, 16);
- fc = IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL;
- if (powersave)
- fc |= IEEE80211_FCTL_PM;
- pspoll->frame_control = cpu_to_le16(fc);
- pspoll->duration_id = cpu_to_le16(stlc->aid);
-
- /* aid in PS-Poll has its two MSBs each set to 1 */
- pspoll->duration_id |= cpu_to_le16(1 << 15) | cpu_to_le16(1 << 14);
-
- memcpy(pspoll->addr1, stlc->bssid, ETH_ALEN);
- memcpy(pspoll->addr2, stlc->mac_addr, ETH_ALEN);
-
- stlc45xx_debug(DEBUG_PSM, "sending PS-Poll frame to %pM (powersave %d, "
- "fc 0x%x, aid %d)", pspoll->addr1,
- powersave, fc, stlc->aid);
-
- spin_lock_bh(&stlc->tx_lock);
-
- entry = stlc45xx_txbuffer_alloc(stlc, skb->len);
-
- spin_unlock_bh(&stlc->tx_lock);
-
- if (!entry) {
- /*
- * The queue should be stopped before the firmware buffer
- * is full, so firmware buffer should always have enough
- * space.
- *
- * But I'm too lazy and omit it for now.
- */
- if (net_ratelimit())
- stlc45xx_warning("firmware tx buffer full is full "
- "for null frame");
- return -ENOSPC;
- }
-
- payload = skb->data;
- payload_len = skb->len;
- padding = (int) (skb->data - sizeof(*data)) & 3;
- entry->header_len = sizeof(*data) + padding;
-
- entry->skb = skb;
- entry->status_needed = false;
- entry->handle = (u32) skb;
- entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME);
-
- stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B "
- "padding %d header_len %d)",
- entry->handle, payload, payload_len, padding,
- entry->header_len);
- stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len);
-
- data = (struct s_lm_data_out *) skb_push(skb, entry->header_len);
-
- memset(data, 0, entry->header_len);
-
- if (padding)
- data->flags = LM_FLAG_ALIGN;
-
- data->flags = LM_OUT_BURST;
- data->length = payload_len;
- data->handle = entry->handle;
- data->aid = 1;
- data->rts_retries = 7;
- data->retries = 7;
- data->aloft_ctrl = 0;
- data->crypt_offset = 58;
- data->keytype = 0;
- data->keylen = 0;
- data->queue = LM_QUEUE_DATA3;
- data->backlog = 32;
- data->antenna = 2;
- data->cts = 3;
- data->power = 127;
-
- for (i = 0; i < 8; i++)
- data->aloft[i] = 0;
-
- /*
- * check if there's enough space in tx buffer
- *
- * FIXME: ignored for now
- */
-
- stlc45xx_tx_frame(stlc, entry->start, skb->data, skb->len);
-
- list_add(&entry->tx_list, &stlc->tx_sent);
-
- return 0;
-}
-
-/*
- * caller must hold mutex
- *
- * shamelessly stolen from mac80211/ieee80211_send_nullfunc
- */
-static int stlc45xx_tx_nullfunc(struct stlc45xx *stlc, bool powersave)
-{
- struct ieee80211_hdr *nullfunc;
- int payload_len, padding, i;
- struct s_lm_data_out *data;
- struct txbuffer *entry;
- struct sk_buff *skb;
- char *payload;
- u16 fc;
-
- skb = dev_alloc_skb(stlc->hw->extra_tx_headroom + 24);
- if (!skb) {
- stlc45xx_warning("failed to allocate buffer for null frame\n");
- return -ENOMEM;
- }
- skb_reserve(skb, stlc->hw->extra_tx_headroom);
-
- nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24);
- memset(nullfunc, 0, 24);
- fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC |
- IEEE80211_FCTL_TODS;
-
- if (powersave)
- fc |= IEEE80211_FCTL_PM;
-
- nullfunc->frame_control = cpu_to_le16(fc);
- memcpy(nullfunc->addr1, stlc->bssid, ETH_ALEN);
- memcpy(nullfunc->addr2, stlc->mac_addr, ETH_ALEN);
- memcpy(nullfunc->addr3, stlc->bssid, ETH_ALEN);
-
- stlc45xx_debug(DEBUG_PSM, "sending Null frame to %pM (powersave %d, "
- "fc 0x%x)", nullfunc->addr1, powersave, fc);
-
- spin_lock_bh(&stlc->tx_lock);
-
- entry = stlc45xx_txbuffer_alloc(stlc, skb->len);
-
- spin_unlock_bh(&stlc->tx_lock);
-
- if (!entry) {
- /*
- * The queue should be stopped before the firmware buffer
- * is full, so firmware buffer should always have enough
- * space.
- *
- * But I'm too lazy and omit it for now.
- */
- if (net_ratelimit())
- stlc45xx_warning("firmware tx buffer full is full "
- "for null frame");
- return -ENOSPC;
- }
-
- payload = skb->data;
- payload_len = skb->len;
- padding = (int) (skb->data - sizeof(*data)) & 3;
- entry->header_len = sizeof(*data) + padding;
-
- entry->skb = skb;
- entry->status_needed = false;
- entry->handle = (u32) skb;
- entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME);
-
- stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B "
- "padding %d header_len %d)",
- entry->handle, payload, payload_len, padding,
- entry->header_len);
- stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len);
-
- data = (struct s_lm_data_out *) skb_push(skb, entry->header_len);
-
- memset(data, 0, entry->header_len);
-
- if (padding)
- data->flags = LM_FLAG_ALIGN;
-
- data->flags = LM_OUT_BURST;
- data->length = payload_len;
- data->handle = entry->handle;
- data->aid = 1;
- data->rts_retries = 7;
- data->retries = 7;
- data->aloft_ctrl = 0;
- data->crypt_offset = 58;
- data->keytype = 0;
- data->keylen = 0;
- data->queue = LM_QUEUE_DATA3;
- data->backlog = 32;
- data->antenna = 2;
- data->cts = 3;
- data->power = 127;
-
- for (i = 0; i < 8; i++)
- data->aloft[i] = 0;
-
- /*
- * check if there's enough space in tx buffer
- *
- * FIXME: ignored for now
- */
-
- stlc45xx_tx_frame(stlc, entry->start, skb->data, skb->len);
-
- list_add(&entry->tx_list, &stlc->tx_sent);
-
- return 0;
-}
-
-/* caller must hold mutex */
-static void stlc45xx_tx_psm(struct stlc45xx *stlc, bool enable)
-{
- struct s_lm_control *control;
- struct s_lmo_psm *psm;
- size_t len, psm_len;
-
- WARN_ON(!stlc->associated);
- WARN_ON(stlc->aid < 1);
- WARN_ON(stlc->aid > 2007);
-
- psm_len = sizeof(*psm);
- len = sizeof(*control) + psm_len;
- control = kzalloc(len, GFP_KERNEL);
- psm = (struct s_lmo_psm *) (control + 1);
-
- control->flags = LM_FLAG_CONTROL | LM_CTRL_OPSET;
- control->length = psm_len;
- control->oid = LM_OID_PSM;
-
- if (enable)
- psm->flags |= LM_PSM;
-
- psm->aid = stlc->aid;
-
- psm->beacon_rcpi_skip_max = 60;
-
- psm->intervals[0].interval = 1;
- psm->intervals[0].periods = 1;
- psm->intervals[1].interval = 1;
- psm->intervals[1].periods = 1;
- psm->intervals[2].interval = 1;
- psm->intervals[2].periods = 1;
- psm->intervals[3].interval = 1;
- psm->intervals[3].periods = 1;
-
- psm->nr = 0;
- psm->exclude[0] = 0;
-
- stlc45xx_debug(DEBUG_PSM, "sending LM_OID_PSM (aid %d, interval %d)",
- psm->aid, psm->intervals[0].interval);
-
- stlc45xx_tx_frame(stlc, FIRMWARE_CONFIG_START, control, len);
-
- kfree(control);
-}
-
-static int stlc45xx_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
- struct stlc45xx *stlc = hw->priv;
- struct ieee80211_tx_info *info;
- struct ieee80211_rate *rate;
- int payload_len, padding, i;
- struct s_lm_data_out *data;
- struct txbuffer *entry;
- char *payload;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- spin_lock_bh(&stlc->tx_lock);
-
- entry = stlc45xx_txbuffer_alloc(stlc, skb->len);
- if (!entry) {
- /* the queue should be stopped before the firmware buffer
- * is full, so firmware buffer should always have enough
- * space */
- if (net_ratelimit())
- stlc45xx_warning("firmware buffer full");
- spin_unlock_bh(&stlc->tx_lock);
- return NETDEV_TX_BUSY;
- }
-
- info = IEEE80211_SKB_CB(skb);
-
- payload = skb->data;
- payload_len = skb->len;
- padding = (int) (skb->data - sizeof(*data)) & 3;
- entry->header_len = sizeof(*data) + padding;
-
- entry->skb = skb;
- entry->status_needed = true;
- entry->handle = (u32) skb;
- entry->lifetime = jiffies + msecs_to_jiffies(TX_FRAME_LIFETIME);
-
- stlc45xx_debug(DEBUG_TX, "tx data 0x%x (0x%p payload %d B "
- "padding %d header_len %d)",
- entry->handle, payload, payload_len, padding,
- entry->header_len);
- stlc45xx_dump(DEBUG_TX_CONTENT, payload, payload_len);
-
- data = (struct s_lm_data_out *) skb_push(skb, entry->header_len);
-
- memset(data, 0, entry->header_len);
-
- if (padding)
- data->flags = LM_FLAG_ALIGN;
-
- data->flags = LM_OUT_BURST;
- data->length = payload_len;
- data->handle = entry->handle;
- data->aid = 1;
- data->rts_retries = 7;
- data->retries = 7;
- data->aloft_ctrl = 0;
- data->crypt_offset = 58;
- data->keytype = 0;
- data->keylen = 0;
- data->queue = 2;
- data->backlog = 32;
- data->antenna = 2;
- data->cts = 3;
- data->power = 127;
-
- for (i = 0; i < 8; i++) {
- rate = ieee80211_get_tx_rate(stlc->hw, info);
- data->aloft[i] = rate->hw_value;
- }
-
- list_add_tail(&entry->tx_list, &stlc->tx_pending);
-
- /* check if there's enough space in tx buffer */
- if (stlc45xx_txbuffer_find(stlc, MAX_FRAME_LEN) == -1) {
- stlc45xx_debug(DEBUG_QUEUE, "tx buffer full, stopping queues");
- stlc->tx_queue_stopped = 1;
- ieee80211_stop_queues(stlc->hw);
- }
-
- queue_work(stlc->hw->workqueue, &stlc->work);
-
- spin_unlock_bh(&stlc->tx_lock);
-
- return NETDEV_TX_OK;
-}
-
-static int stlc45xx_op_start(struct ieee80211_hw *hw)
-{
- struct stlc45xx *stlc = hw->priv;
- unsigned long timeout;
- int ret = 0;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- mutex_lock(&stlc->mutex);
-
- stlc->fw_state = FW_STATE_BOOTING;
- stlc->channel = 1;
-
- stlc45xx_power_on(stlc);
-
- ret = stlc45xx_upload_firmware(stlc);
- if (ret < 0) {
- stlc45xx_power_off(stlc);
- goto out_unlock;
- }
-
- stlc->tx_queue_stopped = 0;
-
- mutex_unlock(&stlc->mutex);
-
- timeout = msecs_to_jiffies(2000);
- timeout = wait_for_completion_interruptible_timeout(&stlc->fw_comp,
- timeout);
- if (!timeout) {
- stlc45xx_error("firmware boot failed");
- stlc45xx_power_off(stlc);
- ret = -1;
- goto out;
- }
-
- stlc45xx_debug(DEBUG_BOOT, "firmware booted");
-
- /* FIXME: should we take mutex just after wait_for_completion()? */
- mutex_lock(&stlc->mutex);
-
- WARN_ON(stlc->fw_state != FW_STATE_READY);
-
-out_unlock:
- mutex_unlock(&stlc->mutex);
-
-out:
- return ret;
-}
-
-static void stlc45xx_op_stop(struct ieee80211_hw *hw)
-{
- struct stlc45xx *stlc = hw->priv;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- mutex_lock(&stlc->mutex);
-
- WARN_ON(stlc->fw_state != FW_STATE_READY);
-
- stlc45xx_power_off(stlc);
-
- /* FIXME: make sure that all work_structs have completed */
-
- spin_lock_bh(&stlc->tx_lock);
- stlc45xx_flush_queues(stlc);
- spin_unlock_bh(&stlc->tx_lock);
-
- stlc->fw_state = FW_STATE_OFF;
-
- mutex_unlock(&stlc->mutex);
-}
-
-static int stlc45xx_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
-{
- struct stlc45xx *stlc = hw->priv;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- switch (conf->type) {
- case NL80211_IFTYPE_STATION:
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- memcpy(stlc->mac_addr, conf->mac_addr, ETH_ALEN);
-
- return 0;
-}
-
-static void stlc45xx_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_if_init_conf *conf)
-{
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-}
-
-static int stlc45xx_op_config(struct ieee80211_hw *hw, u32 changed)
-{
- struct stlc45xx *stlc = hw->priv;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- mutex_lock(&stlc->mutex);
-
- stlc->channel = hw->conf.channel->hw_value;
- stlc45xx_tx_scan(stlc);
- stlc45xx_tx_setup(stlc);
- stlc45xx_tx_edcf(stlc);
-
- if ((hw->conf.flags & IEEE80211_CONF_PS) != stlc->psm) {
- stlc->psm = hw->conf.flags & IEEE80211_CONF_PS;
- if (stlc->associated) {
- stlc45xx_tx_psm(stlc, stlc->psm);
- stlc45xx_tx_nullfunc(stlc, stlc->psm);
- }
- }
-
- mutex_unlock(&stlc->mutex);
-
- return 0;
-}
-
-static void stlc45xx_op_configure_filter(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags,
- int mc_count,
- struct dev_addr_list *mc_list)
-{
- *total_flags = 0;
-}
-
-static void stlc45xx_op_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *info,
- u32 changed)
-{
- struct stlc45xx *stlc = hw->priv;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
- mutex_lock(&stlc->mutex);
-
- memcpy(stlc->bssid, info->bssid, ETH_ALEN);
- stlc45xx_tx_setup(stlc);
-
- mutex_unlock(&stlc->mutex);
-
- if (changed & BSS_CHANGED_ASSOC) {
- stlc->associated = info->assoc;
- if (info->assoc)
- stlc->aid = info->aid;
- else
- stlc->aid = -1;
-
- if (stlc->psm) {
- stlc45xx_tx_psm(stlc, stlc->psm);
- stlc45xx_tx_nullfunc(stlc, stlc->psm);
- }
- }
-}
-
-
-/* can't be const, mac80211 writes to this */
-static struct ieee80211_rate stlc45xx_rates[] = {
- { .bitrate = 10, .hw_value = 0, .hw_value_short = 0, },
- { .bitrate = 20, .hw_value = 1, .hw_value_short = 1, },
- { .bitrate = 55, .hw_value = 2, .hw_value_short = 2, },
- { .bitrate = 110, .hw_value = 3, .hw_value_short = 3, },
- { .bitrate = 60, .hw_value = 4, .hw_value_short = 4, },
- { .bitrate = 90, .hw_value = 5, .hw_value_short = 5, },
- { .bitrate = 120, .hw_value = 6, .hw_value_short = 6, },
- { .bitrate = 180, .hw_value = 7, .hw_value_short = 7, },
- { .bitrate = 240, .hw_value = 8, .hw_value_short = 8, },
- { .bitrate = 360, .hw_value = 9, .hw_value_short = 9, },
- { .bitrate = 480, .hw_value = 10, .hw_value_short = 10, },
- { .bitrate = 540, .hw_value = 11, .hw_value_short = 11, },
-};
-
-/* can't be const, mac80211 writes to this */
-static struct ieee80211_channel stlc45xx_channels[] = {
- { .hw_value = 1, .center_freq = 2412},
- { .hw_value = 2, .center_freq = 2417},
- { .hw_value = 3, .center_freq = 2422},
- { .hw_value = 4, .center_freq = 2427},
- { .hw_value = 5, .center_freq = 2432},
- { .hw_value = 6, .center_freq = 2437},
- { .hw_value = 7, .center_freq = 2442},
- { .hw_value = 8, .center_freq = 2447},
- { .hw_value = 9, .center_freq = 2452},
- { .hw_value = 10, .center_freq = 2457},
- { .hw_value = 11, .center_freq = 2462},
- { .hw_value = 12, .center_freq = 2467},
- { .hw_value = 13, .center_freq = 2472},
-};
-
-/* can't be const, mac80211 writes to this */
-static struct ieee80211_supported_band stlc45xx_band_2ghz = {
- .channels = stlc45xx_channels,
- .n_channels = ARRAY_SIZE(stlc45xx_channels),
- .bitrates = stlc45xx_rates,
- .n_bitrates = ARRAY_SIZE(stlc45xx_rates),
-};
-
-static const struct ieee80211_ops stlc45xx_ops = {
- .start = stlc45xx_op_start,
- .stop = stlc45xx_op_stop,
- .add_interface = stlc45xx_op_add_interface,
- .remove_interface = stlc45xx_op_remove_interface,
- .config = stlc45xx_op_config,
- .configure_filter = stlc45xx_op_configure_filter,
- .tx = stlc45xx_op_tx,
- .bss_info_changed = stlc45xx_op_bss_info_changed,
-};
-
-static int stlc45xx_register_mac80211(struct stlc45xx *stlc)
-{
- /* FIXME: SET_IEEE80211_PERM_ADDR() requires default_mac_addr
- to be non-const for some strange reason */
- static u8 default_mac_addr[ETH_ALEN] = {
- 0x00, 0x02, 0xee, 0xc0, 0xff, 0xee
- };
- int ret;
-
- SET_IEEE80211_PERM_ADDR(stlc->hw, default_mac_addr);
-
- ret = ieee80211_register_hw(stlc->hw);
- if (ret) {
- stlc45xx_error("unable to register mac80211 hw: %d", ret);
- return ret;
- }
-
- return 0;
-}
-
-static void stlc45xx_device_release(struct device *dev)
-{
-
-}
-
-static struct platform_device stlc45xx_device = {
- .name = "stlc45xx",
- .id = -1,
-
- /* device model insists to have a release function */
- .dev = {
- .release = stlc45xx_device_release,
- },
-};
-
-static int __devinit stlc45xx_probe(struct spi_device *spi)
-{
- struct stlc45xx *stlc;
- struct ieee80211_hw *hw;
- int ret;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- /* mac80211 alloc */
- hw = ieee80211_alloc_hw(sizeof(*stlc), &stlc45xx_ops);
- if (!hw) {
- stlc45xx_error("could not alloc ieee80211_hw");
- ret = -ENOMEM;
- goto out;
- }
-
- /* mac80211 clears hw->priv */
- stlc = hw->priv;
-
- stlc->hw = hw;
- dev_set_drvdata(&spi->dev, stlc);
- stlc->spi = spi;
-
- spi->bits_per_word = 16;
- spi->max_speed_hz = 24000000;
-
- ret = spi_setup(spi);
- if (ret < 0)
- stlc45xx_error("spi_setup failed");
-
- ret = gpio_request(stlc45xx_gpio_power, "stlc45xx power");
- if (ret < 0) {
- stlc45xx_error("power GPIO request failed: %d", ret);
- return ret;
- }
-
- ret = gpio_request(stlc45xx_gpio_irq, "stlc45xx irq");
- if (ret < 0) {
- stlc45xx_error("irq GPIO request failed: %d", ret);
- goto out;
- }
-
- gpio_direction_output(stlc45xx_gpio_power, 0);
- gpio_direction_input(stlc45xx_gpio_irq);
-
- ret = request_irq(gpio_to_irq(stlc45xx_gpio_irq),
- stlc45xx_interrupt, IRQF_DISABLED, "stlc45xx",
- stlc->spi);
- if (ret < 0)
- /* FIXME: handle the error */
- stlc45xx_error("request_irq() failed");
-
- set_irq_type(gpio_to_irq(stlc45xx_gpio_irq),
- IRQ_TYPE_EDGE_RISING);
-
- disable_irq(gpio_to_irq(stlc45xx_gpio_irq));
-
- ret = platform_device_register(&stlc45xx_device);
- if (ret) {
- stlc45xx_error("Couldn't register wlan_omap device.");
- return ret;
- }
- dev_set_drvdata(&stlc45xx_device.dev, stlc);
-
- INIT_WORK(&stlc->work, stlc45xx_work);
- INIT_WORK(&stlc->work_reset, stlc45xx_work_reset);
- INIT_DELAYED_WORK(&stlc->work_tx_timeout, stlc45xx_work_tx_timeout);
- mutex_init(&stlc->mutex);
- init_completion(&stlc->fw_comp);
- spin_lock_init(&stlc->tx_lock);
- INIT_LIST_HEAD(&stlc->txbuffer);
- INIT_LIST_HEAD(&stlc->tx_pending);
- INIT_LIST_HEAD(&stlc->tx_sent);
-
- hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
- IEEE80211_HW_SIGNAL_DBM |
- IEEE80211_HW_NOISE_DBM;
- /* four bytes for padding */
- hw->extra_tx_headroom = sizeof(struct s_lm_data_out) + 4;
-
- /* unit us */
- hw->channel_change_time = 1000;
-
- hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
- hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &stlc45xx_band_2ghz;
-
- SET_IEEE80211_DEV(hw, &spi->dev);
-
- BUILD_BUG_ON(sizeof(default_cal_rssi) != RSSI_CAL_ARRAY_LEN);
- BUILD_BUG_ON(sizeof(default_cal_channels) != CHANNEL_CAL_ARRAY_LEN);
-
- stlc->cal_rssi = kmemdup(default_cal_rssi, RSSI_CAL_ARRAY_LEN,
- GFP_KERNEL);
- stlc->cal_channels = kmemdup(default_cal_channels,
- CHANNEL_CAL_ARRAY_LEN,
- GFP_KERNEL);
-
- ret = device_create_file(&stlc45xx_device.dev, &dev_attr_cal_rssi);
- if (ret < 0) {
- stlc45xx_error("failed to create sysfs file cal_rssi");
- goto out;
- }
-
- ret = device_create_file(&stlc45xx_device.dev, &dev_attr_cal_channels);
- if (ret < 0) {
- stlc45xx_error("failed to create sysfs file cal_channels");
- goto out;
- }
-
- ret = device_create_file(&stlc45xx_device.dev, &dev_attr_tx_buf);
- if (ret < 0) {
- stlc45xx_error("failed to create sysfs file tx_buf");
- goto out;
- }
-
- ret = stlc45xx_register_mac80211(stlc);
- if (ret < 0)
- goto out;
-
- stlc45xx_info("v" DRIVER_VERSION " loaded");
-
- stlc45xx_info("config buffer 0x%x-0x%x",
- FIRMWARE_CONFIG_START, FIRMWARE_CONFIG_END);
- stlc45xx_info("tx 0x%x-0x%x, rx 0x%x-0x%x",
- FIRMWARE_TXBUFFER_START, FIRMWARE_TXBUFFER_END,
- FIRMWARE_RXBUFFER_START, FIRMWARE_RXBUFFER_END);
-
-out:
- return ret;
-}
-
-static int __devexit stlc45xx_remove(struct spi_device *spi)
-{
- struct stlc45xx *stlc = dev_get_drvdata(&spi->dev);
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- platform_device_unregister(&stlc45xx_device);
-
- ieee80211_unregister_hw(stlc->hw);
-
- free_irq(gpio_to_irq(stlc45xx_gpio_irq), spi);
-
- gpio_free(stlc45xx_gpio_power);
- gpio_free(stlc45xx_gpio_irq);
-
- /* FIXME: free cal_channels and cal_rssi? */
-
- kfree(stlc->fw);
-
- mutex_destroy(&stlc->mutex);
-
- /* frees also stlc */
- ieee80211_free_hw(stlc->hw);
- stlc = NULL;
-
- return 0;
-}
-
-
-static struct spi_driver stlc45xx_spi_driver = {
- .driver = {
- /* use cx3110x name because board-n800.c uses that for the
- * SPI port */
- .name = "cx3110x",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
-
- .probe = stlc45xx_probe,
- .remove = __devexit_p(stlc45xx_remove),
-};
-
-static int __init stlc45xx_init(void)
-{
- int ret;
-
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- ret = spi_register_driver(&stlc45xx_spi_driver);
- if (ret < 0) {
- stlc45xx_error("failed to register SPI driver: %d", ret);
- goto out;
- }
-
-out:
- return ret;
-}
-
-static void __exit stlc45xx_exit(void)
-{
- stlc45xx_debug(DEBUG_FUNC, "%s", __func__);
-
- spi_unregister_driver(&stlc45xx_spi_driver);
-
- stlc45xx_info("unloaded");
-}
-
-module_init(stlc45xx_init);
-module_exit(stlc45xx_exit);
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Kalle Valo <kalle.valo@nokia.com>");
-MODULE_ALIAS("spi:cx3110x");
diff --git a/drivers/staging/stlc45xx/stlc45xx.h b/drivers/staging/stlc45xx/stlc45xx.h
deleted file mode 100644
index ac96bbbde79f..000000000000
--- a/drivers/staging/stlc45xx/stlc45xx.h
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * This file is part of stlc45xx
- *
- * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Contact: Kalle Valo <kalle.valo@nokia.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/mutex.h>
-#include <linux/list.h>
-#include <net/mac80211.h>
-
-#include "stlc45xx_lmac.h"
-
-#define DRIVER_NAME "stlc45xx"
-#define DRIVER_VERSION "0.1.3"
-
-#define DRIVER_PREFIX DRIVER_NAME ": "
-
-enum {
- DEBUG_NONE = 0,
- DEBUG_FUNC = 1 << 0,
- DEBUG_IRQ = 1 << 1,
- DEBUG_BH = 1 << 2,
- DEBUG_RX = 1 << 3,
- DEBUG_RX_CONTENT = 1 << 5,
- DEBUG_TX = 1 << 6,
- DEBUG_TX_CONTENT = 1 << 8,
- DEBUG_TXBUFFER = 1 << 9,
- DEBUG_QUEUE = 1 << 10,
- DEBUG_BOOT = 1 << 11,
- DEBUG_PSM = 1 << 12,
- DEBUG_ALL = ~0,
-};
-
-#define DEBUG_LEVEL DEBUG_NONE
-/* #define DEBUG_LEVEL DEBUG_ALL */
-/* #define DEBUG_LEVEL (DEBUG_TX | DEBUG_RX | DEBUG_IRQ) */
-/* #define DEBUG_LEVEL (DEBUG_TX | DEBUG_MEMREGION | DEBUG_QUEUE) */
-/* #define DEBUG_LEVEL (DEBUG_MEMREGION | DEBUG_QUEUE) */
-
-#define stlc45xx_error(fmt, arg...) \
- printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg)
-
-#define stlc45xx_warning(fmt, arg...) \
- printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg)
-
-#define stlc45xx_info(fmt, arg...) \
- printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg)
-
-#define stlc45xx_debug(level, fmt, arg...) \
- do { \
- if (level & DEBUG_LEVEL) \
- printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \
- } while (0)
-
-#define stlc45xx_dump(level, buf, len) \
- do { \
- if (level & DEBUG_LEVEL) \
- print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, \
- 16, 1, buf, len, 1); \
- } while (0)
-
-#define MAC2STR(a) ((a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5])
-#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
-
-/* Bit 15 is read/write bit; ON = READ, OFF = WRITE */
-#define ADDR_READ_BIT_15 0x8000
-
-#define SPI_ADRS_ARM_INTERRUPTS 0x00
-#define SPI_ADRS_ARM_INT_EN 0x04
-
-#define SPI_ADRS_HOST_INTERRUPTS 0x08
-#define SPI_ADRS_HOST_INT_EN 0x0c
-#define SPI_ADRS_HOST_INT_ACK 0x10
-
-#define SPI_ADRS_GEN_PURP_1 0x14
-#define SPI_ADRS_GEN_PURP_2 0x18
-
-/* high word */
-#define SPI_ADRS_DEV_CTRL_STAT 0x26
-
-#define SPI_ADRS_DMA_DATA 0x28
-
-#define SPI_ADRS_DMA_WRITE_CTRL 0x2c
-#define SPI_ADRS_DMA_WRITE_LEN 0x2e
-#define SPI_ADRS_DMA_WRITE_BASE 0x30
-
-#define SPI_ADRS_DMA_READ_CTRL 0x34
-#define SPI_ADRS_DMA_READ_LEN 0x36
-#define SPI_ADRS_DMA_READ_BASE 0x38
-
-#define SPI_CTRL_STAT_HOST_OVERRIDE 0x8000
-#define SPI_CTRL_STAT_START_HALTED 0x4000
-#define SPI_CTRL_STAT_RAM_BOOT 0x2000
-#define SPI_CTRL_STAT_HOST_RESET 0x1000
-#define SPI_CTRL_STAT_HOST_CPU_EN 0x0800
-
-#define SPI_DMA_WRITE_CTRL_ENABLE 0x0001
-#define SPI_DMA_READ_CTRL_ENABLE 0x0001
-#define HOST_ALLOWED (1 << 7)
-
-#define FIRMWARE_ADDRESS 0x20000
-
-#define SPI_TIMEOUT 100 /* msec */
-
-#define SPI_MAX_TX_PACKETS 32
-
-#define SPI_MAX_PACKET_SIZE 32767
-
-#define SPI_TARGET_INT_WAKEUP 0x00000001
-#define SPI_TARGET_INT_SLEEP 0x00000002
-#define SPI_TARGET_INT_RDDONE 0x00000004
-
-#define SPI_TARGET_INT_CTS 0x00004000
-#define SPI_TARGET_INT_DR 0x00008000
-
-#define SPI_HOST_INT_READY 0x00000001
-#define SPI_HOST_INT_WR_READY 0x00000002
-#define SPI_HOST_INT_SW_UPDATE 0x00000004
-#define SPI_HOST_INT_UPDATE 0x10000000
-
-/* clear to send */
-#define SPI_HOST_INT_CTS 0x00004000
-
-/* data ready */
-#define SPI_HOST_INT_DR 0x00008000
-
-#define SPI_HOST_INTS_DEFAULT \
- (SPI_HOST_INT_READY | SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE)
-
-#define TARGET_BOOT_SLEEP 50
-
-/* The firmware buffer is divided into three areas:
- *
- * o config area (for control commands)
- * o tx buffer
- * o rx buffer
- */
-#define FIRMWARE_BUFFER_START 0x20200
-#define FIRMWARE_BUFFER_END 0x27c60
-#define FIRMWARE_BUFFER_LEN (FIRMWARE_BUFFER_END - FIRMWARE_BUFFER_START)
-#define FIRMWARE_MTU 3240
-#define FIRMWARE_CONFIG_PAYLOAD_LEN 1024
-#define FIRMWARE_CONFIG_START FIRMWARE_BUFFER_START
-#define FIRMWARE_CONFIG_LEN (sizeof(struct s_lm_control) + \
- FIRMWARE_CONFIG_PAYLOAD_LEN)
-#define FIRMWARE_CONFIG_END (FIRMWARE_CONFIG_START + FIRMWARE_CONFIG_LEN - 1)
-#define FIRMWARE_RXBUFFER_LEN (5 * FIRMWARE_MTU + 1024)
-#define FIRMWARE_RXBUFFER_START (FIRMWARE_BUFFER_END - FIRMWARE_RXBUFFER_LEN)
-#define FIRMWARE_RXBUFFER_END (FIRMWARE_RXBUFFER_START + \
- FIRMWARE_RXBUFFER_LEN - 1)
-#define FIRMWARE_TXBUFFER_START (FIRMWARE_BUFFER_START + FIRMWARE_CONFIG_LEN)
-#define FIRMWARE_TXBUFFER_LEN (FIRMWARE_BUFFER_LEN - FIRMWARE_CONFIG_LEN - \
- FIRMWARE_RXBUFFER_LEN)
-#define FIRMWARE_TXBUFFER_END (FIRMWARE_TXBUFFER_START + \
- FIRMWARE_TXBUFFER_LEN - 1)
-
-#define FIRMWARE_TXBUFFER_HEADER 100
-#define FIRMWARE_TXBUFFER_TRAILER 4
-
-/* FIXME: come up with a proper value */
-#define MAX_FRAME_LEN 2500
-
-/* unit is ms */
-#define TX_FRAME_LIFETIME 2000
-#define TX_TIMEOUT 4000
-
-#define SUPPORTED_CHANNELS 13
-
-/* FIXME */
-/* #define CHANNEL_CAL_LEN offsetof(struct s_lmo_scan, bratemask) - \ */
-/* offsetof(struct s_lmo_scan, channel) */
-#define CHANNEL_CAL_LEN 292
-#define CHANNEL_CAL_ARRAY_LEN (SUPPORTED_CHANNELS * CHANNEL_CAL_LEN)
-/* FIXME */
-/* #define RSSI_CAL_LEN sizeof(struct s_lmo_scan) - \ */
-/* offsetof(struct s_lmo_scan, rssical) */
-#define RSSI_CAL_LEN 8
-#define RSSI_CAL_ARRAY_LEN (SUPPORTED_CHANNELS * RSSI_CAL_LEN)
-
-struct s_dma_regs {
- unsigned short cmd;
- unsigned short len;
- unsigned long addr;
-};
-
-struct stlc45xx_ie_tim {
- u8 dtim_count;
- u8 dtim_period;
- u8 bmap_control;
- u8 pvbmap[251];
-};
-
-struct txbuffer {
- /* can be removed when switched to skb queue */
- struct list_head tx_list;
-
- struct list_head buffer_list;
-
- int start;
- int frame_start;
- int end;
-
- struct sk_buff *skb;
- u32 handle;
-
- bool status_needed;
-
- int header_len;
-
- /* unit jiffies */
- unsigned long lifetime;
-};
-
-enum fw_state {
- FW_STATE_OFF,
- FW_STATE_BOOTING,
- FW_STATE_READY,
- FW_STATE_RESET,
- FW_STATE_RESETTING,
-};
-
-struct stlc45xx {
- struct ieee80211_hw *hw;
- struct spi_device *spi;
- struct work_struct work;
- struct work_struct work_reset;
- struct delayed_work work_tx_timeout;
- struct mutex mutex;
- struct completion fw_comp;
-
-
- u8 bssid[ETH_ALEN];
- u8 mac_addr[ETH_ALEN];
- int channel;
-
- u8 *cal_rssi;
- u8 *cal_channels;
-
- enum fw_state fw_state;
-
- spinlock_t tx_lock;
-
- /* protected by tx_lock */
- struct list_head txbuffer;
-
- /* protected by tx_lock */
- struct list_head tx_pending;
-
- /* protected by tx_lock */
- int tx_queue_stopped;
-
- /* protected by mutex */
- struct list_head tx_sent;
-
- int tx_frames;
-
- u8 *fw;
- int fw_len;
-
- bool psm;
- bool associated;
- int aid;
- bool pspolling;
-};
-
-
diff --git a/drivers/staging/stlc45xx/stlc45xx_lmac.h b/drivers/staging/stlc45xx/stlc45xx_lmac.h
deleted file mode 100644
index af5db801347f..000000000000
--- a/drivers/staging/stlc45xx/stlc45xx_lmac.h
+++ /dev/null
@@ -1,434 +0,0 @@
-/************************************************************************
-* This is the LMAC API interface header file for STLC4560. *
-* Copyright (C) 2007 Conexant Systems, Inc. *
-* This program is free software; you can redistribute it and/or *
-* modify it under the terms of the GNU General Public License *
-* as published by the Free Software Foundation; either version 2 *
-* of the License, or (at your option) any later version. *
-* *
-* 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, see <http://www.gnu.org/licenses/>.*
-*************************************************************************/
-
-#ifndef __lmac_h__
-#define __lmac_h__
-
-#define LM_TOP_VARIANT 0x0506
-#define LM_BOTTOM_VARIANT 0x0506
-
-/*
- * LMAC - UMAC interface definition:
- */
-
-#define LM_FLAG_CONTROL 0x8000
-#define LM_FLAG_ALIGN 0x4000
-
-#define LM_CTRL_OPSET 0x0001
-
-#define LM_OUT_PROMISC 0x0001
-#define LM_OUT_TIMESTAMP 0x0002
-#define LM_OUT_SEQNR 0x0004
-#define LM_OUT_BURST 0x0010
-#define LM_OUT_NOCANCEL 0x0020
-#define LM_OUT_CLEARTIM 0x0040
-#define LM_OUT_HITCHHIKE 0x0080
-#define LM_OUT_COMPRESS 0x0100
-#define LM_OUT_CONCAT 0x0200
-#define LM_OUT_PCS_ACCEPT 0x0400
-#define LM_OUT_WAITEOSP 0x0800
-
-
-#define LM_ALOFT_SP 0x10
-#define LM_ALOFT_CTS 0x20
-#define LM_ALOFT_RTS 0x40
-#define LM_ALOFT_MASK 0x1f
-#define LM_ALOFT_RATE 0x0f
-
-#define LM_IN_FCS_GOOD 0x0001
-#define LM_IN_MATCH_MAC 0x0002
-#define LM_IN_MCBC 0x0004
-#define LM_IN_BEACON 0x0008
-#define LM_IN_MATCH_BSS 0x0010
-#define LM_IN_BCAST_BSS 0x0020
-#define LM_IN_DATA 0x0040
-#define LM_IN_TRUNCATED 0x0080
-
-#define LM_IN_TRANSPARENT 0x0200
-
-#define LM_QUEUE_BEACON 0
-#define LM_QUEUE_SCAN 1
-#define LM_QUEUE_MGT 2
-#define LM_QUEUE_MCBC 3
-#define LM_QUEUE_DATA 4
-#define LM_QUEUE_DATA0 4
-#define LM_QUEUE_DATA1 5
-#define LM_QUEUE_DATA2 6
-#define LM_QUEUE_DATA3 7
-
-#define LM_SETUP_INFRA 0x0001
-#define LM_SETUP_IBSS 0x0002
-#define LM_SETUP_TRANSPARENT 0x0008
-#define LM_SETUP_PROMISCUOUS 0x0010
-#define LM_SETUP_HIBERNATE 0x0020
-#define LM_SETUP_NOACK 0x0040
-#define LM_SETUP_RX_DISABLED 0x0080
-
-#define LM_ANTENNA_0 0
-#define LM_ANTENNA_1 1
-#define LM_ANTENNA_DIVERSITY 2
-
-#define LM_TX_FAILED 0x0001
-#define LM_TX_PSM 0x0002
-#define LM_TX_PSM_CANCELLED 0x0004
-
-#define LM_SCAN_EXIT 0x0001
-#define LM_SCAN_TRAP 0x0002
-#define LM_SCAN_ACTIVE 0x0004
-#define LM_SCAN_FILTER 0x0008
-
-#define LM_PSM 0x0001
-#define LM_PSM_DTIM 0x0002
-#define LM_PSM_MCBC 0x0004
-#define LM_PSM_CHECKSUM 0x0008
-#define LM_PSM_SKIP_MORE_DATA 0x0010
-#define LM_PSM_BEACON_TIMEOUT 0x0020
-#define LM_PSM_HFOSLEEP 0x0040
-#define LM_PSM_AUTOSWITCH_SLEEP 0x0080
-#define LM_PSM_LPIT 0x0100
-#define LM_PSM_BF_UCAST_SKIP 0x0200
-#define LM_PSM_BF_MCAST_SKIP 0x0400
-
-/* hfosleep */
-#define LM_PSM_SLEEP_OPTION_MASK (LM_PSM_AUTOSWITCH_SLEEP | LM_PSM_HFOSLEEP)
-#define LM_PSM_SLEEP_OPTION_SHIFT 6
-/* hfosleepend */
-#define LM_PSM_BF_OPTION_MASK (LM_PSM_BF_MCAST_SKIP | LM_PSM_BF_UCAST_SKIP)
-#define LM_PSM_BF_OPTION_SHIFT 9
-
-
-#define LM_PRIVACC_WEP 0x01
-#define LM_PRIVACC_TKIP 0x02
-#define LM_PRIVACC_MICHAEL 0x04
-#define LM_PRIVACC_CCX_KP 0x08
-#define LM_PRIVACC_CCX_MIC 0x10
-#define LM_PRIVACC_AES_CCMP 0x20
-
-/* size of s_lm_descr in words */
-#define LM_DESCR_SIZE_WORDS 11
-
-#ifndef __ASSEMBLER__
-
-enum {
- LM_MODE_CLIENT = 0,
- LM_MODE_AP
-};
-
-struct s_lm_descr {
- uint16_t modes;
- uint16_t flags;
- uint32_t buffer_start;
- uint32_t buffer_end;
- uint8_t header;
- uint8_t trailer;
- uint8_t tx_queues;
- uint8_t tx_depth;
- uint8_t privacy;
- uint8_t rx_keycache;
- uint8_t tim_size;
- uint8_t pad1;
- uint8_t rates[16];
- uint32_t link;
- uint16_t mtu;
-};
-
-
-struct s_lm_control {
- uint16_t flags;
- uint16_t length;
- uint32_t handle;
- uint16_t oid;
- uint16_t pad;
- /* uint8_t data[]; */
-};
-
-enum {
- LM_PRIV_NONE = 0,
- LM_PRIV_WEP,
- LM_PRIV_TKIP,
- LM_PRIV_TKIPMICHAEL,
- LM_PRIV_CCX_WEPMIC,
- LM_PRIV_CCX_KPMIC,
- LM_PRIV_CCX_KP,
- LM_PRIV_AES_CCMP
-};
-
-enum {
- LM_DECRYPT_NONE,
- LM_DECRYPT_OK,
- LM_DECRYPT_NOKEY,
- LM_DECRYPT_NOMICHAEL,
- LM_DECRYPT_NOCKIPMIC,
- LM_DECRYPT_FAIL_WEP,
- LM_DECRYPT_FAIL_TKIP,
- LM_DECRYPT_FAIL_MICHAEL,
- LM_DECRYPT_FAIL_CKIPKP,
- LM_DECRYPT_FAIL_CKIPMIC,
- LM_DECRYPT_FAIL_AESCCMP
-};
-
-struct s_lm_data_out {
- uint16_t flags;
- uint16_t length;
- uint32_t handle;
- uint16_t aid;
- uint8_t rts_retries;
- uint8_t retries;
- uint8_t aloft[8];
- uint8_t aloft_ctrl;
- uint8_t crypt_offset;
- uint8_t keytype;
- uint8_t keylen;
- uint8_t key[16];
- uint8_t queue;
- uint8_t backlog;
- uint16_t durations[4];
- uint8_t antenna;
- uint8_t cts;
- int16_t power;
- uint8_t pad[2];
- /*uint8_t data[];*/
-};
-
-#define LM_RCPI_INVALID (0xff)
-
-struct s_lm_data_in {
- uint16_t flags;
- uint16_t length;
- uint16_t frequency;
- uint8_t antenna;
- uint8_t rate;
- uint8_t rcpi;
- uint8_t sq;
- uint8_t decrypt;
- uint8_t rssi_raw;
- uint32_t clock[2];
- /*uint8_t data[];*/
-};
-
-union u_lm_data {
- struct s_lm_data_out out;
- struct s_lm_data_in in;
-};
-
-enum {
- LM_OID_SETUP = 0,
- LM_OID_SCAN = 1,
- LM_OID_TRAP = 2,
- LM_OID_EDCF = 3,
- LM_OID_KEYCACHE = 4,
- LM_OID_PSM = 6,
- LM_OID_TXCANCEL = 7,
- LM_OID_TX = 8,
- LM_OID_BURST = 9,
- LM_OID_STATS = 10,
- LM_OID_LED = 13,
- LM_OID_TIMER = 15,
- LM_OID_NAV = 20,
- LM_OID_PCS = 22,
- LM_OID_BT_BALANCER = 28,
- LM_OID_GROUP_ADDRESS_TABLE = 30,
- LM_OID_ARPTABLE = 31,
- LM_OID_BT_OPTIONS = 35
-};
-
-enum {
- LM_FRONTEND_UNKNOWN = 0,
- LM_FRONTEND_DUETTE3,
- LM_FRONTEND_DUETTE2,
- LM_FRONTEND_FRISBEE,
- LM_FRONTEND_CROSSBOW,
- LM_FRONTEND_LONGBOW
-};
-
-
-#define INVALID_LPF_BANDWIDTH 0xffff
-#define INVALID_OSC_START_DELAY 0xffff
-
-struct s_lmo_setup {
- uint16_t flags;
- uint8_t macaddr[6];
- uint8_t bssid[6];
- uint8_t antenna;
- uint8_t rx_align;
- uint32_t rx_buffer;
- uint16_t rx_mtu;
- uint16_t frontend;
- uint16_t timeout;
- uint16_t truncate;
- uint32_t bratemask;
- uint8_t sbss_offset;
- uint8_t mcast_window;
- uint8_t rx_rssi_threshold;
- uint8_t rx_ed_threshold;
- uint32_t ref_clock;
- uint16_t lpf_bandwidth;
- uint16_t osc_start_delay;
-};
-
-
-struct s_lmo_scan {
- uint16_t flags;
- uint16_t dwell;
- uint8_t channel[292];
- uint32_t bratemask;
- uint8_t aloft[8];
- uint8_t rssical[8];
-};
-
-
-enum {
- LM_TRAP_SCAN = 0,
- LM_TRAP_TIMER,
- LM_TRAP_BEACON_TX,
- LM_TRAP_FAA_RADIO_ON,
- LM_TRAP_FAA_RADIO_OFF,
- LM_TRAP_RADAR,
- LM_TRAP_NO_BEACON,
- LM_TRAP_TBTT,
- LM_TRAP_SCO_ENTER,
- LM_TRAP_SCO_EXIT
-};
-
-struct s_lmo_trap {
- uint16_t event;
- uint16_t frequency;
-};
-
-struct s_lmo_timer {
- uint32_t interval;
-};
-
-struct s_lmo_nav {
- uint32_t period;
-};
-
-
-struct s_lmo_edcf_queue;
-
-struct s_lmo_edcf {
- uint8_t flags;
- uint8_t slottime;
- uint8_t sifs;
- uint8_t eofpad;
- struct s_lmo_edcf_queue {
- uint8_t aifs;
- uint8_t pad0;
- uint16_t cwmin;
- uint16_t cwmax;
- uint16_t txop;
- } queues[8];
- uint8_t mapping[4];
- uint16_t maxburst;
- uint16_t round_trip_delay;
-};
-
-struct s_lmo_keycache {
- uint8_t entry;
- uint8_t keyid;
- uint8_t address[6];
- uint8_t pad[2];
- uint8_t keytype;
- uint8_t keylen;
- uint8_t key[24];
-};
-
-
-struct s_lm_interval;
-
-struct s_lmo_psm {
- uint16_t flags;
- uint16_t aid;
- struct s_lm_interval {
- uint16_t interval;
- uint16_t periods;
- } intervals[4];
- /* uint16_t pad; */
- uint8_t beacon_rcpi_skip_max;
- uint8_t rcpi_delta_threshold;
- uint8_t nr;
- uint8_t exclude[1];
-};
-
-#define MC_FILTER_ADDRESS_NUM 4
-
-struct s_lmo_group_address_table {
- uint16_t filter_enable;
- uint16_t num_address;
- uint8_t macaddr_list[MC_FILTER_ADDRESS_NUM][6];
-};
-
-struct s_lmo_txcancel {
- uint32_t address[1];
-};
-
-
-struct s_lmo_tx {
- uint8_t flags;
- uint8_t retries;
- uint8_t rcpi;
- uint8_t sq;
- uint16_t seqctrl;
- uint8_t antenna;
- uint8_t pad;
-};
-
-struct s_lmo_burst {
- uint8_t flags;
- uint8_t queue;
- uint8_t backlog;
- uint8_t pad;
- uint16_t durations[32];
-};
-
-struct s_lmo_stats {
- uint32_t valid;
- uint32_t fcs;
- uint32_t abort;
- uint32_t phyabort;
- uint32_t rts_success;
- uint32_t rts_fail;
- uint32_t timestamp;
- uint32_t time_tx;
- uint32_t noisefloor;
- uint32_t sample_noise[8];
- uint32_t sample_cca;
- uint32_t sample_tx;
-};
-
-
-struct s_lmo_led {
- uint16_t flags;
- uint16_t mask[2];
- uint16_t delay/*[2]*/;
-};
-
-
-struct s_lmo_bt_balancer {
- uint16_t prio_thresh;
- uint16_t acl_thresh;
-};
-
-
-struct s_lmo_arp_table {
- uint16_t filter_enable;
- uint32_t ipaddr;
-};
-
-#endif /* __ASSEMBLER__ */
-
-#endif /* __lmac_h__ */
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
index 7f96bcaf1c60..05186110c029 100644
--- a/drivers/staging/vt6656/main_usb.c
+++ b/drivers/staging/vt6656/main_usb.c
@@ -1332,7 +1332,6 @@ device_release_WPADEV(pDevice);
free_netdev(pDevice->dev);
}
- kfree(pDevice);
DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO "device_disconnect3.. \n");
}
diff --git a/drivers/staging/winbond/Kconfig b/drivers/staging/winbond/Kconfig
index 940460c39f36..132671d96d0d 100644
--- a/drivers/staging/winbond/Kconfig
+++ b/drivers/staging/winbond/Kconfig
@@ -1,6 +1,6 @@
config W35UND
tristate "IS89C35 WLAN USB driver"
- depends on MAC80211 && WLAN_80211 && USB && EXPERIMENTAL
+ depends on MAC80211 && WLAN && USB && EXPERIMENTAL
default n
---help---
This is highly experimental driver for Winbond WIFI card.
diff --git a/drivers/staging/wlan-ng/Kconfig b/drivers/staging/wlan-ng/Kconfig
index 9959b658c8cf..f44294b0d8dc 100644
--- a/drivers/staging/wlan-ng/Kconfig
+++ b/drivers/staging/wlan-ng/Kconfig
@@ -1,6 +1,6 @@
config PRISM2_USB
tristate "Prism2.5/3 USB driver"
- depends on WLAN_80211 && USB && WIRELESS_EXT
+ depends on WLAN && USB && WIRELESS_EXT
default n
---help---
This is the wlan-ng prism 2.5/3 USB driver for a wide range of
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 33351312327f..a18e3c5dd82e 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -223,6 +223,7 @@ config USB_OTG
config USB_GADGET_PXA25X
boolean "PXA 25x or IXP 4xx"
depends on (ARCH_PXA && PXA25x) || ARCH_IXP4XX
+ select USB_OTG_UTILS
help
Intel's PXA 25x series XScale ARM-5TE processors include
an integrated full speed USB 1.1 device controller. The
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index 42a74b8a0bb8..fa3d142ba64d 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -2139,7 +2139,7 @@ static int fsl_proc_read(char *page, char **start, off_t off, int count,
static void fsl_udc_release(struct device *dev)
{
complete(udc_controller->done);
- dma_free_coherent(dev, udc_controller->ep_qh_size,
+ dma_free_coherent(dev->parent, udc_controller->ep_qh_size,
udc_controller->ep_qh, udc_controller->ep_qh_dma);
kfree(udc_controller);
}
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 749b53742828..e33d36256350 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -1003,19 +1003,20 @@ static void r8a66597_check_syssts(struct r8a66597 *r8a66597, int port,
if (syssts == SE0) {
r8a66597_write(r8a66597, ~ATTCH, get_intsts_reg(port));
r8a66597_bset(r8a66597, ATTCHE, get_intenb_reg(port));
- return;
- }
+ } else {
+ if (syssts == FS_JSTS)
+ r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
+ else if (syssts == LS_JSTS)
+ r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
- if (syssts == FS_JSTS)
- r8a66597_bset(r8a66597, HSE, get_syscfg_reg(port));
- else if (syssts == LS_JSTS)
- r8a66597_bclr(r8a66597, HSE, get_syscfg_reg(port));
+ r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
+ r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
- r8a66597_write(r8a66597, ~DTCH, get_intsts_reg(port));
- r8a66597_bset(r8a66597, DTCHE, get_intenb_reg(port));
+ if (r8a66597->bus_suspended)
+ usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
+ }
- if (r8a66597->bus_suspended)
- usb_hcd_resume_root_hub(r8a66597_to_hcd(r8a66597));
+ usb_hcd_poll_rh_status(r8a66597_to_hcd(r8a66597));
}
/* this function must be called with interrupt disabled */
@@ -1024,6 +1025,8 @@ static void r8a66597_usb_connect(struct r8a66597 *r8a66597, int port)
u16 speed = get_rh_usb_speed(r8a66597, port);
struct r8a66597_root_hub *rh = &r8a66597->root_hub[port];
+ rh->port &= ~((1 << USB_PORT_FEAT_HIGHSPEED) |
+ (1 << USB_PORT_FEAT_LOWSPEED));
if (speed == HSMODE)
rh->port |= (1 << USB_PORT_FEAT_HIGHSPEED);
else if (speed == LSMODE)
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 65d96b214f95..cd44c68954df 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -315,6 +315,9 @@ static int option_resume(struct usb_serial *serial);
#define QISDA_PRODUCT_H20_4515 0x4515
#define QISDA_PRODUCT_H20_4519 0x4519
+/* TLAYTECH PRODUCTS */
+#define TLAYTECH_VENDOR_ID 0x20B9
+#define TLAYTECH_PRODUCT_TEU800 0x1682
/* TOSHIBA PRODUCTS */
#define TOSHIBA_VENDOR_ID 0x0930
@@ -593,6 +596,7 @@ static struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(ALINK_VENDOR_ID, ALINK_PRODUCT_3GU, 0xff, 0xff, 0xff) },
{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X060S) },
{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
+ { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 45883988a005..5019325ba25d 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -296,7 +296,6 @@ struct sierra_port_private {
int dsr_state;
int dcd_state;
int ri_state;
-
unsigned int opened:1;
};
@@ -306,6 +305,8 @@ static int sierra_send_setup(struct usb_serial_port *port)
struct sierra_port_private *portdata;
__u16 interface = 0;
int val = 0;
+ int do_send = 0;
+ int retval;
dev_dbg(&port->dev, "%s\n", __func__);
@@ -324,10 +325,7 @@ static int sierra_send_setup(struct usb_serial_port *port)
*/
if (port->interrupt_in_urb) {
/* send control message */
- return usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 0x22, 0x21, val, interface,
- NULL, 0, USB_CTRL_SET_TIMEOUT);
+ do_send = 1;
}
}
@@ -339,12 +337,18 @@ static int sierra_send_setup(struct usb_serial_port *port)
interface = 1;
else if (port->bulk_out_endpointAddress == 5)
interface = 2;
- return usb_control_msg(serial->dev,
- usb_rcvctrlpipe(serial->dev, 0),
- 0x22, 0x21, val, interface,
- NULL, 0, USB_CTRL_SET_TIMEOUT);
+
+ do_send = 1;
}
- return 0;
+ if (!do_send)
+ return 0;
+
+ usb_autopm_get_interface(serial->interface);
+ retval = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
+ 0x22, 0x21, val, interface, NULL, 0, USB_CTRL_SET_TIMEOUT);
+ usb_autopm_put_interface(serial->interface);
+
+ return retval;
}
static void sierra_set_termios(struct tty_struct *tty,
@@ -773,8 +777,11 @@ static void sierra_close(struct usb_serial_port *port)
if (serial->dev) {
mutex_lock(&serial->disc_mutex);
- if (!serial->disconnected)
+ if (!serial->disconnected) {
+ serial->interface->needs_remote_wakeup = 0;
+ usb_autopm_get_interface(serial->interface);
sierra_send_setup(port);
+ }
mutex_unlock(&serial->disc_mutex);
spin_lock_irq(&intfdata->susp_lock);
portdata->opened = 0;
@@ -788,8 +795,6 @@ static void sierra_close(struct usb_serial_port *port)
sierra_release_urb(portdata->in_urbs[i]);
portdata->in_urbs[i] = NULL;
}
- usb_autopm_get_interface(serial->interface);
- serial->interface->needs_remote_wakeup = 0;
}
}
@@ -827,6 +832,8 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port)
if (err) {
/* get rid of everything as in close */
sierra_close(port);
+ /* restore balance for autopm */
+ usb_autopm_put_interface(serial->interface);
return err;
}
sierra_send_setup(port);
@@ -915,7 +922,7 @@ static void sierra_release(struct usb_serial *serial)
#ifdef CONFIG_PM
static void stop_read_write_urbs(struct usb_serial *serial)
{
- int i, j;
+ int i;
struct usb_serial_port *port;
struct sierra_port_private *portdata;
@@ -923,8 +930,7 @@ static void stop_read_write_urbs(struct usb_serial *serial)
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
portdata = usb_get_serial_port_data(port);
- for (j = 0; j < N_IN_URB; j++)
- usb_kill_urb(portdata->in_urbs[j]);
+ sierra_stop_rx_urbs(port);
usb_kill_anchored_urbs(&portdata->active);
}
}
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index 200c22f55130..9dd588042880 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -19,7 +19,6 @@
*/
//#define DEBUG
#include <linux/virtio.h>
-#include <linux/virtio_ids.h>
#include <linux/virtio_balloon.h>
#include <linux/swap.h>
#include <linux/kthread.h>
@@ -248,7 +247,7 @@ out:
return err;
}
-static void virtballoon_remove(struct virtio_device *vdev)
+static void __devexit virtballoon_remove(struct virtio_device *vdev)
{
struct virtio_balloon *vb = vdev->priv;
diff --git a/drivers/virtio/virtio_pci.c b/drivers/virtio/virtio_pci.c
index 4a1f1ebff7bf..28d9cf7cf72f 100644
--- a/drivers/virtio/virtio_pci.c
+++ b/drivers/virtio/virtio_pci.c
@@ -530,19 +530,22 @@ static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs,
err = PTR_ERR(vqs[i]);
goto error_find;
}
+
+ if (!vp_dev->per_vq_vectors || msix_vec == VIRTIO_MSI_NO_VECTOR)
+ continue;
+
/* allocate per-vq irq if available and necessary */
- if (vp_dev->per_vq_vectors) {
- snprintf(vp_dev->msix_names[msix_vec],
- sizeof *vp_dev->msix_names,
- "%s-%s",
- dev_name(&vp_dev->vdev.dev), names[i]);
- err = request_irq(msix_vec, vring_interrupt, 0,
- vp_dev->msix_names[msix_vec],
- vqs[i]);
- if (err) {
- vp_del_vq(vqs[i]);
- goto error_find;
- }
+ snprintf(vp_dev->msix_names[msix_vec],
+ sizeof *vp_dev->msix_names,
+ "%s-%s",
+ dev_name(&vp_dev->vdev.dev), names[i]);
+ err = request_irq(vp_dev->msix_entries[msix_vec].vector,
+ vring_interrupt, 0,
+ vp_dev->msix_names[msix_vec],
+ vqs[i]);
+ if (err) {
+ vp_del_vq(vqs[i]);
+ goto error_find;
}
}
return 0;
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index f53600580726..fbd2ecde93e4 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -285,6 +285,9 @@ static void *vring_get_buf(struct virtqueue *_vq, unsigned int *len)
return NULL;
}
+ /* Only get used array entries after they have been exposed by host. */
+ rmb();
+
i = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].id;
*len = vq->vring.used->ring[vq->last_used_idx%vq->vring.num].len;